Skip to content

Commit

Permalink
Auto-appending tags from open range when pausing
Browse files Browse the repository at this point in the history
Resolves #283.

If the open range contains tags, then `klog pause` will automatically
take them over (i.e., append) them to the pause entry.

## Example

```
2000-01-01
    5:00-? Did #work
```

Then `klog pause` yields:

```
2000-01-01
    5:00-? Did #work
    -0m #work
```

You can still use the `--summary` flag.

`--no-tags` disables this behaviour.
  • Loading branch information
jotaen authored Mar 2, 2024
1 parent 5982e97 commit f083957
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 25 deletions.
20 changes: 15 additions & 5 deletions klog/app/cli/pause.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import (
)

type Pause struct {
Summary klog.EntrySummary `name:"summary" short:"s" placeholder:"TEXT" help:"Summary text for the pause entry"`
Extend bool `name:"extend" short:"e" help:"Extend latest pause, instead of adding a new pause entry"`
Summary klog.EntrySummary `name:"summary" short:"s" placeholder:"TEXT" help:"Summary text for the pause entry"`
NoAppendTags bool `name:"no-tags" help:"Do not automatically take over (append) tags from open range"`
Extend bool `name:"extend" short:"e" help:"Extend latest pause, instead of adding a new pause entry"`
util.OutputFileArgs
util.NoStyleArgs
util.WarnArgs
Expand All @@ -24,11 +25,20 @@ func (opt *Pause) Help() string {
return `Creates a pause entry for a record with an open time range.
The command is blocking – it keeps updating the pause entry until the process is exited.
(The file will be written into once per minute.)
If the open range in the record contains tags, then these will automatically be taken over and appended to the pause entry.
`
}

func (opt *Pause) Run(ctx app.Context) app.Error {
opt.NoStyleArgs.Apply(&ctx)
if opt.Extend && opt.Summary != nil {
return app.NewError(
"Illegal flag combination",
"It’s not possible to combine --extend with --summary",
nil,
)
}
today := klog.NewDateFromGo(ctx.Now())
doReconcile := func(reconcile reconciling.Reconcile) (*reconciling.Result, app.Error) {
return ctx.ReconcileFile(
Expand All @@ -47,9 +57,9 @@ func (opt *Pause) Run(ctx app.Context) app.Error {
// - With `--extend`, find a pause and append the summary
lastResult, err := doReconcile(func(reconciler *reconciling.Reconciler) error {
if opt.Extend {
return reconciler.ExtendPause(klog.NewDuration(0, 0), opt.Summary)
return reconciler.ExtendPause(klog.NewDuration(0, 0))
}
return reconciler.AppendPause(opt.Summary)
return reconciler.AppendPause(opt.Summary, !opt.NoAppendTags)
})
if err != nil {
return err
Expand All @@ -73,7 +83,7 @@ func (opt *Pause) Run(ctx app.Context) app.Error {
if uncapturedIncrement > 0 {
lastResult, err = doReconcile(func(reconciler *reconciling.Reconciler) error {
// Don’t add the summary here, as we already appended it in the initial run.
return reconciler.ExtendPause(klog.NewDuration(0, -1*uncapturedIncrement), nil)
return reconciler.ExtendPause(klog.NewDuration(0, -1*uncapturedIncrement))
})
minsCaptured += uncapturedIncrement
if err != nil {
Expand Down
13 changes: 9 additions & 4 deletions klog/parser/reconciling/pause_open_range.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import (
)

// AppendPause adds a new pause entry to a record that contains an open range.
func (r *Reconciler) AppendPause(summary klog.EntrySummary) error {
if r.findOpenRangeIndex() == -1 {
func (r *Reconciler) AppendPause(summary klog.EntrySummary, appendTags bool) error {
openEntryI := r.findOpenRangeIndex()
if openEntryI == -1 {
return errors.New("No open time range found")
}
entryValue := "-0m"
Expand All @@ -20,11 +21,16 @@ func (r *Reconciler) AppendPause(summary klog.EntrySummary) error {
entryValue += " "
}
summary[0] = entryValue + summary[0]
if appendTags {
openEntry := r.Record.Entries()[openEntryI]
appendableTags := strings.Join(openEntry.Summary().Tags().ToStrings(), " ")
summary = summary.Append(appendableTags)
}
return r.AppendEntry(summary)
}

// ExtendPause extends an existing pause entry.
func (r *Reconciler) ExtendPause(increment klog.Duration, additionalSummary klog.EntrySummary) error {
func (r *Reconciler) ExtendPause(increment klog.Duration) error {
if r.findOpenRangeIndex() == -1 {
return errors.New("No open time range found")
}
Expand All @@ -50,6 +56,5 @@ func (r *Reconciler) ExtendPause(increment klog.Duration, additionalSummary klog
r.lines[pauseLineIndex].Text = strings.Replace(r.lines[pauseLineIndex].Text, value, extendedPause.ToString(), 1)
}

r.concatenateSummary(pauseEntryI, pauseLineIndex, additionalSummary)
return nil
}
73 changes: 57 additions & 16 deletions klog/parser/reconciling/pause_open_range_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestReconcilerAppendingPauseAddsNewEntry(t *testing.T) {
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.AppendPause(nil)
err := reconciler.AppendPause(nil, false)
require.Nil(t, err)

result := assertResult(t, reconciler)
Expand All @@ -35,7 +35,7 @@ func TestReconcilerAppendingPauseWithSummary(t *testing.T) {
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.AppendPause(klog.Ɀ_EntrySummary_("Lunch break"))
err := reconciler.AppendPause(klog.Ɀ_EntrySummary_("Lunch break"), false)
require.Nil(t, err)

result := assertResult(t, reconciler)
Expand All @@ -46,6 +46,48 @@ func TestReconcilerAppendingPauseWithSummary(t *testing.T) {
`, result.AllSerialised)
}

func TestReconcilerAppendingPauseTakesOverTags(t *testing.T) {
original := `
2010-04-27
3:00pm - ? Did some #work
and also #misc other #things
and then more #work (redundant tag)
`
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.AppendPause(nil, true)
require.Nil(t, err)

result := assertResult(t, reconciler)
assert.Equal(t, `
2010-04-27
3:00pm - ? Did some #work
and also #misc other #things
and then more #work (redundant tag)
-0m #misc #things #work
`, result.AllSerialised)
}

func TestReconcilerAppendingPauseTakesOverTagsAndConcatsWithSummary(t *testing.T) {
original := `
2010-04-27
3:00pm - ? Did some #work
`
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.AppendPause(klog.Ɀ_EntrySummary_("Lunch break"), true)
require.Nil(t, err)

result := assertResult(t, reconciler)
assert.Equal(t, `
2010-04-27
3:00pm - ? Did some #work
-0m Lunch break #work
`, result.AllSerialised)
}

func TestReconcilerAppendingPauseWithMultilineSummary(t *testing.T) {
original := `
2010-04-27
Expand All @@ -54,7 +96,7 @@ func TestReconcilerAppendingPauseWithMultilineSummary(t *testing.T) {
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.AppendPause(klog.Ɀ_EntrySummary_("Lunch", "break"))
err := reconciler.AppendPause(klog.Ɀ_EntrySummary_("Lunch", "break"), false)
require.Nil(t, err)

result := assertResult(t, reconciler)
Expand All @@ -75,7 +117,7 @@ func TestReconcilerAppendPauseWithUTF8Summary(t *testing.T) {
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.AppendPause(klog.Ɀ_EntrySummary_("午休"))
err := reconciler.AppendPause(klog.Ɀ_EntrySummary_("午休"), false)
require.Nil(t, err)

result := assertResult(t, reconciler)
Expand All @@ -95,7 +137,7 @@ func TestReconcilerAppendingPauseFailsIfThereIsNoOpenRange(t *testing.T) {
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.AppendPause(nil)
err := reconciler.AppendPause(nil, false)
require.Error(t, err)
}

Expand All @@ -110,7 +152,7 @@ Foo
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.ExtendPause(klog.NewDuration(0, -3), nil)
err := reconciler.ExtendPause(klog.NewDuration(0, -3))
require.Nil(t, err)

result := assertResult(t, reconciler)
Expand All @@ -134,7 +176,7 @@ Foo
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.ExtendPause(klog.NewDuration(0, -3), klog.Ɀ_EntrySummary_("and more break"))
err := reconciler.ExtendPause(klog.NewDuration(0, -3))
require.Nil(t, err)

result := assertResult(t, reconciler)
Expand All @@ -143,7 +185,7 @@ Foo
Foo
3:00 - ? I desperately need
a break!
-4m Lunch break and more break
-4m Lunch break
`, result.AllSerialised)
}

Expand All @@ -158,7 +200,7 @@ Foo
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.ExtendPause(klog.NewDuration(-1, 0), klog.Ɀ_EntrySummary_("", "and more break"))
err := reconciler.ExtendPause(klog.NewDuration(-1, 0))
require.Nil(t, err)

result := assertResult(t, reconciler)
Expand All @@ -168,7 +210,6 @@ Foo
3:00 - ? I desperately need
a break!
-2h Lunch break
and more break
`, result.AllSerialised)
}

Expand All @@ -184,7 +225,7 @@ Foo
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.ExtendPause(klog.NewDuration(-1, 0), klog.Ɀ_EntrySummary_("and more break"))
err := reconciler.ExtendPause(klog.NewDuration(-1, 0))
require.Nil(t, err)

result := assertResult(t, reconciler)
Expand All @@ -194,7 +235,7 @@ Foo
3:00 - ? I desperately need
a break!
-2h Lunch
break and more break
break
`, result.AllSerialised)
}

Expand All @@ -210,7 +251,7 @@ Foo
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.ExtendPause(klog.NewDuration(-2, -51), nil)
err := reconciler.ExtendPause(klog.NewDuration(-2, -51))
require.Nil(t, err)

result := assertResult(t, reconciler)
Expand All @@ -235,7 +276,7 @@ Foo
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.ExtendPause(klog.NewDuration(0, 0), nil)
err := reconciler.ExtendPause(klog.NewDuration(0, 0))
require.Nil(t, err)

result := assertResult(t, reconciler)
Expand All @@ -257,7 +298,7 @@ func TestReconcilerExtendingPauseFailsIfThereIsNoOpenRange(t *testing.T) {
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.ExtendPause(klog.NewDuration(2, 0), nil)
err := reconciler.ExtendPause(klog.NewDuration(2, 0))
require.Error(t, err)
}

Expand All @@ -270,6 +311,6 @@ func TestReconcilerDoesNotExtendNonNegativeDurations(t *testing.T) {
rs, bs, _ := parser.NewSerialParser().Parse(original)
reconciler := NewReconcilerAtRecord(klog.Ɀ_Date_(2010, 4, 27))(rs, bs)
require.NotNil(t, reconciler)
err := reconciler.ExtendPause(klog.NewDuration(0, -10), nil)
err := reconciler.ExtendPause(klog.NewDuration(0, -10))
require.Error(t, err)
}
14 changes: 14 additions & 0 deletions klog/summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,17 @@ func (s EntrySummary) Equals(summary EntrySummary) bool {
}
return RecordSummary(s).Equals(RecordSummary(summary))
}

// Append appends a text to an entry summary
func (s EntrySummary) Append(appendableText string) EntrySummary {
if len(s) == 0 {
return []string{appendableText}
}
delimiter := ""
lastLine := s[len(s)-1]
if len(lastLine) > 0 {
delimiter = " "
}
s[len(s)-1] = lastLine + delimiter + appendableText
return s
}
23 changes: 23 additions & 0 deletions klog/summary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,26 @@ func TestRecognisesAllTags(t *testing.T) {
entrySummary, _ := NewEntrySummary("Hello #world, I feel #great #TODAY")
assert.Equal(t, entrySummary.Tags().ToStrings(), []string{"#great", "#today", "#world"})
}

func TestAppendsToEntrySummary(t *testing.T) {
t.Run("append empty to empty", func(t *testing.T) {
e := Ɀ_EntrySummary_().Append("")
assert.Equal(t, []string{""}, e.Lines())
})
t.Run("append non-empty to zero", func(t *testing.T) {
e := Ɀ_EntrySummary_().Append("foo")
assert.Equal(t, []string{"foo"}, e.Lines())
})
t.Run("append non-empty to empty", func(t *testing.T) {
e := Ɀ_EntrySummary_("").Append("foo")
assert.Equal(t, []string{"foo"}, e.Lines())
})
t.Run("append non-empty to existing", func(t *testing.T) {
e := Ɀ_EntrySummary_("hello").Append("foo")
assert.Equal(t, []string{"hello foo"}, e.Lines())
})
t.Run("append non-empty to multiline", func(t *testing.T) {
e := Ɀ_EntrySummary_("hello", "world").Append("foo")
assert.Equal(t, []string{"hello", "world foo"}, e.Lines())
})
}

0 comments on commit f083957

Please sign in to comment.