diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 4e0709a..96c12a6 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -32,7 +32,7 @@ brews: directory: Formula license: MIT homepage: "https://github.com/dhth/hours" - description: "A no-frills command-line app for tracking time on tasks" + description: "A no-frills time tracking toolkit for the command line" changelog: sort: asc diff --git a/README.md b/README.md index ee075be..c20e54e 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,15 @@ # hours -✨ Overview ---- +`hours` is a no-frills time tracking toolkit for the command line. + +It's designed for users who want basic time tracking for their tasks/projects +right in the terminal. With a simple and minimalistic UI, almost everything in +`hours` can be achieved with one or two keypresses. It can also generate +plaintext reports, summary statistics, and logs based on time tracked. + +![Usage](https://tools.dhruvs.space/images/hours/hours.gif) -`hours` is a no-frills command-line app for tracking time on tasks. It's -designed for users who want basic time tracking for their tasks/projects, right -in the terminal. With a simple and minimalistic UI, almost everything in `hours` -can be achieved with one or two keypresses. It can also generate plaintext -reports, summary statistics, and logs based on time tracked. +[Link to Video][2] 🤔 Motivation --- @@ -22,6 +24,12 @@ precisely fit these needs, so I decided to build one for myself. 💾 Install --- +**homebrew**: + +```sh +brew install dhth/tap/hours +``` + **go**: ```sh @@ -31,6 +39,8 @@ go install github.com/dhth/hours@latest ⚡️ Usage --- +### TUI + Open the TUI by simply running `hours`. The TUI lets you do the following: - create/update tasks @@ -39,125 +49,93 @@ Open the TUI by simply running `hours`. The TUI lets you do the following: - deactivate/activate a task - view historical task log entries +![Usage](https://tools.dhruvs.space/images/hours/tui-1.png) + +![Usage](https://tools.dhruvs.space/images/hours/tui-2.png) + +![Usage](https://tools.dhruvs.space/images/hours/tui-3.png) + Besides a TUI, `hours` also offers reports, statistics, and logs based on the time tracking you do. These can be viewed using the subcommands `report`, `stats`, and `log` respectively. ### Reports +```bash +hours report [flags] [arg] ``` -hours report -h Output a report based on task log entries. Reports show time spent on tasks per day in the time period you specify. These -can also be aggregated (using -a) to consolidate all task entries and show the +can also be aggregated (using `-a`) to consolidate all task entries and show the cumulative time spent on each task per day. Accepts an argument, which can be one of the following: - today: for today's report - yest: for yesterday's report - 3d: for a report on the last 3 days (default) - week: for a report on the current week - date: for a report for a specific date (eg. "2024/06/08") - range: for a report for a date range (eg. "2024/06/08...2024/06/12") + today: for today's report + yest: for yesterday's report + 3d: for a report on the last 3 days (default) + week: for a report on the current week + date: for a report for a specific date (eg. "2024/06/08") + range: for a report for a date range (eg. "2024/06/08...2024/06/12") -Note: If a task log continues past midnight in your local timezone, it -will be reported on the day it ends. +*Note: If a task log continues past midnight in your local timezone, it will be +reported on the day it ends.* -Usage: - hours report [flags] +![Usage](https://tools.dhruvs.space/images/hours/report-1.png) -Flags: - -a, --agg whether to aggregate data by task for each day in report - -p, --plain whether to output report without any formatting -``` +### Logs ```bash -# see report from last 3 days -hours report - -# see aggregated time spent on tasks -hours report -a - -# see report for the 7 days -hours report week - -# see report for a specific date range -hours report 2024/06/08...2024/06/12 -``` - -Statistics ---- - +hours log [flags] [arg] ``` -hours stats -h -Output statistics for tracked time. +Output task log entries. Accepts an argument, which can be one of the following: - today: show stats for today - yest: show stats for yesterday - 3d: show stats for the last 3 days (default) - week: show stats for the current week - month: show stats for the current month - date: show stats for a specific date (eg. "2024/06/08") - range: show stats for a specific date range (eg. "2024/06/08...2024/06/12") - all: show stats for all log entries - -Note: If a task log continues past midnight in your local timezone, it'll -be considered in the stats for the day it ends. + today: for log entries from today + yest: for log entries from yesterday + 3d: for log entries from the last 3 days (default) + week: for log entries from the current week + date: for log entries from a specific date (eg. "2024/06/08") + range: for log entries from a specific date range (eg. "2024/06/08...2024/06/12") -Usage: - hours stats [flags] +*Note: If a task log continues past midnight in your local timezone, it'll +appear in the log for the day it ends.* -Flags: - -p, --plain whether to output stats without any formatting -``` +![Usage](https://tools.dhruvs.space/images/hours/log-1.png) -### Logs +Statistics +--- +```bash +hours stats [flag] [arg] ``` -hours log -h -Output task log entries. +Output statistics for tracked time. Accepts an argument, which can be one of the following: - today: for log entries from today - yest: for log entries from yesterday - 3d: for log entries from the last 3 days (default) - week: for log entries from the current week - date: for log entries from a specific date (eg. "2024/06/08") - range: for log entries from a specific date range (eg. "2024/06/08...2024/06/12") - -Note: If a task log continues past midnight in your local timezone, it'll -appear in the log for the day it ends. - -Usage: - hours log [flags] - -Flags: - -p, --plain whether to output log without any formatting -``` + today: show stats for today + yest: show stats for yesterday + 3d: show stats for the last 3 days (default) + week: show stats for the current week + month: show stats for the current month + date: show stats for a specific date (eg. "2024/06/08") + range: show stats for a specific date range (eg. "2024/06/08...2024/06/12") + all: show stats for all log entries -```bash -# see log entries from today -hours log today +*Note: If a task log continues past midnight in your local timezone, it'll +be considered in the stats for the day it ends.* -# see log entries from a specific day -hours log 2024/06/08 - -# see log entries from a specific date range -hours log 2024/06/08...2024/06/12 -``` +![Usage](https://tools.dhruvs.space/images/hours/stats-1.png) 📋 TUI Reference Manual --- -``` +```text "hours" has 5 panes: - Tasks List View Shows your tasks - Task Management View Allows you to create/update tasks @@ -213,3 +191,4 @@ Acknowledgements `hours` is built using the TUI framework [bubbletea][1]. [1]: https://github.com/charmbracelet/bubbletea +[2]: https://www.youtube.com/watch?v=o244r1nyxac diff --git a/cmd/root.go b/cmd/root.go index 0520cb6..8ec3f44 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -31,7 +31,12 @@ func die(msg string, args ...any) { var rootCmd = &cobra.Command{ Use: "hours", - Short: "Track time on your tasks via a simple TUI.", + Short: "\"hours\" is a no-frills time tracking toolkit for the command line", + Long: `"hours" is a no-frills time tracking toolkit for the command line. + +You can use "hours" to track time on your tasks, or view logs, reports, and +summary statistics for your tracked time. +`, PersistentPreRun: func(cmd *cobra.Command, args []string) { if dbPath == "" { die("dbpath cannot be empty") diff --git a/internal/ui/report.go b/internal/ui/report.go index c6d25f1..e981de8 100644 --- a/internal/ui/report.go +++ b/internal/ui/report.go @@ -153,6 +153,18 @@ func renderNDaysReport(db *sql.DB, writer io.Writer, start time.Time, numDays in rs := getReportStyles(plain) + var summaryBudget int + switch numDays { + case 7: + summaryBudget = 8 + case 6: + summaryBudget = 10 + case 5: + summaryBudget = 14 + default: + summaryBudget = 16 + } + styleCache := make(map[string]lipgloss.Style) for rowIndex := 0; rowIndex < maxEntryForADay; rowIndex++ { row := make([]string, numDays) @@ -166,8 +178,8 @@ func renderNDaysReport(db *sql.DB, writer io.Writer, start time.Time, numDays in timeSpentStr := humanizeDuration(tr.secsSpent) if plain { - row[colIndex] = fmt.Sprintf("%s %s", - RightPadTrim(tr.taskSummary, 8, false), + row[colIndex] = fmt.Sprintf("%s %s", + RightPadTrim(tr.taskSummary, summaryBudget, false), timeSpentStr, ) } else { @@ -178,8 +190,8 @@ func renderNDaysReport(db *sql.DB, writer io.Writer, start time.Time, numDays in styleCache[tr.taskSummary] = reportStyle } - row[colIndex] = fmt.Sprintf("%s %s", - reportStyle.Render(RightPadTrim(tr.taskSummary, 8, false)), + row[colIndex] = fmt.Sprintf("%s %s", + reportStyle.Render(RightPadTrim(tr.taskSummary, summaryBudget, false)), reportStyle.Render(timeSpentStr), ) } @@ -268,6 +280,18 @@ func renderNDaysReportAgg(db *sql.DB, writer io.Writer, start time.Time, numDays rs := getReportStyles(plain) + var summaryBudget int + switch numDays { + case 7: + summaryBudget = 8 + case 6: + summaryBudget = 10 + case 5: + summaryBudget = 14 + default: + summaryBudget = 16 + } + styleCache := make(map[string]lipgloss.Style) for rowIndex := 0; rowIndex < maxEntryForADay; rowIndex++ { row := make([]string, numDays) @@ -281,8 +305,8 @@ func renderNDaysReportAgg(db *sql.DB, writer io.Writer, start time.Time, numDays timeSpentStr := humanizeDuration(tr.secsSpent) if plain { - row[colIndex] = fmt.Sprintf("%s %s", - RightPadTrim(tr.taskSummary, 8, false), + row[colIndex] = fmt.Sprintf("%s %s", + RightPadTrim(tr.taskSummary, summaryBudget, false), timeSpentStr, ) } else { @@ -292,8 +316,8 @@ func renderNDaysReportAgg(db *sql.DB, writer io.Writer, start time.Time, numDays styleCache[tr.taskSummary] = reportStyle } - row[colIndex] = fmt.Sprintf("%s %s", - reportStyle.Render(RightPadTrim(tr.taskSummary, 8, false)), + row[colIndex] = fmt.Sprintf("%s %s", + reportStyle.Render(RightPadTrim(tr.taskSummary, summaryBudget, false)), reportStyle.Render(timeSpentStr), ) }