show
This commit is contained in:
parent
c209ba6197
commit
bd1c0136a9
|
@ -44,6 +44,7 @@ func NewCLI(deps Dependencies) *CLI {
|
||||||
return &CLI{
|
return &CLI{
|
||||||
deps: deps,
|
deps: deps,
|
||||||
cmdArgs: []CommandArgs{
|
cmdArgs: []CommandArgs{
|
||||||
|
NewShowArgs(),
|
||||||
NewAddArgs(), NewDeleteArgs(), NewListArgs(),
|
NewAddArgs(), NewDeleteArgs(), NewListArgs(),
|
||||||
NewSyncArgs(), NewUpdateArgs(),
|
NewSyncArgs(), NewUpdateArgs(),
|
||||||
},
|
},
|
||||||
|
|
|
@ -1 +1,70 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"go-mod.ewintr.nl/planner/plan/format"
|
||||||
|
"go-mod.ewintr.nl/planner/plan/storage"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ShowArgs struct {
|
||||||
|
localID int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewShowArgs() ShowArgs {
|
||||||
|
return ShowArgs{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sa ShowArgs) Parse(main []string, fields map[string]string) (Command, error) {
|
||||||
|
if len(main) != 1 {
|
||||||
|
return nil, ErrWrongCommand
|
||||||
|
}
|
||||||
|
lid, err := strconv.Atoi(main[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, ErrWrongCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Show{
|
||||||
|
args: ShowArgs{
|
||||||
|
localID: lid,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Show struct {
|
||||||
|
args ShowArgs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Show) Do(deps Dependencies) error {
|
||||||
|
id, err := deps.LocalIDRepo.FindOne(s.args.localID)
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, storage.ErrNotFound):
|
||||||
|
return fmt.Errorf("could not find local id")
|
||||||
|
case err != nil:
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tsk, err := deps.TaskRepo.Find(id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not find task")
|
||||||
|
}
|
||||||
|
|
||||||
|
var recurStr string
|
||||||
|
if tsk.Recurrer != nil {
|
||||||
|
recurStr = tsk.Recurrer.String()
|
||||||
|
}
|
||||||
|
data := [][]string{
|
||||||
|
{"title", tsk.Title},
|
||||||
|
{"local id", fmt.Sprintf("%d", s.args.localID)},
|
||||||
|
{"date", tsk.Date.String()},
|
||||||
|
{"time", tsk.Time.String()},
|
||||||
|
{"duration", tsk.Duration.String()},
|
||||||
|
{"recur", recurStr},
|
||||||
|
// {"id", tsk.ID},
|
||||||
|
}
|
||||||
|
fmt.Printf("\n%s\n", format.Table(data))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
package format
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Table(data [][]string) string {
|
||||||
|
if len(data) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// make all cells in a column the same width
|
||||||
|
max := make([]int, len(data[0]))
|
||||||
|
for _, row := range data {
|
||||||
|
for c, cell := range row {
|
||||||
|
if len(cell) > max[c] {
|
||||||
|
max[c] = len(cell)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for r, row := range data {
|
||||||
|
for c, cell := range row {
|
||||||
|
for s := len(cell); s < max[c]; s++ {
|
||||||
|
data[r][c] += " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make it smaller if the result is too wide
|
||||||
|
// only by making the widest column smaller for now
|
||||||
|
maxWidth := findTermWidth()
|
||||||
|
if maxWidth != 0 {
|
||||||
|
width := len(max) - 1
|
||||||
|
for _, m := range max {
|
||||||
|
width += m
|
||||||
|
}
|
||||||
|
shortenWith := width - maxWidth
|
||||||
|
widestColNo, widestColLen := 0, 0
|
||||||
|
for i, m := range max {
|
||||||
|
if m > widestColLen {
|
||||||
|
widestColNo, widestColLen = i, m
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newTaskColWidth := max[widestColNo] - shortenWith
|
||||||
|
if newTaskColWidth < 0 {
|
||||||
|
return "table is too wide to display\n"
|
||||||
|
}
|
||||||
|
if newTaskColWidth < max[widestColNo] {
|
||||||
|
for r, row := range data {
|
||||||
|
data[r][widestColNo] = row[widestColNo][:newTaskColWidth]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// print the rows
|
||||||
|
var output string
|
||||||
|
for _, row := range data {
|
||||||
|
// if r%3 == 0 {
|
||||||
|
// output += fmt.Sprintf("%s", "\x1b[48;5;237m")
|
||||||
|
// }
|
||||||
|
for c, col := range row {
|
||||||
|
output += col
|
||||||
|
if c != len(row)-1 {
|
||||||
|
output += " "
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if r%3 == 0 {
|
||||||
|
// output += fmt.Sprintf("%s", "\x1b[49m")
|
||||||
|
// }
|
||||||
|
output += "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func findTermWidth() int {
|
||||||
|
cmd := exec.Command("stty", "size")
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
out, err := cmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
s := string(out)
|
||||||
|
s = strings.TrimSpace(s)
|
||||||
|
sArr := strings.Split(s, " ")
|
||||||
|
|
||||||
|
width, err := strconv.Atoi(sArr[1])
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return width
|
||||||
|
}
|
|
@ -18,6 +18,19 @@ func NewLocalID() *LocalID {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ml *LocalID) FindOne(lid int) (string, error) {
|
||||||
|
ml.mutex.RLock()
|
||||||
|
defer ml.mutex.RUnlock()
|
||||||
|
|
||||||
|
for id, l := range ml.ids {
|
||||||
|
if lid == l {
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", storage.ErrNotFound
|
||||||
|
}
|
||||||
|
|
||||||
func (ml *LocalID) FindAll() (map[string]int, error) {
|
func (ml *LocalID) FindAll() (map[string]int, error) {
|
||||||
ml.mutex.RLock()
|
ml.mutex.RLock()
|
||||||
defer ml.mutex.RUnlock()
|
defer ml.mutex.RUnlock()
|
||||||
|
|
|
@ -54,6 +54,21 @@ func TestLocalID(t *testing.T) {
|
||||||
t.Errorf("exp 2, got %v", actLid)
|
t.Errorf("exp 2, got %v", actLid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Log("find by local id")
|
||||||
|
actID, actErr := repo.FindOne(1)
|
||||||
|
if actErr != nil {
|
||||||
|
t.Errorf("exp nil, got %v", actErr)
|
||||||
|
}
|
||||||
|
if actID != "test" {
|
||||||
|
t.Errorf("exp test, got %v", actID)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Log("unknown local id")
|
||||||
|
actID, actErr = repo.FindOne(2)
|
||||||
|
if !errors.Is(actErr, storage.ErrNotFound) {
|
||||||
|
t.Errorf("exp ErrNotFound, got %v", actErr)
|
||||||
|
}
|
||||||
|
|
||||||
actIDs, actErr = repo.FindAll()
|
actIDs, actErr = repo.FindAll()
|
||||||
if actErr != nil {
|
if actErr != nil {
|
||||||
t.Errorf("exp nil, got %v", actErr)
|
t.Errorf("exp nil, got %v", actErr)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package sqlite
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"go-mod.ewintr.nl/planner/plan/storage"
|
"go-mod.ewintr.nl/planner/plan/storage"
|
||||||
|
@ -11,6 +12,23 @@ type LocalID struct {
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *LocalID) FindOne(lid int) (string, error) {
|
||||||
|
var id string
|
||||||
|
err := l.db.QueryRow(`
|
||||||
|
SELECT id
|
||||||
|
FROM localids
|
||||||
|
WHERE local_id = ?
|
||||||
|
`, lid).Scan(&id)
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, sql.ErrNoRows):
|
||||||
|
return "", storage.ErrNotFound
|
||||||
|
case err != nil:
|
||||||
|
return "", fmt.Errorf("%w: %v", ErrSqliteFailure, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (l *LocalID) FindAll() (map[string]int, error) {
|
func (l *LocalID) FindAll() (map[string]int, error) {
|
||||||
rows, err := l.db.Query(`
|
rows, err := l.db.Query(`
|
||||||
SELECT id, local_id
|
SELECT id, local_id
|
||||||
|
|
|
@ -13,6 +13,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type LocalID interface {
|
type LocalID interface {
|
||||||
|
FindOne(lid int) (string, error)
|
||||||
FindAll() (map[string]int, error)
|
FindAll() (map[string]int, error)
|
||||||
FindOrNext(id string) (int, error)
|
FindOrNext(id string) (int, error)
|
||||||
Next() (int, error)
|
Next() (int, error)
|
||||||
|
|
Loading…
Reference in New Issue