cli + tui to publish to leaflet (wip) & manage tasks, notes & watch/read lists 馃崈
charm leaflet readability golang
29
fork

Configure Feed

Select the types of activity you want to include in your feed.

at d631904bbdd17c4c85e83012b4eae79459a04a9c 204 lines 5.1 kB view raw
1package main 2 3import ( 4 "context" 5 "fmt" 6 "os" 7 "strings" 8 9 "github.com/charmbracelet/fang" 10 "github.com/charmbracelet/log" 11 "github.com/spf13/cobra" 12 "github.com/stormlightlabs/noteleaf/internal/handlers" 13 "github.com/stormlightlabs/noteleaf/internal/store" 14 "github.com/stormlightlabs/noteleaf/internal/ui" 15 "github.com/stormlightlabs/noteleaf/internal/utils" 16) 17 18// App represents the main CLI application 19type App struct { 20 db *store.Database 21 config *store.Config 22} 23 24// NewApp creates a new CLI application instance 25func NewApp() (*App, error) { 26 db, err := store.NewDatabase() 27 if err != nil { 28 return nil, fmt.Errorf("failed to initialize database: %w", err) 29 } 30 31 if config, err := store.LoadConfig(); err != nil { 32 return nil, fmt.Errorf("failed to load configuration: %w", err) 33 } else { 34 return &App{db, config}, nil 35 } 36} 37 38// Close cleans up application resources 39func (app *App) Close() error { 40 if app.db != nil { 41 return app.db.Close() 42 } 43 return nil 44} 45 46func statusCmd() *cobra.Command { 47 return &cobra.Command{ 48 Use: "status", 49 Short: "Show application status and configuration", 50 RunE: func(cmd *cobra.Command, args []string) error { 51 return handlers.Status(cmd.Context(), args) 52 }, 53 } 54} 55 56func resetCmd() *cobra.Command { 57 return &cobra.Command{ 58 Use: "reset", 59 Short: "Reset the application (removes all data)", 60 RunE: func(cmd *cobra.Command, args []string) error { 61 return handlers.Reset(cmd.Context(), args) 62 }, 63 } 64} 65 66func rootCmd() *cobra.Command { 67 root := &cobra.Command{ 68 Use: "noteleaf", 69 Long: ui.Georgia.ColoredInViewport(), 70 Short: "A TaskWarrior-inspired CLI with notes, media queues and reading lists", 71 RunE: func(c *cobra.Command, args []string) error { 72 if len(args) == 0 { 73 return c.Help() 74 } 75 76 output := strings.Join(args, " ") 77 fmt.Println(output) 78 return nil 79 }, 80 } 81 82 root.SetHelpCommand(&cobra.Command{Hidden: true}) 83 cobra.EnableCommandSorting = false 84 85 root.AddGroup(&cobra.Group{ID: "core", Title: "Core Commands:"}) 86 root.AddGroup(&cobra.Group{ID: "management", Title: "Management Commands:"}) 87 return root 88} 89 90func setupCmd() *cobra.Command { 91 handler, err := handlers.NewSeedHandler() 92 if err != nil { 93 log.Fatalf("failed to instantiate seed handler: %v", err) 94 } 95 96 root := &cobra.Command{ 97 Use: "setup", 98 Short: "Initialize and manage application setup", 99 RunE: func(c *cobra.Command, args []string) error { 100 return handlers.Setup(c.Context(), args) 101 }, 102 } 103 104 seedCmd := &cobra.Command{ 105 Use: "seed", 106 Short: "Populate database with test data", 107 Long: "Add sample tasks, books, and notes to the database for testing and demonstration purposes", 108 RunE: func(c *cobra.Command, args []string) error { 109 force, _ := c.Flags().GetBool("force") 110 return handler.Seed(c.Context(), force) 111 }, 112 } 113 seedCmd.Flags().BoolP("force", "f", false, "Clear existing data and re-seed") 114 115 root.AddCommand(seedCmd) 116 return root 117} 118 119func confCmd() *cobra.Command { 120 handler, err := handlers.NewConfigHandler() 121 if err != nil { 122 log.Fatalf("failed to create config handler: %v", err) 123 } 124 return NewConfigCommand(handler).Create() 125} 126 127func main() { 128 logger := utils.NewLogger("info", "text") 129 utils.Logger = logger 130 131 app, err := NewApp() 132 if err != nil { 133 logger.Fatal("Failed to initialize application", "error", err) 134 } 135 defer app.Close() 136 137 taskHandler, err := handlers.NewTaskHandler() 138 if err != nil { 139 log.Fatalf("failed to create task handler: %v", err) 140 } 141 142 movieHandler, err := handlers.NewMovieHandler() 143 if err != nil { 144 log.Fatalf("failed to create movie handler: %v", err) 145 } 146 147 tvHandler, err := handlers.NewTVHandler() 148 if err != nil { 149 log.Fatalf("failed to create TV handler: %v", err) 150 } 151 152 noteHandler, err := handlers.NewNoteHandler() 153 if err != nil { 154 log.Fatalf("failed to create note handler: %v", err) 155 } 156 157 bookHandler, err := handlers.NewBookHandler() 158 if err != nil { 159 log.Fatalf("failed to create book handler: %v", err) 160 } 161 162 articleHandler, err := handlers.NewArticleHandler() 163 if err != nil { 164 log.Fatalf("failed to create article handler: %v", err) 165 } 166 167 root := rootCmd() 168 169 coreGroups := []CommandGroup{ 170 NewTaskCommand(taskHandler), 171 NewNoteCommand(noteHandler), 172 NewArticleCommand(articleHandler), 173 } 174 175 for _, group := range coreGroups { 176 cmd := group.Create() 177 cmd.GroupID = "core" 178 root.AddCommand(cmd) 179 } 180 181 mediaCmd := &cobra.Command{Use: "media", Short: "Manage media queues (books, movies, TV shows)"} 182 mediaCmd.GroupID = "core" 183 mediaCmd.AddCommand(NewMovieCommand(movieHandler).Create()) 184 mediaCmd.AddCommand(NewTVCommand(tvHandler).Create()) 185 mediaCmd.AddCommand(NewBookCommand(bookHandler).Create()) 186 root.AddCommand(mediaCmd) 187 188 mgmt := []func() *cobra.Command{statusCmd, confCmd, setupCmd, resetCmd} 189 for _, cmdFunc := range mgmt { 190 cmd := cmdFunc() 191 cmd.GroupID = "management" 192 root.AddCommand(cmd) 193 } 194 195 opts := []fang.Option{ 196 fang.WithVersion("0.1.0"), 197 fang.WithoutCompletions(), 198 fang.WithColorSchemeFunc(ui.NoteleafColorScheme), 199 } 200 201 if err := fang.Execute(context.Background(), root, opts...); err != nil { 202 os.Exit(1) 203 } 204}