improve cli field args parser
This commit is contained in:
parent
d53363f1ca
commit
248edf6379
|
@ -2,9 +2,12 @@ package command
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"ewintr.nl/gte/internal/configuration"
|
||||
"ewintr.nl/gte/internal/task"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -12,6 +15,9 @@ var (
|
|||
ErrInvalidArg = errors.New("invalid argument")
|
||||
ErrCouldNotFindTask = errors.New("could not find task")
|
||||
ErrUnknownFolder = errors.New("unknown folder")
|
||||
ErrFieldAlreadyUsed = errors.New("field was already used")
|
||||
ErrInvalidDate = errors.New("could not understand date format")
|
||||
ErrInvalidProject = errors.New("could not understand project")
|
||||
)
|
||||
|
||||
type Command interface {
|
||||
|
@ -89,3 +95,66 @@ func parseRemote(conf *configuration.Configuration, cmdArgs []string) (Command,
|
|||
return cmd, ErrInvalidArg
|
||||
}
|
||||
}
|
||||
|
||||
func ParseTaskFieldArgs(args []string) (*task.LocalUpdate, error) {
|
||||
lu := &task.LocalUpdate{}
|
||||
|
||||
action, fields := []string{}, []string{}
|
||||
for _, f := range args {
|
||||
if project, ok := parseProjectField(f); ok {
|
||||
if lu.Project != "" {
|
||||
return &task.LocalUpdate{}, fmt.Errorf("%w: %s", ErrFieldAlreadyUsed, task.FIELD_PROJECT)
|
||||
|
||||
}
|
||||
if project == "" {
|
||||
return &task.LocalUpdate{}, ErrInvalidProject
|
||||
}
|
||||
lu.Project = project
|
||||
fields = append(fields, task.FIELD_PROJECT)
|
||||
continue
|
||||
}
|
||||
if due, ok := parseDueField(f); ok {
|
||||
if due.IsZero() {
|
||||
return &task.LocalUpdate{}, ErrInvalidDate
|
||||
}
|
||||
if !lu.Due.IsZero() {
|
||||
return &task.LocalUpdate{}, fmt.Errorf("%w: %s", ErrFieldAlreadyUsed, task.FIELD_DUE)
|
||||
}
|
||||
lu.Due = due
|
||||
fields = append(fields, task.FIELD_DUE)
|
||||
continue
|
||||
}
|
||||
if len(f) > 0 {
|
||||
action = append(action, f)
|
||||
}
|
||||
}
|
||||
|
||||
if len(action) > 0 {
|
||||
lu.Action = strings.Join(action, " ")
|
||||
fields = append(fields, task.FIELD_ACTION)
|
||||
}
|
||||
|
||||
lu.Fields = fields
|
||||
|
||||
return lu, nil
|
||||
}
|
||||
|
||||
func parseProjectField(s string) (string, bool) {
|
||||
if !strings.HasPrefix(s, "project:") && !strings.HasPrefix(s, "p:") {
|
||||
return "", false
|
||||
}
|
||||
split := strings.SplitN(s, ":", 2)
|
||||
|
||||
return split[1], true
|
||||
}
|
||||
|
||||
func parseDueField(s string) (task.Date, bool) {
|
||||
if !strings.HasPrefix(s, "due:") && !strings.HasPrefix(s, "d:") {
|
||||
return task.Date{}, false
|
||||
}
|
||||
split := strings.SplitN(s, ":", 2)
|
||||
|
||||
due := task.NewDateFromString(split[1])
|
||||
|
||||
return due, true
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package format_test
|
||||
package command_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
@ -6,7 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"ewintr.nl/go-kit/test"
|
||||
"ewintr.nl/gte/cmd/cli/format"
|
||||
"ewintr.nl/gte/cmd/cli/command"
|
||||
"ewintr.nl/gte/internal/task"
|
||||
)
|
||||
|
||||
|
@ -53,12 +53,47 @@ func TestParseTaskFieldArgs(t *testing.T) {
|
|||
name: "two projects",
|
||||
input: "project:project1 project:project2",
|
||||
expUpdate: &task.LocalUpdate{},
|
||||
expErr: format.ErrFieldAlreadyUsed,
|
||||
expErr: command.ErrFieldAlreadyUsed,
|
||||
},
|
||||
{
|
||||
name: "abbreviated",
|
||||
input: "p:project1 d:2022-09-28",
|
||||
expUpdate: &task.LocalUpdate{
|
||||
Fields: []string{task.FIELD_PROJECT, task.FIELD_DUE},
|
||||
Project: "project1",
|
||||
Due: task.NewDate(2022, 9, 28),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty project",
|
||||
input: "action project:",
|
||||
expUpdate: &task.LocalUpdate{},
|
||||
expErr: command.ErrInvalidProject,
|
||||
},
|
||||
{
|
||||
name: "empty date",
|
||||
input: "action due:",
|
||||
expUpdate: &task.LocalUpdate{},
|
||||
expErr: command.ErrInvalidDate,
|
||||
},
|
||||
{
|
||||
name: "url",
|
||||
input: "https://ewintr.nl/something?arg=1",
|
||||
expUpdate: &task.LocalUpdate{
|
||||
Fields: []string{task.FIELD_ACTION},
|
||||
Action: "https://ewintr.nl/something?arg=1",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "misformatted date",
|
||||
input: "d:20-wrong",
|
||||
expUpdate: &task.LocalUpdate{},
|
||||
expErr: command.ErrInvalidDate,
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
args := strings.Split(tc.input, " ")
|
||||
act, err := format.ParseTaskFieldArgs(args)
|
||||
act, err := command.ParseTaskFieldArgs(args)
|
||||
test.Equals(t, tc.expUpdate, act)
|
||||
test.Assert(t, errors.Is(err, tc.expErr), "wrong err")
|
||||
})
|
|
@ -18,7 +18,7 @@ func NewNew(conf *configuration.Configuration, cmdArgs []string) (*New, error) {
|
|||
return &New{}, err
|
||||
}
|
||||
|
||||
update, err := format.ParseTaskFieldArgs(cmdArgs)
|
||||
update, err := ParseTaskFieldArgs(cmdArgs)
|
||||
if err != nil {
|
||||
return &New{}, err
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ func NewUpdate(localId int, conf *configuration.Configuration, cmdArgs []string)
|
|||
return &Update{}, err
|
||||
}
|
||||
|
||||
update, err := format.ParseTaskFieldArgs(cmdArgs)
|
||||
update, err := ParseTaskFieldArgs(cmdArgs)
|
||||
if err != nil {
|
||||
return &Update{}, err
|
||||
}
|
||||
|
|
|
@ -1,17 +1,11 @@
|
|||
package format
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"ewintr.nl/gte/internal/task"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrFieldAlreadyUsed = errors.New("field was already used")
|
||||
)
|
||||
|
||||
type Column int
|
||||
|
||||
const (
|
||||
|
@ -42,41 +36,3 @@ due: %s
|
|||
|
||||
return fmt.Sprintf("%s\n", output)
|
||||
}
|
||||
|
||||
func ParseTaskFieldArgs(args []string) (*task.LocalUpdate, error) {
|
||||
lu := &task.LocalUpdate{}
|
||||
|
||||
action, fields := []string{}, []string{}
|
||||
for _, f := range args {
|
||||
split := strings.SplitN(f, ":", 2)
|
||||
if len(split) == 2 {
|
||||
switch split[0] {
|
||||
case "project":
|
||||
if lu.Project != "" {
|
||||
return &task.LocalUpdate{}, fmt.Errorf("%w: %s", ErrFieldAlreadyUsed, task.FIELD_PROJECT)
|
||||
}
|
||||
lu.Project = split[1]
|
||||
fields = append(fields, task.FIELD_PROJECT)
|
||||
case "due":
|
||||
if !lu.Due.IsZero() {
|
||||
return &task.LocalUpdate{}, fmt.Errorf("%w: %s", ErrFieldAlreadyUsed, task.FIELD_DUE)
|
||||
}
|
||||
lu.Due = task.NewDateFromString(split[1])
|
||||
fields = append(fields, task.FIELD_DUE)
|
||||
}
|
||||
} else {
|
||||
if len(f) > 0 {
|
||||
action = append(action, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(action) > 0 {
|
||||
lu.Action = strings.Join(action, " ")
|
||||
fields = append(fields, task.FIELD_ACTION)
|
||||
}
|
||||
|
||||
lu.Fields = fields
|
||||
|
||||
return lu, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue