This commit is contained in:
Erik Winter 2024-12-29 09:32:49 +01:00
parent c209ba6197
commit bd1c0136a9
7 changed files with 213 additions and 0 deletions

View File

@ -44,6 +44,7 @@ func NewCLI(deps Dependencies) *CLI {
return &CLI{
deps: deps,
cmdArgs: []CommandArgs{
NewShowArgs(),
NewAddArgs(), NewDeleteArgs(), NewListArgs(),
NewSyncArgs(), NewUpdateArgs(),
},

View File

@ -1 +1,70 @@
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
}

96
plan/format/format.go Normal file
View File

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

View File

@ -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) {
ml.mutex.RLock()
defer ml.mutex.RUnlock()

View File

@ -54,6 +54,21 @@ func TestLocalID(t *testing.T) {
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()
if actErr != nil {
t.Errorf("exp nil, got %v", actErr)

View File

@ -2,6 +2,7 @@ package sqlite
import (
"database/sql"
"errors"
"fmt"
"go-mod.ewintr.nl/planner/plan/storage"
@ -11,6 +12,23 @@ type LocalID struct {
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) {
rows, err := l.db.Query(`
SELECT id, local_id

View File

@ -13,6 +13,7 @@ var (
)
type LocalID interface {
FindOne(lid int) (string, error)
FindAll() (map[string]int, error)
FindOrNext(id string) (int, error)
Next() (int, error)