Skip to content

Instantly share code, notes, and snippets.

@godDLL
Last active December 24, 2023 16:02
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save godDLL/b4a43505b0dac4f12dcd73046efae5ee to your computer and use it in GitHub Desktop.
Save godDLL/b4a43505b0dac4f12dcd73046efae5ee to your computer and use it in GitHub Desktop.
Interactive time-logging calculator on console. Kinda like pomodoro with soulver/numi inside, but in your terminal.

Time Log Fish

Download Latest v0.4  |  USAGE demo  |  HackerNews  |  Wiki/Docs  |  Bugs & Suggestions

A utility to automatically time-stamp and edit a work-log, or what have you.
It's like a task list, a "done list" that can be saved.
Has a handy calculator built-in.
demo

Plays nice with terminal themes.
Integrates with user (meaning Your's) status-line scripts. Please post your own screenshots in the comments.


Installation and Usage

This script depends on the FISH shell, as well as a decent date command.
The ANSI-colors stripping requires a sed command.

To use it copy time-log.fish anywhere in your PATH and chmod +x the script.
Run it, optionally followed by a HEADING.

Saving to File

Time Log Fish can write to a file with the !w command.
This file has all the movement and colors.

If you'd like to see the file use cat FILE.
The colors can be removed with cat FILE | time-log.fish -


To exit and stop the script use <Ctrl>-<D> (can do <Ctrl>-<C> as well).

There are more screencasts and screenshots for you in the Time Log Fish WIKI file.

Marking notes with Time-stamps

Every line in Time Log Fish is time-stamped by default.
Use / to see the difference between last time-stamp and current time.
Enter an empty line to refresh current time, and show STATUS below.
To keep note of this status line enter ++ (this does not update last time-stamp).

To enter a note without updating last time-stamp start the line with +,
or with - to replace the contents of the line above.

EDITING demo

Lines can be deleted and edited with --, and auto-stamped with -+

FISH provides line history with <Up> and <Down> for the current session only.
The standard <Alt>-<E> shortcut will bring up your EDITOR to edit the line,
save and quit to get back to Time Log Fish.

Calculations, maths

Simple math expressions =1+1= 2 are available (do a help math in FISH for more).

To use the last result in a new expression start the line with . instead of =
Going back to the result before last is done with ..

CALC demo

Use ? to summon a HELP cheat-sheet.

     <Enter> to refresh the time
  ⋯  type anything and TIME stays
 --  edit last line, replacing it
 +⋯  add a NOTE                   (default: empty line)
 -⋯  replace last NOTE      (default: delete last note)

 -+  prepend current TIME to the last line     (+- too)
 /   show time difference to the last line     (* also)
 ++  insert weekday & STATUS          (default: HH:MM.)

 =⋯  calculate and note down the result    (default: 0)
 .⋯  use last result                 (default: show it)
 ..  discard last result, use one before (or 0 if none)

 `   run MENU and edit resulting string
 !   insert result of MENU immediately

 !w  (over)write to file     (default: DATE HH:MM.plog)
     to strip ANSI coloring use `cat FILE | time-log -`

  tag: note
  mark:specific.time

For more on how to use Time Log Fish read the WIKI file.

CHANGELOG
* use - once, to remove all lines printed by ?
* changed formatting of time difference to show up as  H hrs M min
* restructured WIKI, mirrored on the new website
+ Time Log Fish now has a documentation section and a website for that
+ added a -h/--help arg, to point to website docs etc.
* general formatting improvements
+ added MENU to call custom script with ! or `
- faster, less subshell usage
* calculator changed to use = instead of :
+ see the time difference with just /
* status adding changed from just + to ++
* a + adds an empty line
+ added facility to strip ANSI colors (keeps motions tho)
+ previous line can now be time-stamped with -+
+ previous line can now be edited with --
+ calculate using last calc result with ./3
+ zero out last result with just :
+ TITLE env variable for custom command hooks
+ setting STATUS command, and ovrerriding it with ARGV
+ deleting and replacing lines interactively
+ adding lines interactively
+ refreshing TIME in prompt with Enter, runs STATUS below
+ adding STATUS as a line with just +
+ adding empty lines with +SPACE
+ writing ANSI file with !w (use cat to view)
+ tagging a line
+ back-dating HH:MM. lines
+ calculate math with :5/13
+ exit with Ctrl-C or Ctrl-D

License MIT, free to do whatever. Yours to fuck up.
general USAGE demo

TODO

- short link or domain for easy curl/wget install 
- update README screenshots, they shold make sense
- update Wiki, make asciicasts for it
- dress up and furnish the project with fish mascot
- watermark for images
- GET FEEDBACK: try HN again? Reddit? Acquaintances?
- FIXME: use manually backdated items for time diff calc when refreshing with /
- accept filename for !w
#!/usr/bin/env fish
# v0.4 gist.github.com/godDLL/b4a43505b0dac4f12dcd73046efae5ee
#
#set -g TITLE 'date +%d\ %m-%Y'
#set -g STATUS 'date +%H:%M.'
#set -g MENU 'pick -i 2 work break calls eat'
# works with the files !w writes
if test '-' = "$argv"
set -l ansi 's/'\e'\[[0-9;]*[m]//g'
while read -l N
echo -e -- "$N" |sed $ansi
end
exit
end
set -q TITLE
and set -- TITLE (eval $TITLE)
or set -- TITLE (date +%d\ %m-%Y)
set TITLE_len (string length -- " $TITLE")
set -l PLOG ## up go to end back up left white on black rst
set -a -- PLOG (echo -e -- '\e[A\e['$COLUMNS'G\e['$TITLE_len'D\e[37;40m '"$TITLE" '\e[m')
echo -- $PLOG[-1]
set -l -- ST
if test -n "$STATUS"
if test -n "$argv"
set -- ST "$argv"
else
set -- ST (eval $STATUS)
test -z "$ST"
and set -- ST (date +%H:%M.)
end
else
if test -n "$argv"
set -- ST "$argv"
test -z "$ST"
and set -- ST (date +%H:%M.)
else
set -- ST (date +%H:%M.)
end
set -- STATUS 'date +%H:%M.'
end
set -l cl '\e[K'
set -l upcl '\e[A'$cl
set -a -- PLOG (echo -e -- $cl'\e[2m' (date +%A) "$ST"'\e[m')
echo -- $PLOG[-1]
#clear
set -e ST
function pick --description 'Show a screenful of options, pick one'
if test -n "$argv[1]"
and contains -- "$argv[1]" -h --help
echo 'Usage: menu [OPTIONS] ITEM1 ITEM2 ...
Returns selected item number.
-i NUM pre-select item
-d STR menu item delimiter, default to \n
-x return code is item index, no echo
' >&2
return
else
set -l clm \e\[m
set -l sel \e\[7m
argparse 'i/item=' 'd/delim=' 'x/echo' -- $argv
test -n "$_flag_d"
and set -l NL $_flag_d
or set -l NL \n
test -n "$_flag_i"
and set -l ID $_flag_i
or set -l ID 1
set -l -- ITEM ' '{$argv}' '
set -l -- LEN (count -- $ITEM)
set -- ITEM[$ID] "$sel$ITEM[$ID]$clm"
echo -en \e\[A >&2
string join -- $NL ' '{$ITEM}' ' >&2
echo -en \e\[H >&2
while read -s -n1 -P '' -l K
switch "$K"
case ' ' '' # select
test -z "$_flag_x"
and echo -en -- $argv[$ID]
or return $ID
return
case ',' k h \[ \' # back
set ITEM[$ID] ' '$argv[$ID]' '
test 1 -lt $ID
and set ID (math -s0 $ID'- 1')
case '.' j l \] \\ # forth
set ITEM[$ID] ' '$argv[$ID]' '
test 1 -lt (math -s0 "$LEN - $ID")
and set ID (math -s0 $ID'+ 1')
end #switch
set ITEM[$ID] "$sel$ITEM[$ID]$clm"
echo -en \e\[A >&2
string join -- $NL ' '{$ITEM}' ' >&2
echo -en \e\[H >&2
end
end
end #fun
test -n "$MENU"; or set -l MENU 'pick -d \t Use "[ and ]" or "j and l"'
set -l ansi 's/'\e'\[[0-9;]*[m|K|G|A|B|C|D]//g'
set -l ripcl '\e[K\e[B\e[K\e[2A\e[K'
set -l ANS ' 0'
# use N > set R, T, P, echo & PLOG > do R, show T, suggest P
set -l P
set -l R
set -l TIME_fmt +\e\[1m'%H:%M'\e\[2m'.%S'\e\[m\
set -l -- T (date $TIME_fmt)
set -l -- EPH (date +%s)
while read -c (echo -e -- "$P") -P (echo -e -- "$R$T") -l N
# simple commands
if test 2 -ge (string length -- "$N"); and string match --invert --quiet -- '=*' "$N"
if test -z "$N"
if test -z "$P"
# don't advance line
set R '\e[A'
else
set R ''
end
set P ''
# do refresh clock
set -- T (date $TIME_fmt)
# where am i?
echo -ne -- $cl'\e[2m' (date +%A\e\[m) (eval $STATUS)'\e[m'
else if test '///' = "/$N/" -o '/*/' = "/$N/"
set P ''
set R '\e[A'
set -l -- TT (math -s0 -- '('(date +%s)' - '$EPH') /60')' min'
echo -ne -- $cl'\e[4m '$TT' \e[m'
set -- T (date $TIME_fmt)
set -e TT
else if test '/--/' = "/$N/"
set -- P (echo -e -- "$PLOG[-1]" |sed $ansi)
if test -z "$P"
set P ' '
end
set R $ripcl'\e[A'
set T ''
set -- PLOG $PLOG[1..-2]
# deleted lines are not logged
else if test '/-+/' = "/$N/" -o '/+-/' = "/$N/"
set P ''
set R ''
set -- PLOG[-1] "$T"(string trim --left -- "$PLOG[-1]")
echo -e -- '\e[A'$ripcl$PLOG[-1]
set -- EPH (date -j -f %H:%M.%S\ (echo -e -- $T |sed $ansi) +%s)
else if test '/-/' = "/$N/"
set P ''
set R $ripcl'\e[A'
set -- PLOG $PLOG[1..-2]
# deleted lines are not logged
else if test '/!/' = "/$N/"
set P ''
set R ''
echo -ne '\e[?1049h'
set -l -- G (eval $MENU)
echo -ne '\e[?1049l'
if test -n "$G"
set -a -- PLOG "$T$G"
echo -e -- '\e[A\e[10G'$G
set -- T (date-fmt t)' '
else
set -- R '\e[A'
end
else if test '/`/' = "/$N/"
set -- R '\e[A'
echo -ne '\e[?1049h'
set -l -- G (eval $MENU)
echo -ne '\e[?1049l\e'
if test -n "$G"
set -- P (echo -e -- $T$G |sed $ansi)
set -- T ''
end
else
set P ''
set R ''
if test '/../' = "/$N/"
set -- ANS $ANS[1..-2]
if test -z "$ANS[-1]"
set -- ANS ' 0'
end
set -a -- PLOG "=$ANS[-1]"
echo -e -- $ripcl$PLOG[-1]
else if test '/./' = "/$N/"
set -a -- PLOG "=$ANS[-1]"
echo -e -- $ripcl$PLOG[-1]
else if test '/++/' = "/$N/"
set -a -- PLOG (echo -e -- $cl'\e[2m' (date +%A\e\[m) (eval $STATUS)'\e[m')
echo -e -- $ripcl$PLOG[-1]
set -- T (date $TIME_fmt)
else if test '/+/' = "/$N/"
set -a -- PLOG ''
echo -e -- $ripcl
# prompt commands
else if test '/!w/' = "/$N/"
# works with `cat FILE | time-log -`
set -l FILE (date +%Y-%m\ %d\ %H-%M).plog
if touch "$FILE"
string join -- \n $PLOG \n >"$FILE"
echo -e -- $upcl"\e[3m$FILE now saved\e[m"
else
echo -e -- ' \e[1;31mErr\e[m: write to file '$FILE
end
else
# WONTFIX: don't care if this part slow, you're not running it 10K times
if test '/?/' = "/$N/" -o '/!/' = "/$N/"
echo -ne '\e[3m'
echo -e -- ' <Enter> to refresh the time
⋯ type anything and TIME stays
-- edit last line, replacing it
+⋯ add a NOTE (default: empty line)
-⋯ replace last NOTE (default: delete last note)\n
-+ prepend current TIME to the last line (+- too)
/ show time difference to the last line (* also)
++ insert weekday & STATUS (default: HH:MM.)\n
=⋯ calculate and note down the result (default: 0)
.⋯ use last result (default: show it)
.. discard last result, use one before (or 0 if none)\n
` run MENU and edit resulting string
! insert result of MENU immediately\n
!w (over)write to file (default: DATE HH:MM.plog)
to strip ANSI coloring use `cat FILE | time-log -`\n'
echo -ne -- ' tag: note\n mark:specific.time'
echo -e '\e[m\n'
else if string match --quiet -- '+*' "$N"
set -l -- M (string sub -s 2 -- "$N")
set -a -- PLOG " $M"
echo -e -- $upcl$PLOG[-1]
# added lines are logged
else if string match --quiet -- '-*' "$N"
set -l -- M (string sub -s 2 -- "$N")
set -- PLOG[-1] " $M"
echo -e -- $upcl$upcl" $M"
# overwritten lines are overwritten in log
# just a short note
else
set -a -- PLOG "$T$N"
end
if test -n "$T"
set -- EPH (date -j -f %H:%M.%S\ (echo -e -- "$T" |sed $ansi) +%s)
end
set -- T (date $TIME_fmt)
end
end
# not simple commands
else
set R ''
if string match --quiet -- '=*' "$N"
set -- N (string sub -s 2 -- "$N")
if test -z "$N"
set N ' 0'
end
set -a -- ANS ' '(math -s2 -- "$N")
set -l -- ANS_len (string length -- " =$ANS[-1]")
## dim go to end back up left bold on cyan rst
set -a -- PLOG (echo -e -- '\e[2m=\e[m'$N'\e['$COLUMNS'G\e['$ANS_len'D\e[1;46m ='$ANS[-1]' \e[m')
echo -e -- $upcl$PLOG[-1]
if test -n "$P"
set P ''
set -- T (date $TIME_fmt)
end
set -e ANS_len
else if string match --quiet -- '.*' "$N"
set -- N (string sub -s 2 -- "$N")
set -a -- ANS ' '(math -s2 -- "$ANS[-1] $N")
set -l -- ANS_len (string length -- " =$ANS[-1]")
## dim go to end back up left bold on cyan rst
set -a -- PLOG (echo -e -- '\e[2m.\e[m'$N'\e['$COLUMNS'G\e['$ANS_len'D\e[1;46m ='$ANS[-1]' \e[m')
echo -e -- $upcl$PLOG[-1]
if test -n "$P"
set P ''
set -- T (date $TIME_fmt)
end
set -e ANS_len
else if string match --quiet -- '*:*.*' "$N"
set -l -- M (string split --max 1 -- ' ' "$N")
if test 7 -le (string length -- "$M[1]")
set -a -- PLOG (echo -e -- "\e[m\e[4m$M[1]\e[m $M[2]")
else
set -- M[2] (string trim --left -- "$M[2]")
set -a -- PLOG (echo -e -- "\e[m\e[4m$M[1]\e[m $M[2]")
end
echo -e -- $upcl$PLOG[-1]
if test -n "$P"
set P ''
set -- T (date $TIME_fmt)
end
set -e M
else if string match --quiet -- '*:*' "$N"
set -l -- M (string split --max 1 -- ':' "$N")
set -- M[2] (string trim --left -- "$M[2]")
set -- M[1] (string upper -- "$M[1]")
set -l -- TT (date +%H:%M.)
## hide dim hide
set -a -- PLOG (echo -e -- "\e[8m$TT.\e[m\e[2m$M[1]\e[m\e[8m:\e[m $M[2]")
echo -e -- $upcl$PLOG[-1]
if test -n "$P"
set P ''
set -- T (date $TIME_fmt)
end
set -e M
set -e TT
else
if string match --quiet -- '+*' "$N"
set P ''
set -l -- M (string sub -s 2 -- "$N")
set -a -- PLOG " $M"
echo -e -- $upcl$PLOG[-1]
set -- T (date $TIME_fmt)
# added lines are logged
else if string match --quiet -- '-*' "$N"
set P ''
set -l -- M (string sub -s 2 -- "$N")
set -- PLOG[-1] " $M"
echo -e -- $upcl$upcl" $M"
set -- T (date $TIME_fmt)
# overwritten lines are overwritten in log
# just a note
else
if test -n "$P"
set P ''
set T ''
end
set -a -- PLOG (echo -e -- "$T$N")
if test -n "$T"
set -- EPH (date -j -f %H:%M.%S\ (echo -e -- $T |sed $ansi) +%s)
end
set -- T (date $TIME_fmt)
end
end # string match commands
end # if len < 2
end

Basic editing and the Calculator

How do I exit Time Log Fish?

Press <Ctrl>-<C> or <Ctrl>-<D> at any time to stop the script. You get to keep the output on your terminal,
and if you want to continue from where you stopped you can use - to delete a couple of lines
that it takes to launch Time Log Fish again.

What can the Calculator do?

How do I edit or delete a line?

Can it tell me how long something took/was?

Is there built-in help, or cheat-sheet?

Where is history kept? For how long?

How do I edit the current line in my EDITOR?

Making it yours, and making it pretty

Why does it look different in every screenshot that I see?

This script uses your terminal's bold, dim, underline, italics and reverse capabilities.
All of those are widely supported by terminal emulation software, and most of them are in fonts.

This makes Time Log Fish adapt to your terminal color theme nicely.
The way colors are used in Time Log Fish should not interfere with that.

How do I set custom HEADING as an opening line of my log?

Just start it followed by the heading, no need to make it one long string:

time-log Hello, world\!
time-log "Hello, world!"

Time Log Fish does not have many command-line parameters. In fact there's only one right now,
and it's - used for stripping ANSI colors from the text passed to the standard input stream.

How to modify the STATUS command that is run upon time refresh?

If you want to use your own scripts for STATUS or TITLE you can do so:

STATUS='df -h / |tail -1 |cut -d" " -f13' \
TITLE=date\ +%Y/%d/%m \
time-log.fish HEADING

Screen Shot 2021-11-06 at 20 37 08

TITLE is the command being run preceeding your logging of time, top-right in the screenshot above.

STATUS is run whenever you press <Enter> submitting an empty line to Time Log Fish.
It can be saved in your log with ++.

How do I use the auto-fill MENU command?

Why do arrow keys not work in MENU, how do I choose items?

There is currently no way to capture arrow keys in the Fish read built-in. You can of course use your own menu command instead of the pick ITEMS… that comes with Time Log Fish. Take a look at fzf, it is glorious.

The pick function uses [ and ] or j and l to select and <Enter> or <Space> for finalizing choice.

What can I do with the plog file that is saved?

F.A.Q.

Is there a web-browser version of this script?

Not right now.

I found this useful in my life. I'd like to say thanks!

Please do, down in the comments; or just buy me a coffee/beer.

@godDLL
Copy link
Author

godDLL commented Nov 5, 2021

License MIT, free to do whatever. Yours to fuck up.
asciinema.org/a/447537

@godDLL
Copy link
Author

godDLL commented Nov 5, 2021

Version 0.1 screenshots:

Screen Shot 2021-11-05 at 09 53 29 copy
Screen Shot 2021-11-05 at 09 53 11 copy

@godDLL
Copy link
Author

godDLL commented Nov 5, 2021

v0.1 bug fixes watch cast

+ calculate math with :
* full weekday name in STATUS
* slow default STATUS line now faster

@godDLL
Copy link
Author

godDLL commented Nov 5, 2021

v0.2 bug fixes

+ calculate using last result with .
* zero out last result with just :

calc

@kseistrup
Copy link

Fish's set_color command will output relevant escape sequences for changing colours and other attributes (and resetting them). Use set_color -c to see the colours it recognizes.

@godDLL
Copy link
Author

godDLL commented Nov 6, 2021

@kseistrup Correct.
It is also dog-slow for what I'd be using it for.

And I don't need the help in manipulating my terminal as to the modes, colors, pages etc.
Which it can't do anyway.
So no, not doing that.
👎

EDIT: eh, I did not mean to come over so stern.
There is nothing wrong with set_color except for how slow it is, really.
I don't even use it in my PROMPTs.

@kseistrup
Copy link

That's fine, I never expected you to — just thought I'd mention it.

Personally, I would never call set_color every time I needed it. Rather, I would e.g. set GREEN (setcolor green) in the beginning of the script and then refer to $GREEN everywhere else. Has the potential of making the code more legible.

I use set_color in some of my own fish scripts, and I disagree with the “dog slowness”.

@godDLL
Copy link
Author

godDLL commented Nov 7, 2021

Oh, it is so good to actually meet someone you could comfortably disagree with. I exactly started doing what you describe, than ran that 10K times, and had to get coffee. Then it happened again, in a different script I wrote. So, how was that saying, three times makes an idiot of me, or whatever to that effect.
I am of the opinion that FISH itself is way slow. If only it wasn't so convenient I'd switch away to, eh, I dunno, I'd whip something up.
❤️

UPDATE: looking for iffy sections I found exactly 5 lines to comment where it's all ANSI escapes, should be very readable now. Thanks.
UPDATE: removed one. But he's not starring this gist no more, so whatever.

@godDLL
Copy link
Author

godDLL commented Nov 7, 2021

v0.3 refinements to the UI, bug fixes

new CALC demo
new EDITING demo
new USAGE demo

* calculator changed to use = instead of :
+ see the time difference with just /
* status adding changed from just + to ++
* a + adds an empty line
+ added facility to strip ANSI colors (keeps motions tho)
+ previous line can now be time-stamped with -+
+ previous line can now be edited with --

(Yes, I know that the maths on main screenshot don't make sense, I'll be doing something about taht.)

@godDLL
Copy link
Author

godDLL commented Nov 8, 2021

Added a WIKI file, now that the feature-set and scope of this script has stabilized enough for that.

I might just not be adding any more features, it all feels well-rounded right now. Quite.

@godDLL
Copy link
Author

godDLL commented Nov 14, 2021

v0.4 added menu for your autofill

new MENU demo will appear with imminent v0.5 as part of documentation effort

* general formatting improvements
+ added MENU to call custom script with ! or `
- faster, less subshell usage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment