masukomi / hey_3 Goto Github PK
View Code? Open in Web Editor NEWHey! An Interruption and Time Tracking Command line app.
Home Page: https://interrupttracker.com/
License: Other
Hey! An Interruption and Time Tracking Command line app.
Home Page: https://interrupttracker.com/
License: Other
It's not uncommon to stop some work and restart it later in the day (or the next day)
given the name of a project we should be able to easily "restart" work on it by creating a new timer with the same tags. The idea being you're "restarting" work on that project.
proposed interface
hey restart @project
It should error gracefully, if the name doesn't correspond to any known project.
it should use the same tags associated with the last event for this project.
variant
hey restart
will just restart whatever the last event was.
originated in this comment by @codesections
Killing projects is dangerous for anyone using this for billing purposes.
As such i think that there should be a -f
/ --force
option for this. If the flag isn't passed then the project is actually just archived. This is a personal time tracker so the amount of data we're talking about is negligible and not going to cause anyone problems
this, of course, means we need a way to see a list of "archived" projects...
I'm thinking maybe a hey archives
command which would, initially, just list archived projects, but if we decide to archive people instead of deleting it could have a section for them too.
and then a way to unarchive a project:
hey unkill project <name>
? π€ I'm unsure about unkill
vs unarchive
I don't want to do a hey kill project <x>
AND hey archive project <x>
because it's too easy to move fast and accidentally do the dangerous one. really deleting should require the extra thought / effort of adding --force
hey delete <numeric id>
Hey is fairly slow to start up. Even on a fairly decent desktop, it routinely takes nearly a second to launch, even for simple commands such as displaying the USAGE
message. (Testing with hyperfine shows a startup time of 832ms (Β±16ms)).
Some of this is, unfortunately, a Raku problem β even "Hello world!" Raku programs take ~100ms to start. But it's definitely possible to start up a lot faster than Hey is right now; for example, zef
displays it usage message in ~250ms. And, for interactive CLI use, the difference between ΒΌ second and ΒΎ second feels huge (at least in my highly subjective experience).
I'm not 100% sure of the best fix, but I suspect that moving logic (and module loading) out of bin/hey
would be a good place to start.
Currently when you stop a timer it says something like this
Stopped at Sun, 03:25 PM
it should say something like this
Stopped at Sun, 03:25 PM - 2hr 3min
I find i generally don't want multiple timers to be able to run at the same time, but I can see value in the feature, so I don't want to get rid of it.
Instead i think i want to add a new metadata field to toggle "single timer mode"
in single timer mode the following behavior would be exhibited
starting 1 timer would stop a running timer at the same moment (or maybe prior second), and print out the ids of both. Something like:
stopped: @foo (123) after 22 minutes
started: @bar at 11:22
beta 8 code, but i suspect it has existed all along.
The line in question is say $table
which is an instance of Prettier::Table
. I initially thought this was a bug in Prettier::Table but now I'm not so sure, because the demo.raku file over there does say $table
and can be piped without issue.
Failed to write 2048 bytes to filehandle: Broken pipe
in sub display-timers-as-table at /Users/masukomi/workspace/Hey/lib/Hey/Timer.rakumod (Hey::Timer) line 90
in sub generate-log at bin/hey line 408
in sub MAIN at bin/hey line 211
in block <unit> at bin/hey line 49
latest commit is
commit 738ea03b621ceb7ca04ecedf8fed3996ed7faa2f (HEAD -> beta_8, origin/beta_8)
Author: masukomi <[email protected]>
Date: Sat Dec 31 18:01:05 2022 -0500
summarized timers now say duration in table title
backdating is tricky without a good way to "freeze time"
The DB uses epoch time stamps to record time (because SQLite doesn't have a native concept of Dates or Times... at least not as far as a data type).
We need tests that confirm that starting & stopping of a task, and the creation of interruptions using the relative and absolute formats
Examples:
hey start at 4:30 @proj +task
hey stop at 5:30
hey bob at 13:50
hey bob at 1:51
hey start 4 minutes ago
hey stop 3 minutes ago
The problem is that without the ability to freeze time it becomes difficult to test the time you're expecting in the db. You have to start testing for ranges. For example, create the thing, get the current epoch time, and then test that the started_at
column contains a number within 2 seconds of the current epoch time you recorded.
This is because you could create a thing, and in the millisecond between creation and reading you've crossed into the next second, and now the numbers aren't the same.
So, we a new assert
function. I've filed a feature request ticket against bash_unit.
Once we have / create that then we can do the simple math of taking the current epoch time, subtracting N minutes worth of seconds, and comparing that to the backdated time shoved in the db.
currently saying hey stop
will stop the most recently started timer. This is problematic if you have automations starting timers and unclear when you didn't realize you had multiple running.
request:
hey stop at 3:00
would ask you for an ID and then be invoked as if you ran hey stop <id> at 3:00
It'd be nice to be able to configure things, such as when the start of the day is. Many of us work past midnight, and consider it part of the prior day's work. So, it'd be nice to have the logging use our preferred "start of day" time.
There should be a config file in $XDG_CONFIG_HOME/hey/config.toml
(or similar) that allows users to specify that time. I think that file should probably be TOML, but am open to suggestions. Just not YAML because way too many developers hate YAML. :/
The summarize functionality (e.g. hey summarize timers 1 day
) doesn't correctly handle overlaps. the math is wrong and results in overlapping timers causing an increase in unaccounted time.
β― hey log 1 day
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β All Timers β
βββββββ¬βββββββββββββββββββββ¬βββββββββββββββ¬βββββββββ¬ββββββββββββββ¬βββββββββββββββββββββββββββββ€
β ID β Started β Ended β Total β Projects β Tags β
βββββββΌβββββββββββββββββββββΌβββββββββββββββΌβββββββββΌββββββββββββββΌβββββββββββββββββββββββββββββ€
β 384 β Mon 01/30 08:31 AM β Mon 09:32 AM β 1h49s β daily_todos β unwanted β
β 385 β Mon 01/30 09:33 AM β Mon 10:51 AM β 1h19m β eating β breakfast, required, smile β
β 386 β Mon 01/30 10:01 AM β Mon 10:51 AM β 50m53s β daily_todos β meh, unwanted β
β 387 β Mon 01/30 10:52 AM β Mon 11:20 AM β 28m33s β daily_todos β unwanted β
βββββββ΄βββββββββββββββββββββ΄βββββββββββββββ΄βββββββββ΄ββββββββββββββ΄βββββββββββββββββββββββββββββ
resulted in this summary
β― hey summarize timers 1 day
βββββββββββββββββββββββββββββ
β 1 day Summaryβ¦ β
ββββββββββββββββ¬βββββββββββββ€
β Project β Total Time β
ββββββββββββββββΌβββββββββββββ€
β daily_todos β 2h20m β
β eating β 1h19m β
β βββββββββββ β βββββββ β
β Allβ¦ β 3h39m β
β Unaccountedβ¦ β 49m50s β
ββββββββββββββββ΄βββββββββββββ
but when I modified the end of timer 385 (eating) such that it no longer overlapped and went too long it decreased the unaccounted time,
β― hey summarize timers 1 day
βββββββββββββββββββββββββββββ
β 1 day Summaryβ¦ β
ββββββββββββββββ¬βββββββββββββ€
β Project β Total Time β
ββββββββββββββββΌβββββββββββββ€
β daily_todos β 2h20m β
β eating β 27m β
β βββββββββββ β βββββββ β
β Allβ¦ β 2h47m β
β Unaccountedβ¦ β 1m45s β
ββββββββββββββββ΄βββββββββββββ
Mostly this is just a case of the algorithm being too simple and assuming none of the timers overlap and thus their total seconds can be summed without issue.
I want to be able to type min
and mins
instead of minute
or minutes
and hr
or hrs
instead of hour
or hours
This would be adding those to the list in utilities and adding them to the place where it checks if you're using a duration that's shorter than "days".
tried to kill by id (couldn't remember if i'd added support for that - see #37 ) got this as a result.
there should be no stack trace after the error message.
1202 wasn't found. Maybe they know what you're planning!
in sub unwrap at /Users/masukomi/.rakubrew/versions/moar-2022.12/share/perl6/site/sources/E2EB282798A7D4CB4E849B977867B774BBD41E92 (Definitely) line 235
in sub MAIN at /Users/masukomi/.rakubrew/versions/moar-2022.12/share/perl6/site/resources/E470A641173EDC7592C583B0792D50B5BC0EC783 line 358
in block <unit> at /Users/masukomi/.rakubrew/versions/moar-2022.12/share/perl6/site/resources/E470A641173EDC7592C583B0792D50B5BC0EC783 line 59
in sub MAIN at /Users/masukomi/.rakubrew/versions/moar-2022.12/share/perl6/site/bin/hey line 3
in block <unit> at /Users/masukomi/.rakubrew/versions/moar-2022.12/share/perl6/site/bin/hey line 1
hey nevermind
shouldn't be restricted to timers.
it should get rid of the last event regardless of if it was a timer or an interruption.
HOWEVER,
in both cases it should remove one-off metadata.
if i type hey runnnig
instead of hey running
(typo) it's going to create an interruption event from a new person named runnnig
. I want to hey nevermind
and eliminate that event, but ALSO see that runnnig
(the person) only existed in the context of that one event and get rid of it.
Similarly if the timer is associated with a project that has no other associated events the project should be deleted. Ditto for tags.
I want a fast and easy way to address bad data resulting from typos if i notice them immediately after creation.
addressing them later is a trickier task.
nevermind
functionality should be expanded to encompass interruptionsnevermind
functionality should delete records that are associated with the "bad" event IF they aren't tied to any other event.I'm using the Time::Duration
library to generate the duration text in the logs.
it was outputting something like "2 hours and 23 minutes". In Beta 5 it's outputting "2h23m" That's a bit... too concise for my taste.
I'd like "2hr 23min".
I think the best solution is to make a PR against Time::Duration and then use that, but barring/until that we can just shove it into Utilities.rakumod
I should be able to associate a project with some default tags.
that way when i say hey start @foo
i don't have to say hey start @foo +tags +foo +always +has
and / or don't have to remember to add them in afterwards.
Not sure how to handle this at the db level. π€
Currently there's a "Started" column which contains something like this 12/30 08:23 AM
and a "Total" column which contains something like this 1h19m
I keep finding that i need to start a timer after the fact, but figuring out when involves mental math to calculate what time the prior timer stopped.
This ticket proposes a "Stopped" column that contains something like 09:30 AM
. We know the day from "Started" and it's rarely going to be multi-day or crossing day boundary. When it does i think the context of the "Total" will be plenty.
Note: this does overlap in concept with the need for the ability to start a timer at the end of the prior timer ( Issue #14 ) but i think this is valuable for other reasons too.
I would like to be able to tell hey to start a new timer that starts immediately after the last timer ended.
So,
59
minutes the new one should start at 0
minutes. Ignore secondsUX something like
hey start after [last|id] @foo +bar
no time adjustment would be supported in this interface.
hey start 4 minutes ago @project +tag
is all well and good, but it'd also be nice to be able to say hey start @project +tag 4 minutes ago
or hey start @project 4 minutes ago +tag
Ditto for the at 4:00
style of backdating.
With a little bit of creative Regexp we can detect the time strings, and then extract them from the arguments list regardless of where they are.
hey summarize @foo 1 day
will output a table showing how how much time was spent on the @foo
project, regardless of tags, for the given duration.
When the duration is "day" or larger and the number is > 1 it should have a line for each block of that duration and a line for the total spent across the reporting time.
So, if we said hey summarize @foo 4 weeks
We'd see something like this
week starting | time spent |
---|---|
11/28/22 | 3hrs 42mins |
12/05/22 | 14hrs 3 mins |
12/12/22 | 5hrs 16 mins |
12/26/22 | 0mins |
Totals | 24hrs 1 min |
If we said hey summarize @foo 40320 seconds
(4 weeks) we'd see something like this (because seconds < days )
Total for 40320 seconds |
---|
24hrs 1 min |
We should be able to do the same for tags +bar
or combinations thereof (@foo +bar). The latter being only reporting on the foo
project where entries also had the bar
tag.
It'd be great if we could do specify multiple projects and multiple tags to get really really specific but that query might be a pain in the butt.
hey log-json <duration>
Basically the same thing as hey log <duration>
but it would output a JSON array with containing a denormalized object / Hash for each event that looked like this.
events that had not ended /would/ be included, but would have null
in the ended_at
field.
{
"type": "event",
"id": 12345,
"created_at": "<ISO-8601 string>",
"updated_at": "<ISO-8601 string>",
"started_at": "<ISO-8601 string>",
"ended_at": "<ISO-8601 string>",
"total_seconds": 12345,
"projects": [ "foo", "bar"],
"tags": ["baz", "beedle"]
}
we have the id of the timer / interrupt from the logs. We just need a command that lets us say we're editing the start or end.
Note that Timers and Interruptions are both records in the events table so the ids don't overlap. We can, in theory, use the same command for both. That way we wont need "hey edit timer 4 start at 4:44" and "hey edit interrupt 5 start at 5:55" we can just have one "hey edit event start at 6:46" as well as a "end" version.
The "end" version should error if the id corresponds to an interruption.
Events have a type
of interruption
or timer
.
So, the request is for a new "edit" command in hey which lets us do the following, and updates the db as you'd expect.
hey edit 4 start at 5:30
hey edit 4 start 4 minutes ago
hey edit 4 end at 6:30
hey edit 4 end 12 minutes ago
Most of the code for this already exists and can be reused.
Note: technically we already have half of this. We can say hey stop 4 at .....
on a timer that's already been stopped and it'll change the stop time.
We really need Raku unit tests for the time related functions in Utilities
We don't have an equivalent of timecop in Raku AFAIK so, we'll have to modify anything that's comparing the current date to a past date to take an optionalDateTime
parameter (named now
?) if it isn't already.
This is somewhat thinking-out-loud not "what must happen". The most important thing being that the resulting code is testable, and easy to wrap your head around.
extract-time-adjustment-args
needs to be modified to return a hash, and the multiple places that interact with its output need to be modified accordingly
the hash contents should address the following questions
as this method is just about "get the args out of the input" it shouldn't be doing any calculations based on those.
I think then we might want to introduce an intermediary method(s) that expands on that hash. and answers the following questions
Many of these already exist and could just be leveraged to shove their output into the hash.
after all that we can just take the contents of the hash, shove them into a new DateTime
object.
unit test the π© out of whatever comes out of that.
hey kill timer <id>
and hey summarize timers
use multi-word commands, but hey log-interrupts
uses a hyphen. It seems like hey should pick one style and stick to it.
(This is very minor, but it's easier to change now).
I don't have strong feelings on which style to adopt, but I mildly prefer the hyphenated version (which IME is more common).
add tab completion of projects and tags
start @project_<tab>
should
the same behavior should apply to tags. eg. hey start @project +wal<tab>
Example tab-completion code via Linenoise. I'm currently unsure how to handle the printing of suggestions that then go away.
#!/usr/bin/env raku
use Linenoise;
my @commands = <help quit list get set>;
sub find-last-word(Str $line) {
return $line.subst(/.*? \s? $<lw>=(\S+) $/, {"$<lw>"} );
}
linenoiseSetCompletionCallback(-> $line, $c {
my ( $last-word ) = find-last-word($line);
for @commands.grep(/^ "$last-word" /).sort -> $cmd {
linenoiseAddCompletion($c, $cmd);
}
});
my $line = linenoise '> ';
# while (my $line = linenoise '> ').defined {
say "got a line: $line";
# }
This is a high level ticket to work out ideas for generating data for invoicing as I'm about to need it.
I can see 2 main desires here:
XDG_HOME_CONFIG
and a file is generated based off of that.Setting aside how we export it, I think we need to contemplate what we report.
I think we need to be able to specify a time range, and one with no end date is just "since X"
Output options:
I think there's an implication here about billing, and that one shouldn't be able to bill for the same time unit twice. This implies that we should add an "invoiced" flag. But, what does it mean if you try and edit a thing that's been invoiced. "Are you sure? This has been invoiced" I'm thinking there are times when you'll generate an invoice, go 'oh crap', edit something, and then regenerate it, so they should be editable. Maybe there's a --force
flag when editing the time on an invoiced entry. Without it it goes "Oy! this has been invoiced. Try again with --force if you really want to be editing this." Or something like that.
π€ I wonder if there are any services with APIs that we could push to, and if it'd be worth the effort to support them.
proposed interface
hey rename project <old name> <new name>
Behind the scenes this would just need to do a
UPDATE projects SET name = 'new-name'
WHERE name = 'old-name`;
Project names should be unique, and can't be "archived", so this change should be safe without other constraints.
you should be able to "archive" a project such that it no longer shows up in the list of hey projects
because if we're going to build autocomplete tools and GUIs they shouldn't be asking you to choose from projects you no longer care about.
if you start a new timer with a project name that's been previously archived it should unarchive that project. Maybe the client came back. Doesn't matter why you've started using it, just that if you are, it's no longer conceptually in the "archive".
we'll eventually have to do this with tags too...
if you have two timers going and say hey stop <id of earlier timer> 1 minute ago
it will stop the most recently started one instead of the one specified.
The problem is that stop + id expects explicit 4 section time string (date + 24hr time), but it's not getting that and it's mistakenly not erroring out.
bug found on beta_9 branch, but probably exists in main.
A simple vertical bar graph. Each bar represents 1 of whatever time unit was requested.
if you ask for 7 days you get 7 bars. 2 weeks 2 bars, etc.
each bar represents the total hours captured. I think the max should probably be ~18hrs ? I'm hoping folks aren't working more than 18hrs in a day (shudder at the thought of doctors with 24hr shifts). The problem with 24 is that it leaves a ton of empty space at the top for the vast vast majority of humans.
This will require a cli graphing library. We'll probably have to port something like this library i wrote in crystal unless something like this already exists in Raku.
it supports multiple simultaneous timers, but you can only support the last one.
hey log
shows the ID now.
enable stop
to take an id as the first parameter.
Hi,
on one hand, it's very flattering to see dependencies on Template6 that mostly I have been maintaining for a while... on the other hand, this repo doesn't seem to use it for anything. Perhaps it could be removed from dependencies, or I'm missing something.
Cheers.
create a "days totals" (or months, or whatever) table that displays after the log and contains the total time spent within the given duration on each project in a duration.
So, if you have logged 3 timers of 1hr each for @foo
project today, there would be, in a subsequent table a line that indicated that @foo
had 3hrs spent on it
Something like this
project | time spent |
---|---|
@foo | 3h |
@bar | 45m |
total | 3h45m |
Ongoing timers should have their current duration displayed instead of just "ongoing"
when you say hey today
or hey log 1 day
I'm thinking it should be something like > 40m41s
when you hey summarize 1 day
it should add in whatever time has passed so far on ongoing timers.
right now you can say hey stop at HH:MM
but i just noticed i've left a timer running for two days π€¦π»ββοΈ so the normal backdating isn't going to work.
I'm proposing the expansion of the at <time>
time modification to be at [optional date] <time>
# hey stop at mm/dd HH:MM
hey stop at 12/16 14:22
In this case we would have to presume 24hr time input because we don't have relative context to guess at which 6:40
they meant.
The final sentence in the "Tracking Time" section currently reads
You can in the GitHub README
It looks like some words might be missing.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.