feat: improve configure
This commit is contained in:
+237
-133
@@ -27,6 +27,8 @@ const (
|
|||||||
SectionInjection ConfigSection = "injection"
|
SectionInjection ConfigSection = "injection"
|
||||||
SectionNotifications ConfigSection = "notifications"
|
SectionNotifications ConfigSection = "notifications"
|
||||||
SectionFullSetup ConfigSection = "full_setup"
|
SectionFullSetup ConfigSection = "full_setup"
|
||||||
|
SectionSaveExit ConfigSection = "save_exit"
|
||||||
|
SectionDiscardExit ConfigSection = "discard_exit"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Run starts the TUI configuration wizard
|
// Run starts the TUI configuration wizard
|
||||||
@@ -51,38 +53,46 @@ func hasUserChanges(cfg *config.Config) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// runEditExisting runs the section-based edit flow for existing configs
|
// runEditExisting runs the menu-based edit flow for existing configs
|
||||||
func runEditExisting(cfg *config.Config) (*ConfigureResult, error) {
|
func runEditExisting(cfg *config.Config) (*ConfigureResult, error) {
|
||||||
fmt.Println(Logo())
|
fmt.Println(Logo())
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Println(StyleMuted.Render("Configuration detected. Select sections to edit."))
|
|
||||||
fmt.Println()
|
|
||||||
|
|
||||||
// Section picker
|
|
||||||
sections, err := selectSections()
|
|
||||||
if err != nil {
|
|
||||||
return &ConfigureResult{Cancelled: true}, nil
|
|
||||||
}
|
|
||||||
if len(sections) == 0 {
|
|
||||||
return &ConfigureResult{Cancelled: true}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if full setup requested
|
|
||||||
for _, s := range sections {
|
|
||||||
if s == SectionFullSetup {
|
|
||||||
return runFreshInstall(cfg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track which providers are configured (for smart detection)
|
// Track which providers are configured (for smart detection)
|
||||||
configuredProviders := getConfiguredProviders(cfg)
|
configuredProviders := getConfiguredProviders(cfg)
|
||||||
|
|
||||||
// Process each selected section
|
// Menu loop
|
||||||
for _, section := range sections {
|
for {
|
||||||
|
// Clear screen for cleaner UX
|
||||||
|
fmt.Print("\033[H\033[2J")
|
||||||
|
fmt.Println(Logo())
|
||||||
|
fmt.Println()
|
||||||
|
|
||||||
|
section, err := selectSection(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return &ConfigureResult{Cancelled: true}, nil
|
||||||
|
}
|
||||||
|
|
||||||
switch section {
|
switch section {
|
||||||
|
case SectionSaveExit:
|
||||||
|
confirmed, err := showSummary(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return &ConfigureResult{Cancelled: true}, nil
|
||||||
|
}
|
||||||
|
if confirmed {
|
||||||
|
return &ConfigureResult{Config: cfg, Cancelled: false}, nil
|
||||||
|
}
|
||||||
|
// User cancelled save, back to menu
|
||||||
|
|
||||||
|
case SectionDiscardExit:
|
||||||
|
return &ConfigureResult{Cancelled: true}, nil
|
||||||
|
|
||||||
|
case SectionFullSetup:
|
||||||
|
return runFreshInstall(cfg)
|
||||||
|
|
||||||
case SectionProviders:
|
case SectionProviders:
|
||||||
if err := editProviders(cfg); err != nil {
|
if err := editProviders(cfg); err != nil {
|
||||||
return &ConfigureResult{Cancelled: true}, nil
|
continue // back to menu on cancel
|
||||||
}
|
}
|
||||||
configuredProviders = getConfiguredProviders(cfg)
|
configuredProviders = getConfiguredProviders(cfg)
|
||||||
|
|
||||||
@@ -90,77 +100,131 @@ func runEditExisting(cfg *config.Config) (*ConfigureResult, error) {
|
|||||||
var err error
|
var err error
|
||||||
configuredProviders, err = editTranscription(cfg, configuredProviders)
|
configuredProviders, err = editTranscription(cfg, configuredProviders)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ConfigureResult{Cancelled: true}, nil
|
continue // back to menu on cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
case SectionLLM:
|
case SectionLLM:
|
||||||
var err error
|
var err error
|
||||||
configuredProviders, err = editLLM(cfg, configuredProviders)
|
configuredProviders, err = editLLM(cfg, configuredProviders)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ConfigureResult{Cancelled: true}, nil
|
continue // back to menu on cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
case SectionKeywords:
|
case SectionKeywords:
|
||||||
keywords, err := inputKeywords(cfg.Keywords)
|
keywords, err := inputKeywords(cfg.Keywords)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ConfigureResult{Cancelled: true}, nil
|
continue // back to menu on cancel
|
||||||
}
|
}
|
||||||
cfg.Keywords = keywords
|
cfg.Keywords = keywords
|
||||||
|
|
||||||
case SectionInjection:
|
case SectionInjection:
|
||||||
backends, err := selectBackends(cfg.Injection.Backends)
|
backends, err := selectBackends(cfg.Injection.Backends)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ConfigureResult{Cancelled: true}, nil
|
continue // back to menu on cancel
|
||||||
}
|
}
|
||||||
cfg.Injection.Backends = backends
|
cfg.Injection.Backends = backends
|
||||||
|
|
||||||
case SectionNotifications:
|
case SectionNotifications:
|
||||||
enabled, err := configureNotifications(cfg.Notifications.Enabled)
|
enabled, err := configureNotifications(cfg.Notifications.Enabled)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &ConfigureResult{Cancelled: true}, nil
|
continue // back to menu on cancel
|
||||||
}
|
}
|
||||||
cfg.Notifications.Enabled = enabled
|
cfg.Notifications.Enabled = enabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Summary and confirm
|
|
||||||
confirmed, err := showSummary(cfg)
|
|
||||||
if err != nil || !confirmed {
|
|
||||||
return &ConfigureResult{Cancelled: true}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ConfigureResult{Config: cfg, Cancelled: false}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func selectSections() ([]ConfigSection, error) {
|
func selectSection(cfg *config.Config) (ConfigSection, error) {
|
||||||
options := []huh.Option[ConfigSection]{
|
options := []huh.Option[ConfigSection]{
|
||||||
huh.NewOption("Providers - API keys", SectionProviders),
|
huh.NewOption(formatProvidersLabel(cfg), SectionProviders),
|
||||||
huh.NewOption("Transcription - speech-to-text settings", SectionTranscription),
|
huh.NewOption(formatTranscriptionLabel(cfg), SectionTranscription),
|
||||||
huh.NewOption("LLM - post-processing settings", SectionLLM),
|
huh.NewOption(formatLLMLabel(cfg), SectionLLM),
|
||||||
huh.NewOption("Keywords - spelling hints", SectionKeywords),
|
huh.NewOption(formatKeywordsLabel(cfg), SectionKeywords),
|
||||||
huh.NewOption("Injection - text input backends", SectionInjection),
|
huh.NewOption(formatInjectionLabel(cfg), SectionInjection),
|
||||||
huh.NewOption("Notifications - desktop alerts", SectionNotifications),
|
huh.NewOption(formatNotificationsLabel(cfg), SectionNotifications),
|
||||||
huh.NewOption("Full Setup - reconfigure everything", SectionFullSetup),
|
huh.NewOption("Full Setup (reconfigure everything)", SectionFullSetup),
|
||||||
|
huh.NewOption("Save & Exit", SectionSaveExit),
|
||||||
|
huh.NewOption("Discard & Exit", SectionDiscardExit),
|
||||||
}
|
}
|
||||||
|
|
||||||
var selected []ConfigSection
|
var selected ConfigSection
|
||||||
form := huh.NewForm(
|
form := huh.NewForm(
|
||||||
huh.NewGroup(
|
huh.NewGroup(
|
||||||
huh.NewMultiSelect[ConfigSection]().
|
huh.NewSelect[ConfigSection]().
|
||||||
Title("What do you want to configure?").
|
Title("Configuration Menu").
|
||||||
Description("Select one or more sections to edit").
|
Description("↑/↓ navigate • enter select • esc cancel").
|
||||||
Options(options...).
|
Options(options...).
|
||||||
Value(&selected),
|
Value(&selected),
|
||||||
),
|
),
|
||||||
).WithTheme(getTheme())
|
).WithTheme(getTheme())
|
||||||
|
|
||||||
if err := form.Run(); err != nil {
|
if err := form.Run(); err != nil {
|
||||||
return nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return selected, nil
|
return selected, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// formatProvidersLabel shows configured providers
|
||||||
|
func formatProvidersLabel(cfg *config.Config) string {
|
||||||
|
var providers []string
|
||||||
|
for name, pc := range cfg.Providers {
|
||||||
|
if pc.APIKey != "" {
|
||||||
|
providers = append(providers, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(providers) == 0 {
|
||||||
|
return "Providers - none configured"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Providers - %s", strings.Join(providers, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatTranscriptionLabel shows current transcription settings
|
||||||
|
func formatTranscriptionLabel(cfg *config.Config) string {
|
||||||
|
if cfg.Transcription.Provider == "" {
|
||||||
|
return "Transcription - not configured"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Transcription - %s/%s", cfg.Transcription.Provider, cfg.Transcription.Model)
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatLLMLabel shows current LLM settings
|
||||||
|
func formatLLMLabel(cfg *config.Config) string {
|
||||||
|
if !cfg.LLM.Enabled {
|
||||||
|
return "LLM - disabled"
|
||||||
|
}
|
||||||
|
if cfg.LLM.Provider == "" {
|
||||||
|
return "LLM - enabled (not configured)"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("LLM - %s/%s", cfg.LLM.Provider, cfg.LLM.Model)
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatKeywordsLabel shows keyword count
|
||||||
|
func formatKeywordsLabel(cfg *config.Config) string {
|
||||||
|
if len(cfg.Keywords) == 0 {
|
||||||
|
return "Keywords - none"
|
||||||
|
}
|
||||||
|
if len(cfg.Keywords) <= 3 {
|
||||||
|
return fmt.Sprintf("Keywords - %s", strings.Join(cfg.Keywords, ", "))
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Keywords - %d configured", len(cfg.Keywords))
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatInjectionLabel shows backends
|
||||||
|
func formatInjectionLabel(cfg *config.Config) string {
|
||||||
|
if len(cfg.Injection.Backends) == 0 {
|
||||||
|
return "Injection - no backends"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Injection - %s", strings.Join(cfg.Injection.Backends, " → "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatNotificationsLabel shows notification status
|
||||||
|
func formatNotificationsLabel(cfg *config.Config) string {
|
||||||
|
if cfg.Notifications.Enabled {
|
||||||
|
return "Notifications - enabled"
|
||||||
|
}
|
||||||
|
return "Notifications - disabled"
|
||||||
|
}
|
||||||
|
|
||||||
// getConfiguredProviders returns list of providers with API keys
|
// getConfiguredProviders returns list of providers with API keys
|
||||||
func getConfiguredProviders(cfg *config.Config) []string {
|
func getConfiguredProviders(cfg *config.Config) []string {
|
||||||
var providers []string
|
var providers []string
|
||||||
@@ -172,57 +236,71 @@ func getConfiguredProviders(cfg *config.Config) []string {
|
|||||||
return providers
|
return providers
|
||||||
}
|
}
|
||||||
|
|
||||||
// editProviders handles the providers section edit
|
// editProviders handles the providers section edit with submenu
|
||||||
func editProviders(cfg *config.Config) error {
|
func editProviders(cfg *config.Config) error {
|
||||||
// Show current providers with option to add/edit
|
|
||||||
allProviders := []string{"openai", "groq", "mistral", "elevenlabs"}
|
allProviders := []string{"openai", "groq", "mistral", "elevenlabs"}
|
||||||
|
|
||||||
var options []huh.Option[string]
|
for {
|
||||||
for _, name := range allProviders {
|
// Build options with current status
|
||||||
label := strings.Title(name)
|
var options []huh.Option[string]
|
||||||
if _, exists := cfg.Providers[name]; exists && cfg.Providers[name].APIKey != "" {
|
for _, name := range allProviders {
|
||||||
label += " (configured)"
|
options = append(options, huh.NewOption(formatProviderOption(cfg, name), name))
|
||||||
}
|
}
|
||||||
switch name {
|
options = append(options, huh.NewOption("Back", "back"))
|
||||||
case "openai":
|
|
||||||
options = append(options, huh.NewOption(label+" - Whisper + GPT", name))
|
|
||||||
case "groq":
|
|
||||||
options = append(options, huh.NewOption(label+" - Whisper + Llama", name))
|
|
||||||
case "mistral":
|
|
||||||
options = append(options, huh.NewOption(label+" - Voxtral", name))
|
|
||||||
case "elevenlabs":
|
|
||||||
options = append(options, huh.NewOption(label+" - Scribe", name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var selected []string
|
var selected string
|
||||||
form := huh.NewForm(
|
form := huh.NewForm(
|
||||||
huh.NewGroup(
|
huh.NewGroup(
|
||||||
huh.NewMultiSelect[string]().
|
huh.NewSelect[string]().
|
||||||
Title("Configure API keys for:").
|
Title("Provider Settings").
|
||||||
Description("Select providers to add or update API keys").
|
Description("Select a provider to configure API key").
|
||||||
Options(options...).
|
Options(options...).
|
||||||
Value(&selected),
|
Value(&selected),
|
||||||
),
|
),
|
||||||
).WithTheme(getTheme())
|
).WithTheme(getTheme())
|
||||||
|
|
||||||
if err := form.Run(); err != nil {
|
if err := form.Run(); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Input API keys for selected providers
|
|
||||||
for _, providerName := range selected {
|
|
||||||
apiKey, err := inputAPIKey(providerName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if selected == "back" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure the selected provider
|
||||||
|
apiKey, err := inputAPIKey(selected)
|
||||||
|
if err != nil {
|
||||||
|
continue // cancelled, back to provider menu
|
||||||
|
}
|
||||||
|
|
||||||
if cfg.Providers == nil {
|
if cfg.Providers == nil {
|
||||||
cfg.Providers = make(map[string]config.ProviderConfig)
|
cfg.Providers = make(map[string]config.ProviderConfig)
|
||||||
}
|
}
|
||||||
cfg.Providers[providerName] = config.ProviderConfig{APIKey: apiKey}
|
cfg.Providers[selected] = config.ProviderConfig{APIKey: apiKey}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatProviderOption formats a provider menu option with status
|
||||||
|
func formatProviderOption(cfg *config.Config, name string) string {
|
||||||
|
var status string
|
||||||
|
if pc, exists := cfg.Providers[name]; exists && pc.APIKey != "" {
|
||||||
|
status = "(configured)"
|
||||||
|
} else {
|
||||||
|
status = "(not configured)"
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
switch name {
|
||||||
|
case "openai":
|
||||||
|
return fmt.Sprintf("OpenAI - Whisper + GPT %s", status)
|
||||||
|
case "groq":
|
||||||
|
return fmt.Sprintf("Groq - Whisper + Llama %s", status)
|
||||||
|
case "mistral":
|
||||||
|
return fmt.Sprintf("Mistral - Voxtral %s", status)
|
||||||
|
case "elevenlabs":
|
||||||
|
return fmt.Sprintf("ElevenLabs - Scribe %s", status)
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("%s %s", name, status)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// editTranscription handles the transcription section edit with smart provider detection
|
// editTranscription handles the transcription section edit with smart provider detection
|
||||||
@@ -433,30 +511,11 @@ func editLLM(cfg *config.Config, configuredProviders []string) ([]string, error)
|
|||||||
|
|
||||||
cfg.LLM.Model = selectedModel
|
cfg.LLM.Model = selectedModel
|
||||||
|
|
||||||
// Post-processing options
|
// Post-processing options using MultiSelect
|
||||||
ppForm := huh.NewForm(
|
var ppErr error
|
||||||
huh.NewGroup(
|
postProcessing, ppErr = selectPostProcessingOptions(postProcessing)
|
||||||
huh.NewConfirm().
|
if ppErr != nil {
|
||||||
Title("Remove stutters").
|
return configuredProviders, ppErr
|
||||||
Description("Remove repeated words like 'I I I think'").
|
|
||||||
Value(&postProcessing.RemoveStutters),
|
|
||||||
huh.NewConfirm().
|
|
||||||
Title("Add punctuation").
|
|
||||||
Description("Add proper punctuation to text").
|
|
||||||
Value(&postProcessing.AddPunctuation),
|
|
||||||
huh.NewConfirm().
|
|
||||||
Title("Fix grammar").
|
|
||||||
Description("Correct grammatical errors").
|
|
||||||
Value(&postProcessing.FixGrammar),
|
|
||||||
huh.NewConfirm().
|
|
||||||
Title("Remove filler words").
|
|
||||||
Description("Remove 'um', 'uh', 'like', etc.").
|
|
||||||
Value(&postProcessing.RemoveFillerWords),
|
|
||||||
),
|
|
||||||
).WithTheme(getTheme())
|
|
||||||
|
|
||||||
if err := ppForm.Run(); err != nil {
|
|
||||||
return configuredProviders, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.LLM.PostProcessing = postProcessing
|
cfg.LLM.PostProcessing = postProcessing
|
||||||
@@ -958,29 +1017,10 @@ func configureLLM(configuredProviders []string, cfg *config.Config) (bool, strin
|
|||||||
postProcessing = cfg.LLM.PostProcessing
|
postProcessing = cfg.LLM.PostProcessing
|
||||||
}
|
}
|
||||||
|
|
||||||
ppForm := huh.NewForm(
|
var ppErr error
|
||||||
huh.NewGroup(
|
postProcessing, ppErr = selectPostProcessingOptions(postProcessing)
|
||||||
huh.NewConfirm().
|
if ppErr != nil {
|
||||||
Title("Remove stutters").
|
return false, "", "", postProcessing, customPrompt, ppErr
|
||||||
Description("Remove repeated words like 'I I I think'").
|
|
||||||
Value(&postProcessing.RemoveStutters),
|
|
||||||
huh.NewConfirm().
|
|
||||||
Title("Add punctuation").
|
|
||||||
Description("Add proper punctuation to text").
|
|
||||||
Value(&postProcessing.AddPunctuation),
|
|
||||||
huh.NewConfirm().
|
|
||||||
Title("Fix grammar").
|
|
||||||
Description("Correct grammatical errors").
|
|
||||||
Value(&postProcessing.FixGrammar),
|
|
||||||
huh.NewConfirm().
|
|
||||||
Title("Remove filler words").
|
|
||||||
Description("Remove 'um', 'uh', 'like', etc.").
|
|
||||||
Value(&postProcessing.RemoveFillerWords),
|
|
||||||
),
|
|
||||||
).WithTheme(getTheme())
|
|
||||||
|
|
||||||
if err := ppForm.Run(); err != nil {
|
|
||||||
return false, "", "", postProcessing, customPrompt, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom prompt
|
// Custom prompt
|
||||||
@@ -1045,6 +1085,70 @@ func getLLMModelOptions(provider string) []huh.Option[string] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// selectPostProcessingOptions shows a multi-select for LLM post-processing toggles
|
||||||
|
func selectPostProcessingOptions(current config.LLMPostProcessingConfig) (config.LLMPostProcessingConfig, error) {
|
||||||
|
type ppOption string
|
||||||
|
const (
|
||||||
|
optRemoveStutters ppOption = "stutters"
|
||||||
|
optAddPunctuation ppOption = "punctuation"
|
||||||
|
optFixGrammar ppOption = "grammar"
|
||||||
|
optRemoveFillerWords ppOption = "fillers"
|
||||||
|
)
|
||||||
|
|
||||||
|
options := []huh.Option[ppOption]{
|
||||||
|
huh.NewOption("Remove stutters (repeated words)", optRemoveStutters),
|
||||||
|
huh.NewOption("Add punctuation", optAddPunctuation),
|
||||||
|
huh.NewOption("Fix grammar", optFixGrammar),
|
||||||
|
huh.NewOption("Remove filler words (um, uh, like)", optRemoveFillerWords),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pre-select based on current config
|
||||||
|
var selected []ppOption
|
||||||
|
if current.RemoveStutters {
|
||||||
|
selected = append(selected, optRemoveStutters)
|
||||||
|
}
|
||||||
|
if current.AddPunctuation {
|
||||||
|
selected = append(selected, optAddPunctuation)
|
||||||
|
}
|
||||||
|
if current.FixGrammar {
|
||||||
|
selected = append(selected, optFixGrammar)
|
||||||
|
}
|
||||||
|
if current.RemoveFillerWords {
|
||||||
|
selected = append(selected, optRemoveFillerWords)
|
||||||
|
}
|
||||||
|
|
||||||
|
form := huh.NewForm(
|
||||||
|
huh.NewGroup(
|
||||||
|
huh.NewMultiSelect[ppOption]().
|
||||||
|
Title("Post-Processing Options").
|
||||||
|
Description("Select which improvements to apply").
|
||||||
|
Options(options...).
|
||||||
|
Value(&selected),
|
||||||
|
),
|
||||||
|
).WithTheme(getTheme())
|
||||||
|
|
||||||
|
if err := form.Run(); err != nil {
|
||||||
|
return current, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert selections back to config
|
||||||
|
result := config.LLMPostProcessingConfig{}
|
||||||
|
for _, opt := range selected {
|
||||||
|
switch opt {
|
||||||
|
case optRemoveStutters:
|
||||||
|
result.RemoveStutters = true
|
||||||
|
case optAddPunctuation:
|
||||||
|
result.AddPunctuation = true
|
||||||
|
case optFixGrammar:
|
||||||
|
result.FixGrammar = true
|
||||||
|
case optRemoveFillerWords:
|
||||||
|
result.RemoveFillerWords = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func inputKeywords(existingKeywords []string) ([]string, error) {
|
func inputKeywords(existingKeywords []string) ([]string, error) {
|
||||||
var keywordsInput string
|
var keywordsInput string
|
||||||
if len(existingKeywords) > 0 {
|
if len(existingKeywords) > 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user