This commit is contained in:
Zach Nickel 2025-11-01 14:22:31 -07:00 committed by GitHub
commit 79606b81f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 66 additions and 16 deletions

View file

@ -19,6 +19,7 @@ import (
"database/sql"
"fmt"
"strings"
"time"
"github.com/dnote/dnote/pkg/cli/context"
"github.com/dnote/dnote/pkg/cli/infra"
@ -55,7 +56,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,
}
@ -64,7 +65,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 {
@ -75,7 +76,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)
}
@ -92,6 +93,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
}
@ -163,7 +165,23 @@ func printBooks(ctx context.DnoteCtx, nameOnly bool) error {
return nil
}
func printNotes(ctx context.DnoteCtx, bookName string) error {
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
var bookUUID string
@ -174,7 +192,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")
}
@ -183,7 +201,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")
}
@ -194,14 +212,7 @@ func printNotes(ctx context.DnoteCtx, bookName string) error {
log.Infof("on book %s\n", bookName)
for _, info := range infos {
body, isExcerpt := formatBody(info.Body)
rowid := log.ColorYellow.Sprintf("(%d)", info.RowID)
if isExcerpt {
body = fmt.Sprintf("%s %s", body, log.ColorYellow.Sprintf("[---More---]"))
}
log.Plainf("%s %s\n", rowid, body)
printNoteLine(info, timestamps)
}
return nil

View file

@ -39,6 +39,7 @@ var example = `
var nameOnly bool
var contentOnly bool
var timestamps bool
func preRun(cmd *cobra.Command, args []string) error {
if len(args) > 2 {
@ -62,6 +63,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(&timestamps, "timestamps", "t", false, "print creation timestamp of notes rather than IDs")
return cmd
}
@ -71,7 +73,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")
@ -80,7 +86,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

View file

@ -106,6 +106,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) {
testDir, opts := setupTestEnv(t)