cmd

package
v0.0.0-...-598aced Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 16, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var AuthCmd = &cobra.Command{
	Use:   "auth",
	Short: "Add Google Gemini API key.",
	Args:  cobra.NoArgs,
	RunE: func(cmd *cobra.Command, args []string) error {
		fmt.Print("Enter your Google Gemini API key: ")
		password, err := term.ReadPassword(int(os.Stdin.Fd()))
		if err != nil {
			return err
		}
		apiKey := string(password)
		err = core.WithDefaultDB(func(db *core.DB) error {
			return db.SetAPIKey(apiKey)
		})
		if err != nil {
			return err
		}
		fmt.Println("\nSuccessfully set API key.")
		return nil
	},
}
View Source
var AuthDeleteCmd = &cobra.Command{
	Use:   "delete",
	Short: "Delete your Google Gemini API key.",
	Args:  cobra.NoArgs,
	RunE: func(cmd *cobra.Command, args []string) error {
		err := core.WithDefaultDB(func(db *core.DB) error {
			return db.SetAPIKey("")
		})
		if err != nil {
			return err
		}
		fmt.Println("Successfully deleted API key.")
		return nil
	},
}
View Source
var CleanCmd = &cobra.Command{
	Use:   "clean [list1 names...]",
	Short: "Remove all completed tasks from the specified lists or just the current list if none are specified.",
	Args:  cobra.ArbitraryArgs,
	RunE: func(cmd *cobra.Command, args []string) error {
		if cleanAll {
			return cleanAllLists()
		} else if len(args) > 0 {
			return cleanSpecifiedLists(args)
		} else {
			return cleanCurrentList()
		}
	},
}
View Source
var DeleteCmd = &cobra.Command{
	Use:   "delete <list name> [more list names...]",
	Short: "Delete the specified list(s).",
	Args:  cobra.ArbitraryArgs,
	RunE: func(cmd *cobra.Command, args []string) error {
		if deleteAll {
			return deleteAllLists()
		} else if len(args) == 0 {
			return cmd.Help()
		} else {
			return deleteSpecifiedLists(args)
		}
	},
}
View Source
var ExportCmd = &cobra.Command{
	Use:   "export <file> [list names...] ",
	Short: "Export list to a file. Uses current list if no list name(s) provided. Supported formats: JSON, YAML",
	Args:  cobra.MinimumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		lists := make([]core.List, max(1, len(args)-1))
		err := core.WithDefaultDB(func(db *core.DB) error {
			var fileName string

			if len(args) == 1 {
				listName, err := db.GetCurrentListName()
				if err != nil {
					return err
				}
				list, err := db.GetList(listName)
				if err != nil {
					return err
				}
				fileName = args[0]
				lists[0] = list
			} else {
				fileName = args[0]
				for i := 1; i < len(args); i++ {
					list, err := db.GetList(args[i])
					if err != nil {
						return err
					}
					lists[i-1] = list
				}
			}

			content, err := dataToFile(lists, filepath.Ext(fileName))
			if err != nil {
				return err
			}
			return os.WriteFile(fileName, content, 0644)
		})
		if err != nil {
			return err
		}
		fmt.Printf("Exported the following lists to \"%s\":\n", args[0])
		for _, list := range lists {
			fmt.Println("  - ", list.Info.Name)
		}
		return nil
	},
}
View Source
var GenerateCmd = &cobra.Command{
	Use:   "generate <file>",
	Short: "Generate lists based on descriptions in a txt file.",
	Args:  cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {

		fileName := args[0]
		content, err := os.ReadFile(fileName)
		if err != nil {
			return err
		}

		return core.WithDefaultDB(func(db *core.DB) error {

			apiKey, err := db.GetAPIKey()
			if err != nil {
				return err
			}

			ctx := context.Background()
			client, err := genai.NewClient(ctx, &genai.ClientConfig{APIKey: apiKey})
			if err != nil {
				return err
			}

			allInfo, err := db.GetInfo()
			if err != nil {
				return err
			}
			existingLists := ""
			for _, info := range allInfo {
				existingLists += "\"" + info.Name + "\", "
			}
			instructions += " Exclude the following names from the lists: " + strings.TrimSuffix(existingLists, ", ") + "."

			result, err := generateLists(ctx, client, content)
			if err != nil {
				return err
			}

			lists, err := fileToData([]byte(result.Text()), ".json")
			if err != nil {
				return err
			}
			for _, list := range lists {
				fmt.Println()
				fmt.Printf("%v", &list)
			}

			reader := bufio.NewReader(os.Stdin)
			fmt.Print("\nAdd these to your lists? (y/n) ")
			for {
				char, _, err := reader.ReadRune()
				if err != nil {
					return err
				}
				if char == 'y' || char == 'Y' {

					for _, list := range lists {
						db.SaveList(list)
					}
					fmt.Println("Success! All lists added.")
					break
				} else if char == 'n' || char == 'N' {

					fmt.Println("Lists discarded.")
					break
				}
			}

			return nil
		})
	},
}
View Source
var ImportCmd = &cobra.Command{
	Use:   "import <file>",
	Short: "Import tasks from a file. Supported formats: JSON, YAML",
	Args:  cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		fileName := args[0]
		content, err := os.ReadFile(fileName)
		if err != nil {
			return err
		}
		lists, err := fileToData(content, filepath.Ext(fileName))
		if err != nil {
			return err
		}
		err = core.WithDefaultDB(func(db *core.DB) error {
			for _, list := range lists {
				exists, err := db.ListExists(list.Info.Name)
				if err != nil {
					return err
				}
				if exists {
					return fmt.Errorf("failed to import because list %q already exists", list.Info.Name)
				}

				err = db.SaveList(list)
				if err != nil {
					return err
				}
			}
			return nil
		})
		if err != nil {
			return err
		}
		fmt.Printf("Imported the following lists:\n")
		for _, list := range lists {
			fmt.Println("  - ", list.Info.Name)
		}
		return nil
	},
}
View Source
var KmapClearCmd = &cobra.Command{
	Use:   "clear",
	Short: "Revert to default bindings. Does not edit files.",
	Args:  cobra.NoArgs,
	RunE: func(cmd *cobra.Command, args []string) error {
		err := core.WithDefaultDB(func(db *core.DB) error {
			return db.SetKmapPath("")
		})
		if err != nil {
			return err
		}

		fmt.Println("Success! Key-bindings reset to default.")
		return nil
	},
}
View Source
var KmapCmd = &cobra.Command{
	Use:   "kmap [command]",
	Short: "Manage key-mappings for the TUI",
}
View Source
var KmapSetCmd = &cobra.Command{
	Use:   "set <file>",
	Short: "Sets the file to refer to for key-mappings. Refer to the README for file formatting.",
	Long:  "Sets the file to refer to for key-mappings. Fails if file does not exist. Refer to the README for file formatting.",
	Args:  cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		pth := args[0]
		absPath, err := filepath.Abs(pth)
		if err != nil {
			return err
		}

		err = core.WithDefaultDB(func(db *core.DB) error {
			return db.SetKmapPath(absPath)
		})
		if err != nil {
			return err
		}

		fmt.Printf("Success! Refering to %s for key-mappings.\n", pth)
		return nil
	},
}
View Source
var KmapShowCmd = &cobra.Command{
	Use:   "show",
	Short: "Show which file is being used for the current keymap.",
	Args:  cobra.NoArgs,
	RunE: func(cmd *cobra.Command, args []string) error {
		// get the file path
		var pth string
		err := core.WithDefaultDB(func(db *core.DB) error {
			var err error
			pth, err = db.GetKmapPath()
			if err != nil {
				return err
			}
			return nil
		})
		if err != nil {
			return err
		}

		if pth == "" {
			fmt.Println("No file set. Using defaults.")
		} else {
			fmt.Printf("Using %s for key-mapping.\n", pth)

			_, err = os.Stat(pth)
			if err != nil {
				fmt.Println("WARNING: File does not exist. Using defaults.")
			}
		}

		return nil
	},
}
View Source
var ListCmd = &cobra.Command{
	Use:   "list",
	Short: "Display the names of all todo lists along with their task counts.",
	Args:  cobra.NoArgs,
	RunE: func(cmd *cobra.Command, args []string) error {
		return core.WithDefaultDB(func(db *core.DB) error {
			allInfo, err := db.GetInfo()
			if err != nil {
				return fmt.Errorf("failed to retrieve lists: %v", err)
			}

			if len(allInfo) == 0 {
				return fmt.Errorf("no lists found - create a new one with\n\n\tlistly new <list name> ... ")
			}

			currentListName, err := db.GetCurrentListName()
			if err != nil {
				return fmt.Errorf("failed to retrieve current list name: %v", err)
			}
			maxLen := 12
			for _, info := range allInfo {
				name := info.Name
				nameLen := len(name)
				if name == currentListName {
					nameLen += len(" (current)") + 2
				}
				if nameLen > maxLen {
					maxLen = nameLen
				}
			}

			// Convert map to slice for sorting
			var allInfoSlice []core.ListInfo
			for _, info := range allInfo {
				allInfoSlice = append(allInfoSlice, info)
			}

			sort.Slice(allInfoSlice, func(i, j int) bool {
				return allInfoSlice[i].Name < allInfoSlice[j].Name
			})

			printRow("List Name", "Pending", "Done", "Total", maxLen)
			fmt.Println(strings.Repeat("=", maxLen+21))
			for _, info := range allInfoSlice {
				var name string
				if useQuotes {
					name = fmt.Sprintf("\"%s\"", info.Name)
				} else {
					name = info.Name
				}
				if info.Name == currentListName {
					printRow(
						fmt.Sprintf("%s (current)", name),
						strconv.Itoa(info.NumPending),
						strconv.Itoa(info.NumDone),
						strconv.Itoa(info.NumTasks),
						maxLen,
					)
				} else {
					printRow(
						name,
						strconv.Itoa(info.NumPending),
						strconv.Itoa(info.NumDone),
						strconv.Itoa(info.NumTasks),
						maxLen,
					)
				}
			}
			return nil
		})
	},
}
View Source
var NewCmd = &cobra.Command{
	Use:   "new [list name]",
	Short: "Create a new todo list.",
	Args:  cobra.MinimumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {

		noDup := []string{}
		seen := map[string]struct{}{}
		for _, listName := range args {
			_, ok := seen[listName]
			if ok {
				continue
			}
			seen[listName] = struct{}{}
			noDup = append(noDup, listName)
		}

		return core.WithDefaultDB(func(db *core.DB) error {
			for _, listName := range noDup {
				exists, err := db.ListExists(listName)
				if err != nil {
					return err
				}
				if exists {
					return fmt.Errorf("list \"%s\" already exists. No new list created", listName)
				}
			}
			for _, listName := range noDup {
				err := createNewList(db, listName)
				if err != nil {
					return err
				}
			}
			core.Success(fmt.Sprintf("Created new todo-lists:\n%s", core.ListLists(noDup, "  ")))
			return nil
		})
	},
}
View Source
var OpenCmd = &cobra.Command{
	Use:   "open [list name]",
	Short: "Open the TUI for the specified list or the current list if no list is specified.",
	Args:  cobra.MaximumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		return core.WithDefaultDB(
			func(db *core.DB) error {
				var listName string
				if len(args) > 0 {
					listName = args[0]
				} else {
					var err error
					listName, err = db.GetCurrentListName()
					if err != nil {
						return err
					}
					if listName == "" {
						return fmt.Errorf("no list chosen. specify a list name or use\n\n\tlistly switch <list name>\n ")
					}
				}

				err := db.SetCurrentListName(listName)
				if err != nil {
					return err
				}

				exists, err := db.ListExists(listName)
				if err != nil {
					return err
				}
				if !exists {
					return fmt.Errorf("list %q does not exist", listName)
				}

				m, err := tui.NewModel(db, listName)
				if err != nil {
					return err
				}

				tuiProgram := tea.NewProgram(m)
				_, err = tuiProgram.Run()
				if err != nil {
					return err
				}
				fmt.Print("\033[H\033[2J")
				return nil
			},
		)
	},
}
View Source
var RenameCmd = &cobra.Command{
	Use:   "rename <old list name> <new list name>",
	Short: "Rename an existing todo list.",
	Args:  cobra.ExactArgs(2),
	RunE: func(cmd *cobra.Command, args []string) error {
		oldName := args[0]
		newName := args[1]

		return core.WithDefaultDB(func(db *core.DB) error {
			err := db.RenameList(oldName, newName)
			if err != nil {
				return fmt.Errorf("could not rename todo-list due to the following error\n\t %v", err)
			}
			core.Success(fmt.Sprintf("Renamed todo-list '%s' to '%s'", oldName, newName))
			return nil
		})
	},
}
View Source
var RootCmd = &cobra.Command{
	Use:   "listly",
	Short: "Listly is a CLI task manager",
	Long: `
Listly is a task manager that lets you efficiently create and 
manage different todo lists with CLI commands. It also provides
a TUI that allows you to add/remove/edit tasks using Vim-style keybindings.`,
}
View Source
var ShowCmd = &cobra.Command{
	Use:   "show [list name]",
	Short: "Print all tasks in the current or specified list.",
	Args:  cobra.MaximumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		return core.WithDefaultDB(func(db *core.DB) error {
			// Get the list name (current or specified)
			var listName string
			if len(args) > 0 {
				listName = args[0]
			} else {
				var err error
				listName, err = db.GetCurrentListName()
				if err != nil {
					return fmt.Errorf("could not retrieve current list name due to the following error\n\t %v", err)
				}
				if listName == "" {
					return fmt.Errorf("no list selected")
				}
			}

			list, err := db.GetList(listName)
			if err != nil {
				return fmt.Errorf("could not retrieve list %s due to the following error\n\t %v", listName, err)
			}

			fmt.Printf("%v", &list)
			return nil
		})
	},
}
View Source
var SwitchCmd = &cobra.Command{
	Use:   "switch [list name]",
	Short: "Switch to the specified todo list.",
	Args:  cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		listName := args[0]
		return core.WithDefaultDB(func(db *core.DB) error {
			exists, err := db.ListExists(listName)
			if err != nil {
				return fmt.Errorf("could not check if list %s exists due to the following error\n\t %v", listName, err)
			}

			if !exists {
				return fmt.Errorf("list %s does not exist - cannot switch to it", listName)
			}

			if err := db.SetCurrentListName(listName); err != nil {
				return fmt.Errorf("could not switch to list %s due to the following error\n\t %v", listName, err)
			}
			core.Success(fmt.Sprintf("Switched to todo-list '%s'", listName))
			return nil
		})
	},
}

Functions

func SetUp

func SetUp()

can also be done with multiple init() functions, but it's easier to follow this way.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL