From 2b12b74285b4d32f42b9c49da877ed53552382aa Mon Sep 17 00:00:00 2001 From: nicknickel Date: Tue, 21 Feb 2023 21:25:28 +0000 Subject: [PATCH 1/2] add ability to list note timestamps --- pkg/cli/cmd/ls/ls.go | 22 ++++++++++++++-------- pkg/cli/cmd/view/view.go | 10 ++++++++-- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/pkg/cli/cmd/ls/ls.go b/pkg/cli/cmd/ls/ls.go index 9f22ab4e..265d4516 100644 --- a/pkg/cli/cmd/ls/ls.go +++ b/pkg/cli/cmd/ls/ls.go @@ -22,6 +22,7 @@ import ( "database/sql" "fmt" "strings" + "time" "github.com/dnote/dnote/pkg/cli/context" "github.com/dnote/dnote/pkg/cli/infra" @@ -58,7 +59,7 @@ func NewCmd(ctx context.DnoteCtx) *cobra.Command { Aliases: []string{"l", "notes"}, Short: "List all notes", Example: example, - RunE: NewRun(ctx, false), + RunE: NewRun(ctx, false, false), PreRunE: preRun, Deprecated: deprecationWarning, } @@ -67,7 +68,7 @@ func NewCmd(ctx context.DnoteCtx) *cobra.Command { } // NewRun returns a new run function for ls -func NewRun(ctx context.DnoteCtx, nameOnly bool) infra.RunEFunc { +func NewRun(ctx context.DnoteCtx, nameOnly bool, timestamps bool) infra.RunEFunc { return func(cmd *cobra.Command, args []string) error { if len(args) == 0 { if err := printBooks(ctx, nameOnly); err != nil { @@ -78,7 +79,7 @@ func NewRun(ctx context.DnoteCtx, nameOnly bool) infra.RunEFunc { } bookName := args[0] - if err := printNotes(ctx, bookName); err != nil { + if err := printNotes(ctx, bookName, timestamps); err != nil { return errors.Wrapf(err, "viewing book '%s'", bookName) } @@ -95,6 +96,7 @@ type bookInfo struct { // noteInfo is an information about the note to be printed on screen type noteInfo struct { RowID int + AddedOn int64 Body string } @@ -166,7 +168,7 @@ func printBooks(ctx context.DnoteCtx, nameOnly bool) error { return nil } -func printNotes(ctx context.DnoteCtx, bookName string) error { +func printNotes(ctx context.DnoteCtx, bookName string, timestamps bool) error { db := ctx.DB var bookUUID string @@ -177,7 +179,7 @@ func printNotes(ctx context.DnoteCtx, bookName string) error { return errors.Wrap(err, "querying the book") } - rows, err := db.Query(`SELECT rowid, body FROM notes WHERE book_uuid = ? AND deleted = ? ORDER BY added_on ASC;`, bookUUID, false) + rows, err := db.Query(`SELECT rowid, added_on, body FROM notes WHERE book_uuid = ? AND deleted = ? ORDER BY added_on ASC;`, bookUUID, false) if err != nil { return errors.Wrap(err, "querying notes") } @@ -186,7 +188,7 @@ func printNotes(ctx context.DnoteCtx, bookName string) error { infos := []noteInfo{} for rows.Next() { var info noteInfo - err = rows.Scan(&info.RowID, &info.Body) + err = rows.Scan(&info.RowID, &info.AddedOn, &info.Body) if err != nil { return errors.Wrap(err, "scanning a row") } @@ -199,12 +201,16 @@ func printNotes(ctx context.DnoteCtx, bookName string) error { for _, info := range infos { body, isExcerpt := formatBody(info.Body) - rowid := log.ColorYellow.Sprintf("(%d)", info.RowID) + preface := log.ColorYellow.Sprintf("(%d)", info.RowID) + if timestamps { + local_time := time.Unix(0, info.AddedOn).Format(time.DateTime) + preface = log.ColorYellow.Sprintf("(%s)", local_time) + } if isExcerpt { body = fmt.Sprintf("%s %s", body, log.ColorYellow.Sprintf("[---More---]")) } - log.Plainf("%s %s\n", rowid, body) + log.Plainf("%s %s\n", preface, body) } return nil diff --git a/pkg/cli/cmd/view/view.go b/pkg/cli/cmd/view/view.go index cc39a451..b3bb1b9b 100644 --- a/pkg/cli/cmd/view/view.go +++ b/pkg/cli/cmd/view/view.go @@ -42,6 +42,7 @@ var example = ` var nameOnly bool var contentOnly bool +var timestamps bool func preRun(cmd *cobra.Command, args []string) error { if len(args) > 2 { @@ -65,6 +66,7 @@ func NewCmd(ctx context.DnoteCtx) *cobra.Command { f := cmd.Flags() f.BoolVarP(&nameOnly, "name-only", "", false, "print book names only") f.BoolVarP(&contentOnly, "content-only", "", false, "print the note content only") + f.BoolVarP(×tamps, "timestamps", "t", false, "print creation timestamp of notes rather than IDs") return cmd } @@ -74,7 +76,11 @@ func newRun(ctx context.DnoteCtx) infra.RunEFunc { var run infra.RunEFunc if len(args) == 0 { - run = ls.NewRun(ctx, nameOnly) + if timestamps { + return errors.New("timestamps flag is only valid when viewing notes") + } + + run = ls.NewRun(ctx, nameOnly, false) } else if len(args) == 1 { if nameOnly { return errors.New("--name-only flag is only valid when viewing books") @@ -83,7 +89,7 @@ func newRun(ctx context.DnoteCtx) infra.RunEFunc { if utils.IsNumber(args[0]) { run = cat.NewRun(ctx, contentOnly) } else { - run = ls.NewRun(ctx, false) + run = ls.NewRun(ctx, false, timestamps) } } else if len(args) == 2 { // DEPRECATED: passing book name to view command is deprecated From 8e2437ee7da233530a2f403f0135c8ce1c871f4e Mon Sep 17 00:00:00 2001 From: nicknickel Date: Wed, 1 Mar 2023 21:04:44 +0000 Subject: [PATCH 2/2] move print note line to separate function and add tests --- pkg/cli/cmd/ls/ls.go | 29 +++++++++++++++++------------ pkg/cli/main_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/pkg/cli/cmd/ls/ls.go b/pkg/cli/cmd/ls/ls.go index 265d4516..84332fe5 100644 --- a/pkg/cli/cmd/ls/ls.go +++ b/pkg/cli/cmd/ls/ls.go @@ -168,6 +168,22 @@ func printBooks(ctx context.DnoteCtx, nameOnly bool) error { return nil } +func printNoteLine(info noteInfo, showTimestamp bool) { + body, isExcerpt := formatBody(info.Body) + + rowid := log.ColorYellow.Sprintf("(%d)", info.RowID) + preface := "" + if showTimestamp { + local_time := time.Unix(0, info.AddedOn).Format(time.DateTime) + preface = log.ColorYellow.Sprintf(" [%s]", local_time) + } + if isExcerpt { + body = fmt.Sprintf("%s %s", body, log.ColorYellow.Sprintf("[---More---]")) + } + + log.Plainf("%s%s %s\n", rowid, preface, body) +} + func printNotes(ctx context.DnoteCtx, bookName string, timestamps bool) error { db := ctx.DB @@ -199,18 +215,7 @@ func printNotes(ctx context.DnoteCtx, bookName string, timestamps bool) error { log.Infof("on book %s\n", bookName) for _, info := range infos { - body, isExcerpt := formatBody(info.Body) - - preface := log.ColorYellow.Sprintf("(%d)", info.RowID) - if timestamps { - local_time := time.Unix(0, info.AddedOn).Format(time.DateTime) - preface = log.ColorYellow.Sprintf("(%s)", local_time) - } - if isExcerpt { - body = fmt.Sprintf("%s %s", body, log.ColorYellow.Sprintf("[---More---]")) - } - - log.Plainf("%s %s\n", preface, body) + printNoteLine(info, timestamps) } return nil diff --git a/pkg/cli/main_test.go b/pkg/cli/main_test.go index 4f68e9b3..21382329 100644 --- a/pkg/cli/main_test.go +++ b/pkg/cli/main_test.go @@ -105,6 +105,39 @@ func TestInit(t *testing.T) { assert.NotEqual(t, lastSyncAt, "", "last sync at should not be empty") } +func TestViewNote(t *testing.T) { + // tests successful if command does not return an error + t.Run("using default", func(t *testing.T) { + // Setup + db := database.InitTestDB(t, fmt.Sprintf("%s/%s/%s", testDir, consts.DnoteDirName, consts.DnoteDBFileName), nil) + testutils.Setup3(t, db) + + // Execute + testutils.RunDnoteCmd(t, opts, binaryName, "view", "js") + defer testutils.RemoveDir(t, testDir) + }) + + t.Run("content only", func(t *testing.T) { + // Setup + db := database.InitTestDB(t, fmt.Sprintf("%s/%s/%s", testDir, consts.DnoteDirName, consts.DnoteDBFileName), nil) + testutils.Setup3(t, db) + + // Execute + testutils.RunDnoteCmd(t, opts, binaryName, "view", "js", "--content-only") + defer testutils.RemoveDir(t, testDir) + }) + + t.Run("with timestamps", func(t *testing.T) { + // Setup + db := database.InitTestDB(t, fmt.Sprintf("%s/%s/%s", testDir, consts.DnoteDirName, consts.DnoteDBFileName), nil) + testutils.Setup3(t, db) + + // Execute + testutils.RunDnoteCmd(t, opts, binaryName, "view", "js", "-t") + defer testutils.RemoveDir(t, testDir) + }) +} + func TestAddNote(t *testing.T) { t.Run("new book", func(t *testing.T) { // Set up and execute