├── .gitignore ├── visuals ├── icon.png └── ascii_logo.txt ├── binaries └── codetimer ├── scripts └── compile_binary_deb.sh ├── install.sh ├── README.md └── timer.sh /.gitignore: -------------------------------------------------------------------------------- 1 | art.txt 2 | *.sh.x.c 3 | .gitignore -------------------------------------------------------------------------------- /visuals/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdallah-sameh-ragab/code-timer/master/visuals/icon.png -------------------------------------------------------------------------------- /binaries/codetimer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdallah-sameh-ragab/code-timer/master/binaries/codetimer -------------------------------------------------------------------------------- /scripts/compile_binary_deb.sh: -------------------------------------------------------------------------------- 1 | sudo apt-get install libc6-dev 2 | sudo apt-get install shc 3 | sudo shc -f timer.sh -o binaries/codetimer 4 | -------------------------------------------------------------------------------- /visuals/ascii_logo.txt: -------------------------------------------------------------------------------- 1 | ______ ______ _____ ______ 2 | /\ ___\ /\ __ \ /\ __-. /\ ___\ 3 | \ \ \____ \ \ \/\ \ \ \ \/\ \ \ \ __\ 4 | \ \_____\ \ \_____\ \ \____- \ \_____\ 5 | \/_____/ \/_____/ \/____/ \/_____/ 6 | ______ __ __ __ ______ ______ 7 | /\__ _\ /\ \ /\ "-./ \ /\ ___\ /\ == \ 8 | \/_/\ \/ \ \ \ \ \ \-./\ \ \ \ __\ \ \ __< 9 | \ \_\ \ \_\ \ \_\ \ \_\ \ \_____\ \ \_\ \_\ 10 | \/_/ \/_/ \/_/ \/_/ \/_____/ \/_/ /_/ 11 | 12 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | INSTALL_DIR="/opt/codetimer" 3 | BINARY_INSTALL_DIR="/usr/local/bin" 4 | CURRENT_DIR="$(pwd)" 5 | 6 | if [ -d "$INSTALL_DIR" ]; 7 | then 8 | rm -r $INSTALL_DIR 9 | fi 10 | sudo mkdir $INSTALL_DIR 11 | 12 | sudo cp "$CURRENT_DIR/timer.sh" $INSTALL_DIR/ 13 | sudo chmod +x "$INSTALL_DIR/timer.sh" 14 | 15 | sudo cp -R "$CURRENT_DIR/visuals/" "$INSTALL_DIR/" 16 | sudo cat > /usr/share/applications/codetimer.desktop << EOF 17 | [Desktop Entry] 18 | Version=1.0 19 | Type=Application 20 | Name=Code Timer 21 | Comment=VS Code time tracker. 22 | Exec=bash $INSTALL_DIR/timer.sh 23 | Icon=$INSTALL_DIR/visuals/icon.png 24 | Terminal=true 25 | StartupNotify=false 26 | EOF 27 | 28 | sudo chmod u+x /usr/share/applications/codetimer.desktop 29 | 30 | sudo cp "$CURRENT_DIR/binaries/codetimer" $BINARY_INSTALL_DIR/ 31 | sudo chmod +x "$BINARY_INSTALL_DIR/codetimer" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The CodeTimer - VS Code Session time messurement tool. 2 | The CodeTimer is a simple tool built in bash script that tracks your time spent on vs code. the tool can detect when you are actively using vs code and when you are idling or using different applications. 3 | when inactivity is detected the tool gives you a duration called Buffer Time to return back to vs code before it stops counting time as "coding time". 4 | Buffer Time can be set using option -b and the its default duration is 300s or 5m. 5 | 6 | ## Installation 7 | 8 | Simply run the installation script. 9 | 10 | sudo ./install.sh 11 | 12 | Make sure the script is executable by running the following command before running the installation script. 13 | 14 | chmod +x install.sh 15 | **Please note:** that the installation uses a pre-compiled binary included in the "binaries" folder, 16 | However you can compile your own binary using the script included in the "scripts" folder. make sure to replace the included binary with your own in the "binaries" folder before running the installation script. 17 | 18 | 19 | ## Usage 20 | 21 | Simply run `codetimer [-option ] [-option]` on the terminal. 22 | You can use any of these **options:** 23 | 24 | - ` -b [seconds]` Set the buffer time. 25 | - ` -c ` Run VS Code alongside the timer (if it wasn't already running). 26 | - ` -h ` Show instructions. 27 | -------------------------------------------------------------------------------- /timer.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | GUIDE=" 3 | Description: 4 | The Code Timer. 5 | Simple script to keep track of your coding time spent on VS Code. 6 | 7 | Requirements: 8 | pidof, xdotool, xargs 9 | 10 | USAGE: 11 | $0 [-c] [-b seconds] 12 | 13 | OPTIONS: 14 | -b [OPTIONAL] Set buffer time (in seconds) default value is 300s. 15 | -c [OPTIONAL] Launces vs code alongside the timer. 16 | -h Help. 17 | 18 | **buffer time is the duratuion given to the user to return to VS Code 19 | before the timer stops recording coding time and move on to rest time.** 20 | " 21 | 22 | BRED='\033[1;91m' 23 | LRED='\033[1;31m' 24 | BGREEN="\033[1;92m" 25 | LGREEN='\033[1;32m' 26 | BBLUE="\033[1;94m" 27 | LBLUE='\033[1;34m' 28 | LYELLOW='\033[1;33m' 29 | BYELLOW='\033[1;93m' 30 | GRAY='\033[1;30m' 31 | LGRAY='\033[0;37m' 32 | BWHITE='\033[1;97m' 33 | LCYAN="\033[1;36m" 34 | BCYAN="\033[1;96m" 35 | MAGENTA="\033[1;95m" 36 | LMAGENTA="\033[1;35m" 37 | NC='\033[0m' 38 | 39 | LAUNCH_CODE=false 40 | CODE_RUNNING=false 41 | CODE_ACTIVE=false 42 | RECORDING=false 43 | PAUSED=false 44 | BUFFERING=false 45 | CODE_TIME=0 46 | BUFFER_LIMIT=300 47 | BUFFER_TIME=0 48 | IDLE_TIME=0 49 | SHOW_PROMPT=false 50 | SHOULD_RESET=false 51 | SHOULD_QUIT=false 52 | 53 | 54 | run(){ 55 | check_requirements 56 | iscoderunning 57 | run_code 58 | while :; do 59 | live_view 60 | update 61 | listen_for_keys 62 | done 63 | } 64 | 65 | check_requirements(){ 66 | if ! command -v code &> /dev/null 67 | then 68 | printf "${LRED}ERROR:${NC} VS Code is not installed in your system.\n" 69 | printf "${LYELLOW}TRY:${NC} sudo apt install code\n" 70 | exit 71 | elif ! command -v pidof &> /dev/null 72 | then 73 | printf "${LRED}ERROR:${NC} pidof is not installed in your system.\n" 74 | printf "${LYELLOW}TRY:${NC} sudo apt install pidof\n" 75 | exit 76 | 77 | elif ! command -v xdotool &> /dev/null 78 | then 79 | printf "${LRED}ERROR:${NC} xdotool is not installed in your system.\n" 80 | printf "${LYELLOW}TRY:${NC} sudo apt install xdotool\n" 81 | exit 82 | elif ! command -v xargs &> /dev/null 83 | then 84 | printf "${LRED}ERROR:${NC} xargs is not installed in your system.\n" 85 | printf "${LYELLOW}TRY:${NC} sudo apt install xargs\n" 86 | exit 87 | fi 88 | } 89 | 90 | ispidof() { 91 | PIDS=$(pidof $2) 92 | STRIPPED_PIDS=$(echo $PIDS | xargs) 93 | if [ -z "${STRIPPED_PIDS}" ] ;then 94 | CODE_RUNNING=false 95 | CODE_ACTIVE=false 96 | return 97 | else 98 | CODE_RUNNING=true 99 | fi 100 | INPUT=$(echo $1 | xargs) 101 | read -a PIDS_LIST <<< "$PIDS" 102 | for PID in "${PIDS_LIST[@]}"; 103 | do 104 | if [ "$PID" = "$INPUT" ]; then 105 | CODE_ACTIVE=true 106 | return 107 | fi 108 | done 109 | CODE_ACTIVE=false 110 | return 111 | } 112 | 113 | iscoderunning(){ 114 | CURRENT_PID=$(xdotool getwindowfocus getwindowpid); 115 | ispidof $CURRENT_PID code 116 | } 117 | update(){ 118 | iscoderunning 119 | if ! $CODE_RUNNING || $SHOW_PROMPT;then 120 | return 121 | fi 122 | if ($CODE_ACTIVE);then 123 | RECORDING=true 124 | CODE_TIME=$(($CODE_TIME + $BUFFER_TIME)) 125 | BUFFER_TIME=0 126 | BUFFERING=false 127 | else 128 | if $RECORDING;then 129 | RECORDING=false 130 | BUFFERING=true 131 | elif $BUFFERING;then 132 | BUFFER_TIME=$(($BUFFER_TIME + "1")) 133 | if [ $BUFFER_TIME -gt $BUFFER_LIMIT ];then 134 | BUFFER_TIME=0 135 | BUFFERING=false 136 | fi 137 | else 138 | IDLE_TIME=$(($IDLE_TIME + "1")) 139 | fi 140 | fi 141 | count 142 | } 143 | count(){ 144 | if ($RECORDING);then 145 | CODE_TIME=$(($CODE_TIME + "1")) 146 | fi 147 | } 148 | live_view(){ 149 | clear 150 | render_art 151 | if ! $CODE_RUNNING;then 152 | printf "${LRED} VS CODE IS NOT RUNNING ${BWHITE}CLICK [C]${LRED} TO LAUNCH IT\n${NC}" 153 | elif $PAUSED;then 154 | printf "${BRED} TIMER PAUSED\n${NC}" 155 | elif $CODE_ACTIVE;then 156 | printf "${BGREEN} VS CODE IS ACTIVE [CODING]\n${NC}" 157 | elif $BUFFERING;then 158 | printf "${BYELLOW} VS CODE IS NOT ACTIVE [IDLING IN $(($BUFFER_LIMIT - $BUFFER_TIME))s]\n${NC}" 159 | else 160 | printf "${BRED} VS CODE IS NOT ACTIVE [IDLE]\n${NC}" 161 | fi 162 | 163 | printf "${BBLUE} CODING TIME:${BWHITE} $(date -d@$CODE_TIME -u +%H:%M:%S)${NC}\n" 164 | printf "${BCYAN} IDLE TIME:${BWHITE} $(date -d@$IDLE_TIME -u +%H:%M:%S)${NC}\n" 165 | 166 | printf " 167 | ${BWHITE} Controls: 168 | ${LMAGENTA}[${BYELLOW}P${LMAGENTA}]${NC}ause/resume 169 | ${LMAGENTA}[${BYELLOW}R${LMAGENTA}]${NC}eset 170 | ${LMAGENTA}[${BYELLOW}Q${LMAGENTA}]${NC}uit\n" 171 | if ! $CODE_RUNNING;then 172 | printf " ${LMAGENTA}[${BYELLOW}C${LMAGENTA}]${NC}ode - Run VS Code\n" 173 | fi 174 | 175 | if ! $CODE_RUNNING;then 176 | printf "${BYELLOW}\n Hint:${LGRAY} run${BWHITE} $0 -c${LGRAY} to launch vs code alongside the timer.\n${NC}" 177 | fi 178 | if $SHOW_PROMPT;then 179 | printf "\n${BYELLOW} Are you sure ? ${NC}[${BRED}Y${NC}]es or [${BGREEN}N${NC}]o\n${NC}" 180 | fi 181 | 182 | } 183 | render_art(){ 184 | LOCAL_FILE="visuals/ascii_logo.txt" 185 | INSTALLATION_FILE="/opt/codetimer/visuals/ascii_logo.txt" 186 | if [[ -f "$LOCAL_FILE" ]]; then 187 | FILE=$LOCAL_FILE 188 | elif [[ -f "$INSTALLATION_FILE" ]]; then 189 | FILE=$INSTALLATION_FILE 190 | else 191 | return 192 | fi 193 | while IFS= read -r LINE 194 | do 195 | echo "$LINE" 196 | done < "$FILE" 197 | } 198 | 199 | listen_for_keys(){ 200 | 201 | PRE_SEC=$(date +%s) 202 | 203 | read -r -s -t .$((10**9-10#$(date +%N))) -n 1 input 204 | 205 | if [[ $input = "q" ]] || [[ $input = "Q" ]]; then 206 | if ! $SHOW_PROMPT;then 207 | SHOW_PROMPT=true 208 | SHOULD_QUIT=true 209 | return 210 | fi 211 | elif [[ $input = "r" ]] || [[ $input = "R" ]]; then 212 | if ! $SHOW_PROMPT;then 213 | SHOW_PROMPT=true 214 | SHOULD_RESET=true 215 | return 216 | fi 217 | elif [[ $input = "p" ]] || [[ $input = "P" ]]; then 218 | if $PAUSED;then 219 | PAUSED=false 220 | else 221 | PAUSED=true 222 | return 223 | fi 224 | P_SEC=$C_SEC 225 | elif [[ $input = "y" ]] || [[ $input = "Y" ]]; then 226 | if $SHOW_PROMPT;then 227 | if $SHOULD_RESET;then 228 | SHOW_PROMPT=false 229 | SHOULD_RESET=false 230 | reset 231 | return 232 | elif $SHOULD_QUIT;then 233 | SHOW_PROMPT=false 234 | SHOULD_QUIT=false 235 | quit 236 | fi 237 | fi 238 | elif [[ $input = "n" ]] || [[ $input = "N" ]]; then 239 | if $SHOW_PROMPT;then 240 | SHOW_PROMPT=false 241 | SHOULD_RESET=false 242 | SHOULD_QUIT=false 243 | return 244 | fi 245 | elif [[ $input = "c" ]] || [[ $input = "C" ]]; then 246 | if ! $CODE_RUNNING;then 247 | LAUNCH_CODE=true 248 | run_code 249 | # break 250 | fi 251 | fi 252 | 253 | C_SEC=$(date +%s) 254 | if (( $PRE_SEC == $C_SEC )); then 255 | sleep .$((10**9-10#$(date +%N))) 256 | fi 257 | } 258 | 259 | reset(){ 260 | CODE_TIME=0 261 | IDLE_TIME=0 262 | } 263 | 264 | quit(){ 265 | exit 266 | } 267 | 268 | run_code(){ 269 | if $LAUNCH_CODE && ! $CODE_RUNNING; then 270 | clear 271 | render_art 272 | printf "${LYELLOW} LAUNCHING VS CODE ... \n${NC}" 273 | code 274 | while ! $CODE_RUNNING; 275 | do 276 | iscoderunning 277 | sleep 1 278 | done 279 | fi 280 | } 281 | 282 | if [ $1 = "--help" ];then 283 | echo "$GUIDE" 284 | exit 285 | fi 286 | 287 | while getopts "cb:h" arg; do 288 | case $arg in 289 | b) 290 | BUFFER_LIMIT=$OPTARG 291 | ;; 292 | c) 293 | LAUNCH_CODE=true 294 | ;; 295 | h) 296 | echo "$GUIDE" 297 | exit 298 | ;; 299 | esac 300 | done 301 | 302 | run 303 | --------------------------------------------------------------------------------