1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
package task
import (
"bytes"
"context"
"fmt"
"os/exec"
"strings"
"github.com/google/shlex"
)
func run(args ...string) error {
return runContext(context.Background(), args...)
}
func runContext(ctx context.Context, args ...string) error {
_, err := RunArgs(ctx, args)
return err
}
// RunLine splits line using shell-word rules and runs the resulting task
// arguments. A leading "task" token is ignored so callers may accept either
// "add foo" or "task add foo" from user input.
func RunLine(ctx context.Context, line string) (RunResult, error) {
fields, err := shlex.Split(line)
if err != nil {
return RunResult{}, err
}
if len(fields) > 0 && fields[0] == "task" {
fields = fields[1:]
}
return RunArgs(ctx, fields)
}
// RunShellLine runs a user-entered task command in non-interactive mode. It
// avoids Taskwarrior's recurring-task prompt by applying the same behavior as
// answering "no": modify only the addressed recurrence.
func RunShellLine(ctx context.Context, line string) (RunResult, error) {
fields, err := shlex.Split(line)
if err != nil {
return RunResult{}, err
}
if len(fields) > 0 && fields[0] == "task" {
fields = fields[1:]
}
fields = append([]string{"rc.recurrence.confirmation=no"}, fields...)
return RunArgs(ctx, fields)
}
// RunArgs runs "task" with args and captures stdout and stderr.
func RunArgs(ctx context.Context, args []string) (RunResult, error) {
copied := append([]string(nil), args...)
result := RunResult{Args: copied}
if len(copied) == 0 {
return result, fmt.Errorf("empty task command")
}
if dbg.writer != nil {
if _, err := fmt.Fprintln(dbg.writer, "task "+strings.Join(copied, " ")); err != nil {
return result, fmt.Errorf("write debug log: %w", err)
}
}
cmd := exec.CommandContext(ctx, "task", copied...)
configureCommandContext(cmd)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
result.Stdout = stdout.String()
result.Stderr = stderr.String()
if err != nil {
if ctxErr := ctx.Err(); ctxErr != nil {
return result, fmt.Errorf("task command: %w", ctxErr)
}
if strings.TrimSpace(result.Stderr) != "" {
return result, fmt.Errorf("%w: %s", err, strings.TrimSpace(result.Stderr))
}
return result, err
}
return result, nil
}
|