cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists ๐Ÿƒ
charm leaflet readability golang

chore: remove dead code

+25 -126
+15 -24
cmd/commands.go
··· 9 "github.com/stormlightlabs/noteleaf/internal/handlers" 10 ) 11 12 - func parseID(k string, args []string) (int64, error) { 13 - id, err := strconv.ParseInt(args[0], 10, 64) 14 - if err != nil { 15 - return id, fmt.Errorf("invalid %v ID: %s", k, args[0]) 16 - } 17 - 18 - return id, err 19 - } 20 - 21 // CommandGroup represents a group of related CLI commands 22 type CommandGroup interface { 23 Create() *cobra.Command ··· 203 204 Updates episode tracking and completion status. Can mark individual episodes 205 or complete seasons/series depending on ID format.`, 206 - Args: cobra.ExactArgs(1), 207 RunE: func(cmd *cobra.Command, args []string) error { 208 return c.handler.MarkWatched(cmd.Context(), args[0]) 209 }, ··· 328 Specify a percentage value between 0 and 100 to indicate how far you've 329 progressed through the book. Automatically updates status to 'reading' if not 330 already set.`, 331 - Args: cobra.ExactArgs(2), 332 RunE: func(cmd *cobra.Command, args []string) error { 333 progress, err := strconv.Atoi(args[1]) 334 if err != nil { ··· 345 346 Valid statuses are: queued (not started), reading (in progress), finished 347 (completed), or removed (no longer tracking).`, 348 - Args: cobra.ExactArgs(2), 349 RunE: func(cmd *cobra.Command, args []string) error { 350 return c.handler.UpdateStatus(cmd.Context(), args[0], args[1]) 351 }, ··· 359 handler *handlers.NoteHandler 360 } 361 362 - // NewNoteCommand creates a new NoteCommand with the given handler 363 func NewNoteCommand(handler *handlers.NoteHandler) *NoteCommand { 364 return &NoteCommand{handler: handler} 365 } ··· 445 446 Shows the note with syntax highlighting, proper formatting, and metadata. 447 Useful for quick viewing without opening an editor.`, 448 - Args: cobra.ExactArgs(1), 449 RunE: func(cmd *cobra.Command, args []string) error { 450 - if noteID, err := parseID("note", args); err != nil { 451 return err 452 } else { 453 defer c.handler.Close() ··· 464 Uses the editor specified in your noteleaf configuration or the EDITOR 465 environment variable. Changes are automatically saved when you close the 466 editor.`, 467 - Args: cobra.ExactArgs(1), 468 RunE: func(cmd *cobra.Command, args []string) error { 469 - if noteID, err := parseID("note", args); err != nil { 470 return err 471 } else { 472 defer c.handler.Close() ··· 483 484 Removes both the markdown file and database metadata. This operation cannot be 485 undone. You will be prompted for confirmation before deletion.`, 486 - Args: cobra.ExactArgs(1), 487 RunE: func(cmd *cobra.Command, args []string) error { 488 - if noteID, err := parseID("note", args); err != nil { 489 return err 490 } else { 491 defer c.handler.Close() ··· 566 567 Shows article title, author, publication date, URL, and a brief content 568 preview. Use 'read' command to view the full article content.`, 569 - Args: cobra.ExactArgs(1), 570 RunE: func(cmd *cobra.Command, args []string) error { 571 - if articleID, err := parseID("article", args); err != nil { 572 return err 573 } else { 574 defer c.handler.Close() ··· 586 This displays the complete article content using syntax highlighting and proper formatting.`, 587 Args: cobra.ExactArgs(1), 588 RunE: func(cmd *cobra.Command, args []string) error { 589 - if articleID, err := parseID("article", args); err != nil { 590 return err 591 } else { 592 defer c.handler.Close() ··· 604 605 Removes the article metadata from the database and deletes associated markdown 606 and HTML files. This operation cannot be undone.`, 607 - Args: cobra.ExactArgs(1), 608 RunE: func(cmd *cobra.Command, args []string) error { 609 - if articleID, err := parseID("article", args); err != nil { 610 return err 611 } else { 612 defer c.handler.Close()
··· 9 "github.com/stormlightlabs/noteleaf/internal/handlers" 10 ) 11 12 // CommandGroup represents a group of related CLI commands 13 type CommandGroup interface { 14 Create() *cobra.Command ··· 194 195 Updates episode tracking and completion status. Can mark individual episodes 196 or complete seasons/series depending on ID format.`, 197 + Args: cobra.ExactArgs(1), 198 RunE: func(cmd *cobra.Command, args []string) error { 199 return c.handler.MarkWatched(cmd.Context(), args[0]) 200 }, ··· 319 Specify a percentage value between 0 and 100 to indicate how far you've 320 progressed through the book. Automatically updates status to 'reading' if not 321 already set.`, 322 + Args: cobra.ExactArgs(2), 323 RunE: func(cmd *cobra.Command, args []string) error { 324 progress, err := strconv.Atoi(args[1]) 325 if err != nil { ··· 336 337 Valid statuses are: queued (not started), reading (in progress), finished 338 (completed), or removed (no longer tracking).`, 339 + Args: cobra.ExactArgs(2), 340 RunE: func(cmd *cobra.Command, args []string) error { 341 return c.handler.UpdateStatus(cmd.Context(), args[0], args[1]) 342 }, ··· 350 handler *handlers.NoteHandler 351 } 352 353 + // NewNoteCommand creates a new [NoteCommand] with the given handler 354 func NewNoteCommand(handler *handlers.NoteHandler) *NoteCommand { 355 return &NoteCommand{handler: handler} 356 } ··· 436 437 Shows the note with syntax highlighting, proper formatting, and metadata. 438 Useful for quick viewing without opening an editor.`, 439 + Args: cobra.ExactArgs(1), 440 RunE: func(cmd *cobra.Command, args []string) error { 441 + if noteID, err := handlers.ParseID(args[0], "note"); err != nil { 442 return err 443 } else { 444 defer c.handler.Close() ··· 455 Uses the editor specified in your noteleaf configuration or the EDITOR 456 environment variable. Changes are automatically saved when you close the 457 editor.`, 458 + Args: cobra.ExactArgs(1), 459 RunE: func(cmd *cobra.Command, args []string) error { 460 + if noteID, err := handlers.ParseID(args[0], "note"); err != nil { 461 return err 462 } else { 463 defer c.handler.Close() ··· 474 475 Removes both the markdown file and database metadata. This operation cannot be 476 undone. You will be prompted for confirmation before deletion.`, 477 + Args: cobra.ExactArgs(1), 478 RunE: func(cmd *cobra.Command, args []string) error { 479 + if noteID, err := handlers.ParseID(args[0], "note"); err != nil { 480 return err 481 } else { 482 defer c.handler.Close() ··· 557 558 Shows article title, author, publication date, URL, and a brief content 559 preview. Use 'read' command to view the full article content.`, 560 + Args: cobra.ExactArgs(1), 561 RunE: func(cmd *cobra.Command, args []string) error { 562 + if articleID, err := handlers.ParseID(args[0], "article"); err != nil { 563 return err 564 } else { 565 defer c.handler.Close() ··· 577 This displays the complete article content using syntax highlighting and proper formatting.`, 578 Args: cobra.ExactArgs(1), 579 RunE: func(cmd *cobra.Command, args []string) error { 580 + if articleID, err := handlers.ParseID(args[0], "article"); err != nil { 581 return err 582 } else { 583 defer c.handler.Close() ··· 595 596 Removes the article metadata from the database and deletes associated markdown 597 and HTML files. This operation cannot be undone.`, 598 + Args: cobra.ExactArgs(1), 599 RunE: func(cmd *cobra.Command, args []string) error { 600 + if articleID, err := handlers.ParseID(args[0], "article"); err != nil { 601 return err 602 } else { 603 defer c.handler.Close()
+10
internal/handlers/handlers.go
··· 6 "io" 7 "os" 8 "path/filepath" 9 10 "github.com/stormlightlabs/noteleaf/internal/store" 11 "github.com/stormlightlabs/noteleaf/internal/utils" 12 ) 13 14 // Setup initializes the application database and configuration 15 func Setup(ctx context.Context, args []string) error {
··· 6 "io" 7 "os" 8 "path/filepath" 9 + "strconv" 10 11 "github.com/stormlightlabs/noteleaf/internal/store" 12 "github.com/stormlightlabs/noteleaf/internal/utils" 13 ) 14 + 15 + // ParseID converts a string ID to int64 16 + func ParseID(id string, itemType string) (int64, error) { 17 + itemID, err := strconv.ParseInt(id, 10, 64) 18 + if err != nil { 19 + return 0, fmt.Errorf("invalid %s ID: %s", itemType, id) 20 + } 21 + return itemID, nil 22 + } 23 24 // Setup initializes the application database and configuration 25 func Setup(ctx context.Context, args []string) error {
-102
internal/handlers/media_utilities.go
··· 1 - package handlers 2 - 3 - import ( 4 - "context" 5 - "fmt" 6 - "io" 7 - "strconv" 8 - 9 - "github.com/stormlightlabs/noteleaf/internal/models" 10 - ) 11 - 12 - // MediaPrinter defines how to format a media item for display 13 - type MediaPrinter[T any] func(item *T) 14 - 15 - // ListMediaItems is a generic utility for listing media items with status filtering 16 - func ListMediaItems[T any]( 17 - ctx context.Context, 18 - status string, 19 - mediaType string, 20 - listAll func(ctx context.Context) ([]*T, error), 21 - listByStatus func(ctx context.Context, status string) ([]*T, error), 22 - printer MediaPrinter[T], 23 - ) error { 24 - var items []*T 25 - var err error 26 - 27 - if status == "" { 28 - items, err = listAll(ctx) 29 - if err != nil { 30 - return fmt.Errorf("failed to list %s: %w", mediaType, err) 31 - } 32 - } else { 33 - items, err = listByStatus(ctx, status) 34 - if err != nil { 35 - return fmt.Errorf("failed to get %s %s: %w", status, mediaType, err) 36 - } 37 - } 38 - 39 - if len(items) == 0 { 40 - if status == "" { 41 - fmt.Printf("No %s found\n", mediaType) 42 - } else { 43 - fmt.Printf("No %s %s found\n", status, mediaType) 44 - } 45 - return nil 46 - } 47 - 48 - fmt.Printf("Found %d %s:\n\n", len(items), mediaType) 49 - for _, item := range items { 50 - printer(item) 51 - } 52 - 53 - return nil 54 - } 55 - 56 - // PromptUserChoice prompts the user to select from a list of results 57 - func PromptUserChoice(reader io.Reader, maxChoices int) (int, error) { 58 - fmt.Print("\nEnter number to add (1-", maxChoices, "), or 0 to cancel: ") 59 - 60 - var choice int 61 - if reader != nil { 62 - if _, err := fmt.Fscanf(reader, "%d", &choice); err != nil { 63 - return 0, fmt.Errorf("invalid input") 64 - } 65 - } else { 66 - if _, err := fmt.Scanf("%d", &choice); err != nil { 67 - return 0, fmt.Errorf("invalid input") 68 - } 69 - } 70 - 71 - if choice == 0 { 72 - fmt.Println("Cancelled.") 73 - return 0, nil 74 - } 75 - if choice < 1 || choice > maxChoices { 76 - return 0, fmt.Errorf("invalid choice: %d", choice) 77 - } 78 - return choice, nil 79 - } 80 - 81 - // ParseID converts a string ID to int64 82 - func ParseID(id string, itemType string) (int64, error) { 83 - itemID, err := strconv.ParseInt(id, 10, 64) 84 - if err != nil { 85 - return 0, fmt.Errorf("invalid %s ID: %s", itemType, id) 86 - } 87 - return itemID, nil 88 - } 89 - 90 - // PrintSearchResults displays search results with a type-specific formatter 91 - func PrintSearchResults[T models.Model](results []*models.Model, formatter func(*models.Model, int)) error { 92 - if len(results) == 0 { 93 - fmt.Println("No results found.") 94 - return nil 95 - } 96 - 97 - fmt.Printf("Found %d result(s):\n\n", len(results)) 98 - for i, result := range results { 99 - formatter(result, i+1) 100 - } 101 - return nil 102 - }
···