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 d2c4ecc217c2c1655026bba3b364c124b3a95a8a 209 lines 5.2 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 return &cobra.Command{ 121 Use: "config [key] [value]", 122 Short: "Manage configuration", 123 Args: cobra.ExactArgs(2), 124 RunE: func(c *cobra.Command, args []string) error { 125 key, value := args[0], args[1] 126 fmt.Printf("Setting config %s = %s\n", key, value) 127 return nil 128 }, 129 } 130} 131 132func main() { 133 logger := utils.NewLogger("info", "text") 134 utils.Logger = logger 135 136 app, err := NewApp() 137 if err != nil { 138 logger.Fatal("Failed to initialize application", "error", err) 139 } 140 defer app.Close() 141 142 taskHandler, err := handlers.NewTaskHandler() 143 if err != nil { 144 log.Fatalf("failed to create task handler: %v", err) 145 } 146 147 movieHandler, err := handlers.NewMovieHandler() 148 if err != nil { 149 log.Fatalf("failed to create movie handler: %v", err) 150 } 151 152 tvHandler, err := handlers.NewTVHandler() 153 if err != nil { 154 log.Fatalf("failed to create TV handler: %v", err) 155 } 156 157 noteHandler, err := handlers.NewNoteHandler() 158 if err != nil { 159 log.Fatalf("failed to create note handler: %v", err) 160 } 161 162 bookHandler, err := handlers.NewBookHandler() 163 if err != nil { 164 log.Fatalf("failed to create book handler: %v", err) 165 } 166 167 articleHandler, err := handlers.NewArticleHandler() 168 if err != nil { 169 log.Fatalf("failed to create article handler: %v", err) 170 } 171 172 root := rootCmd() 173 174 coreGroups := []CommandGroup{ 175 NewTaskCommand(taskHandler), 176 NewNoteCommand(noteHandler), 177 NewArticleCommand(articleHandler), 178 } 179 180 for _, group := range coreGroups { 181 cmd := group.Create() 182 cmd.GroupID = "core" 183 root.AddCommand(cmd) 184 } 185 186 mediaCmd := &cobra.Command{Use: "media", Short: "Manage media queues (books, movies, TV shows)"} 187 mediaCmd.GroupID = "core" 188 mediaCmd.AddCommand(NewMovieCommand(movieHandler).Create()) 189 mediaCmd.AddCommand(NewTVCommand(tvHandler).Create()) 190 mediaCmd.AddCommand(NewBookCommand(bookHandler).Create()) 191 root.AddCommand(mediaCmd) 192 193 mgmt := []func() *cobra.Command{statusCmd, confCmd, setupCmd, resetCmd} 194 for _, cmdFunc := range mgmt { 195 cmd := cmdFunc() 196 cmd.GroupID = "management" 197 root.AddCommand(cmd) 198 } 199 200 opts := []fang.Option{ 201 fang.WithVersion("0.1.0"), 202 fang.WithoutCompletions(), 203 fang.WithColorSchemeFunc(ui.NoteleafColorScheme), 204 } 205 206 if err := fang.Execute(context.Background(), root, opts...); err != nil { 207 os.Exit(1) 208 } 209}