Clean up task editor and time editor

This commit is contained in:
Martin Pander
2026-02-17 20:57:21 +01:00
parent 6e60698526
commit 1a9fd9b4b0
10 changed files with 141 additions and 115 deletions

View File

@@ -5,6 +5,7 @@ package taskwarrior
import (
"bytes"
"context"
"encoding/json"
"fmt"
"log/slog"
@@ -111,11 +112,12 @@ type TaskSquire struct {
config *TWConfig
reports Reports
contexts Contexts
ctx context.Context
mutex sync.Mutex
}
func NewTaskSquire(configLocation string) *TaskSquire {
func NewTaskSquire(ctx context.Context, configLocation string) *TaskSquire {
if _, err := exec.LookPath(twBinary); err != nil {
slog.Error("Taskwarrior not found")
return nil
@@ -125,6 +127,7 @@ func NewTaskSquire(configLocation string) *TaskSquire {
ts := &TaskSquire{
configLocation: configLocation,
defaultArgs: defaultArgs,
ctx: ctx,
mutex: sync.Mutex{},
}
ts.config = ts.extractConfig()
@@ -169,17 +172,20 @@ func (ts *TaskSquire) GetTasks(report *Report, filter ...string) Tasks {
exportArgs = append(exportArgs, report.Name)
}
cmd := exec.Command(twBinary, append(args, exportArgs...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(args, exportArgs...)...)
output, err := cmd.CombinedOutput()
if err != nil {
slog.Error("Failed getting report:", err)
if ts.ctx.Err() == context.Canceled {
return nil
}
slog.Error("Failed getting report", "error", err)
return nil
}
tasks := make(Tasks, 0)
err = json.Unmarshal(output, &tasks)
if err != nil {
slog.Error("Failed unmarshalling tasks:", err)
slog.Error("Failed unmarshalling tasks", "error", err)
return nil
}
@@ -198,10 +204,10 @@ func (ts *TaskSquire) GetTasks(report *Report, filter ...string) Tasks {
}
func (ts *TaskSquire) getIds(filter []string) string {
cmd := exec.Command(twBinary, append(append(ts.defaultArgs, filter...), "_ids")...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(append(ts.defaultArgs, filter...), "_ids")...)
out, err := cmd.CombinedOutput()
if err != nil {
slog.Error("Failed getting field:", err)
slog.Error("Failed getting field", "error", err)
return ""
}
@@ -219,7 +225,7 @@ func (ts *TaskSquire) GetContext(context string) *Context {
if context, ok := ts.contexts[context]; ok {
return context
} else {
slog.Error(fmt.Sprintf("Context not found: %s", context.Name))
slog.Error("Context not found", "name", context)
return nil
}
}
@@ -248,11 +254,11 @@ func (ts *TaskSquire) GetProjects() []string {
ts.mutex.Lock()
defer ts.mutex.Unlock()
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"_projects"}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"_projects"}...)...)
output, err := cmd.CombinedOutput()
if err != nil {
slog.Error("Failed getting projects:", err)
slog.Error("Failed getting projects", "error", err)
return nil
}
@@ -286,11 +292,11 @@ func (ts *TaskSquire) GetTags() []string {
ts.mutex.Lock()
defer ts.mutex.Unlock()
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"_tags"}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"_tags"}...)...)
output, err := cmd.CombinedOutput()
if err != nil {
slog.Error("Failed getting tags:", err)
slog.Error("Failed getting tags", "error", err)
return nil
}
@@ -333,10 +339,13 @@ func (ts *TaskSquire) GetUdas() []Uda {
ts.mutex.Lock()
defer ts.mutex.Unlock()
cmd := exec.Command(twBinary, append(ts.defaultArgs, "_udas")...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, "_udas")...)
output, err := cmd.CombinedOutput()
if err != nil {
slog.Error("Failed getting config:", err)
if ts.ctx.Err() == context.Canceled {
return nil
}
slog.Error("Failed getting UDAs", "error", err)
return nil
}
@@ -345,7 +354,7 @@ func (ts *TaskSquire) GetUdas() []Uda {
if uda != "" {
udatype := UdaType(ts.config.Get(fmt.Sprintf("uda.%s.type", uda)))
if udatype == "" {
slog.Error(fmt.Sprintf("UDA type not found: %s", uda))
slog.Error("UDA type not found", "uda", uda)
continue
}
@@ -376,9 +385,9 @@ func (ts *TaskSquire) SetContext(context *Context) error {
return nil
}
cmd := exec.Command(twBinary, []string{"context", context.Name}...)
cmd := exec.CommandContext(ts.ctx, twBinary, []string{"context", context.Name}...)
if err := cmd.Run(); err != nil {
slog.Error("Failed setting context:", err)
slog.Error("Failed setting context", "error", err)
return err
}
@@ -433,14 +442,17 @@ func (ts *TaskSquire) ImportTask(task *Task) {
tasks, err := json.Marshal(Tasks{task})
if err != nil {
slog.Error("Failed marshalling task:", err)
slog.Error("Failed marshalling task", "error", err)
}
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"import", "-"}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"import", "-"}...)...)
cmd.Stdin = bytes.NewBuffer(tasks)
out, err := cmd.CombinedOutput()
if err != nil {
slog.Error("Failed modifying task:", err, string(out))
if ts.ctx.Err() == context.Canceled {
return
}
slog.Error("Failed modifying task", "error", err, "output", string(out))
}
}
@@ -448,10 +460,10 @@ func (ts *TaskSquire) SetTaskDone(task *Task) {
ts.mutex.Lock()
defer ts.mutex.Unlock()
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"done", task.Uuid}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"done", task.Uuid}...)...)
err := cmd.Run()
if err != nil {
slog.Error("Failed setting task done:", err)
slog.Error("Failed setting task done", "error", err)
}
}
@@ -459,10 +471,10 @@ func (ts *TaskSquire) DeleteTask(task *Task) {
ts.mutex.Lock()
defer ts.mutex.Unlock()
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{task.Uuid, "delete"}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{task.Uuid, "delete"}...)...)
err := cmd.Run()
if err != nil {
slog.Error("Failed deleting task:", err)
slog.Error("Failed deleting task", "error", err)
}
}
@@ -471,10 +483,10 @@ func (ts *TaskSquire) Undo() {
ts.mutex.Lock()
defer ts.mutex.Unlock()
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"undo"}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"undo"}...)...)
err := cmd.Run()
if err != nil {
slog.Error("Failed undoing task:", err)
slog.Error("Failed undoing task", "error", err)
}
}
@@ -482,10 +494,10 @@ func (ts *TaskSquire) StartTask(task *Task) {
ts.mutex.Lock()
defer ts.mutex.Unlock()
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"start", task.Uuid}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"start", task.Uuid}...)...)
err := cmd.Run()
if err != nil {
slog.Error("Failed starting task:", err)
slog.Error("Failed starting task", "error", err)
}
}
@@ -493,10 +505,10 @@ func (ts *TaskSquire) StopTask(task *Task) {
ts.mutex.Lock()
defer ts.mutex.Unlock()
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"stop", task.Uuid}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"stop", task.Uuid}...)...)
err := cmd.Run()
if err != nil {
slog.Error("Failed stopping task:", err)
slog.Error("Failed stopping task", "error", err)
}
}
@@ -504,25 +516,28 @@ func (ts *TaskSquire) StopActiveTasks() {
ts.mutex.Lock()
defer ts.mutex.Unlock()
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"+ACTIVE", "export"}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"+ACTIVE", "export"}...)...)
output, err := cmd.CombinedOutput()
if err != nil {
slog.Error("Failed getting active tasks:", "error", err, "output", string(output))
if ts.ctx.Err() == context.Canceled {
return
}
slog.Error("Failed getting active tasks", "error", err, "output", string(output))
return
}
tasks := make(Tasks, 0)
err = json.Unmarshal(output, &tasks)
if err != nil {
slog.Error("Failed unmarshalling active tasks:", err)
slog.Error("Failed unmarshalling active tasks", "error", err)
return
}
for _, task := range tasks {
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"stop", task.Uuid}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"stop", task.Uuid}...)...)
err := cmd.Run()
if err != nil {
slog.Error("Failed stopping task:", err)
slog.Error("Failed stopping task", "error", err)
}
}
}
@@ -531,10 +546,13 @@ func (ts *TaskSquire) GetInformation(task *Task) string {
ts.mutex.Lock()
defer ts.mutex.Unlock()
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{fmt.Sprintf("uuid:%s", task.Uuid), "information"}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{fmt.Sprintf("uuid:%s", task.Uuid), "information"}...)...)
output, err := cmd.CombinedOutput()
if err != nil {
slog.Error("Failed getting task information:", err)
if ts.ctx.Err() == context.Canceled {
return ""
}
slog.Error("Failed getting task information", "error", err)
return ""
}
@@ -545,17 +563,20 @@ func (ts *TaskSquire) AddTaskAnnotation(uuid string, annotation string) {
ts.mutex.Lock()
defer ts.mutex.Unlock()
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{uuid, "annotate", annotation}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{uuid, "annotate", annotation}...)...)
err := cmd.Run()
if err != nil {
slog.Error("Failed adding annotation:", err)
slog.Error("Failed adding annotation", "error", err)
}
}
func (ts *TaskSquire) extractConfig() *TWConfig {
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"_show"}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"_show"}...)...)
output, err := cmd.CombinedOutput()
if err != nil {
if ts.ctx.Err() == context.Canceled {
return nil
}
slog.Error("Failed getting config", "error", err, "output", string(output))
return nil
}
@@ -564,7 +585,7 @@ func (ts *TaskSquire) extractConfig() *TWConfig {
}
func (ts *TaskSquire) extractReports() Reports {
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"_config"}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"_config"}...)...)
output, err := cmd.CombinedOutput()
if err != nil {
return nil
@@ -610,10 +631,13 @@ func extractReports(config string) []string {
}
func (ts *TaskSquire) extractContexts() Contexts {
cmd := exec.Command(twBinary, append(ts.defaultArgs, []string{"_context"}...)...)
cmd := exec.CommandContext(ts.ctx, twBinary, append(ts.defaultArgs, []string{"_context"}...)...)
output, err := cmd.CombinedOutput()
if err != nil {
if ts.ctx.Err() == context.Canceled {
return nil
}
slog.Error("Failed getting contexts", "error", err, "output", string(output))
return nil
}