improve cli field args parser

This commit is contained in:
Erik Winter 2022-09-28 08:49:25 +02:00
parent d53363f1ca
commit 248edf6379
5 changed files with 110 additions and 50 deletions

View File

@ -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
}

View File

@ -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")
})

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}