diff --git a/README.md b/README.md index 289652a..0b1b179 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,7 @@ timetrace start [+TAG1, +TAG2, ...] | ---------------- | ----- | ---------------------------------------------------------------------------------------------------------- | | `--billable` | `-b` | Mark the record as billable. | | `--non-billable` | | Mark the record as non-billable, even if the project is [billable by default](#per-project-configuration). | +| `--description` | `-d` | Add a description to your record | **Example:** @@ -195,6 +196,12 @@ Start working on the `make-coffee` project and add two tags: timetrace start make-coffee +espresso +morning ``` +Start working on the `make-coffee` project and add a description: + +``` +timetrace start make-coffee -d "first time using the new beans" +``` + ### Print the tracking status **Syntax:** diff --git a/cli/create.go b/cli/create.go index e38acbc..29d24ec 100644 --- a/cli/create.go +++ b/cli/create.go @@ -100,10 +100,11 @@ func createRecordCommand(t *core.Timetrace) *cobra.Command { } record := core.Record{ - Project: project, - Start: start, - End: &end, - IsBillable: options.isBillable, + Project: project, + Start: start, + End: &end, + IsBillable: options.isBillable, + Description: options.description, } collides, err := t.RecordCollides(record) @@ -127,5 +128,8 @@ func createRecordCommand(t *core.Timetrace) *cobra.Command { createRecord.Flags().BoolVarP(&options.isBillable, "billable", "b", false, `mark tracked time as billable`) + createRecord.Flags().StringVarP(&options.description, "description", "d", + "", `set a description for your record`) + return createRecord } diff --git a/cli/list.go b/cli/list.go index c808412..31b386b 100644 --- a/cli/list.go +++ b/cli/list.go @@ -107,7 +107,7 @@ func listRecordsCommand(t *core.Timetrace) *cobra.Command { billable = "yes" } - rows[i] = make([]string, 7) + rows[i] = make([]string, 8) rows[i][0] = strconv.Itoa(len(records) - i) rows[i][1] = t.Formatter().RecordKey(record) rows[i][2] = record.Project.Key @@ -115,13 +115,14 @@ func listRecordsCommand(t *core.Timetrace) *cobra.Command { rows[i][4] = end rows[i][5] = billable rows[i][6] = t.Formatter().FormatTags(record.Tags) + rows[i][7] = record.Description } - footer := make([]string, 7) + footer := make([]string, 8) footer[len(footer)-2] = "Total: " footer[len(footer)-1] = t.Formatter().FormatDuration(getTotalTrackedTime(records)) - out.Table([]string{"#", "Key", "Project", "Start", "End", "Billable", "Tags"}, rows, footer) + out.Table([]string{"#", "Key", "Project", "Start", "End", "Billable", "Tags", "Description"}, rows, footer) }, } diff --git a/cli/start.go b/cli/start.go index 71e015a..5489a6f 100644 --- a/cli/start.go +++ b/cli/start.go @@ -15,6 +15,7 @@ const TagsPrefix = "+" type startOptions struct { isBillable bool isNonBillable bool // Used for overwriting `billable: true` in the project config. + description string } func startCommand(t *core.Timetrace) *cobra.Command { @@ -36,6 +37,8 @@ func startCommand(t *core.Timetrace) *cobra.Command { isBillable := options.isBillable + description := options.description + // If there is a default configuration for the project key, use that configuration. if projectConfig, ok := t.Config().Projects[projectKey]; ok { isBillable = projectConfig.Billable @@ -51,7 +54,7 @@ func startCommand(t *core.Timetrace) *cobra.Command { return } - if err := t.Start(projectKey, isBillable, tagNames); err != nil { + if err := t.Start(projectKey, isBillable, tagNames, description); err != nil { out.Err("failed to start tracking: %s", err.Error()) return } @@ -66,6 +69,9 @@ func startCommand(t *core.Timetrace) *cobra.Command { start.Flags().BoolVar(&options.isNonBillable, "non-billable", false, `mark tracked time as non-billable if the project is configured as billable`) + start.Flags().StringVarP(&options.description, "description", "d", + "", `set a description for your record`) + return start } diff --git a/core/record.go b/core/record.go index d69a619..9596f45 100644 --- a/core/record.go +++ b/core/record.go @@ -22,11 +22,12 @@ var ( ) type Record struct { - Start time.Time `json:"start"` - End *time.Time `json:"end"` - Project *Project `json:"project"` - IsBillable bool `json:"is_billable"` - Tags []string `json:"tags"` + Start time.Time `json:"start"` + End *time.Time `json:"end"` + Project *Project `json:"project"` + IsBillable bool `json:"is_billable"` + Tags []string `json:"tags"` + Description string `json:"description"` } // Duration calculates time duration for a specific record. If the record doesn't diff --git a/core/timetrace.go b/core/timetrace.go index ee1dcfd..9f05af6 100644 --- a/core/timetrace.go +++ b/core/timetrace.go @@ -67,7 +67,7 @@ func New(config *config.Config, fs Filesystem) *Timetrace { // record with the current time as start time. // // Since parallel work isn't supported, the previous work must be stopped first. -func (t *Timetrace) Start(projectKey string, isBillable bool, tags []string) error { +func (t *Timetrace) Start(projectKey string, isBillable bool, tags []string, description string) error { latestRecord, err := t.LoadLatestRecord() if err != nil && !errors.Is(err, ErrAllDirectoriesEmpty) { return err @@ -87,10 +87,11 @@ func (t *Timetrace) Start(projectKey string, isBillable bool, tags []string) err } record := Record{ - Start: time.Now(), - Project: project, - IsBillable: isBillable, - Tags: tags, + Start: time.Now(), + Project: project, + IsBillable: isBillable, + Tags: tags, + Description: description, } return t.SaveRecord(record, false)