diff --git a/CHANGELOG.md b/CHANGELOG.md index e2f895e..2282789 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ ### Fixes +- Kept documented command-local search flags working after the query, such as `discrawl search "term" --limit 5`. Thanks @PrinceOfEgypt. - Made the terminal browser more useful and accurate: default guild scoping, newest-message startup, compact panes, selected-message detail panes, count-header sorting, local/remote status labels, right-click actions, Discord message URLs, row labels, direct-message pane labels, mention rendering, inline mention resolution, attachment details, and reply-context hydration without broad thread scans. - Kept read-only commands such as `search`, `messages`, and safe `sql` usable while `tail` or another writer holds the sync lock. Thanks @PrinceOfEgypt. - Kept `tui --help`, status, and terminal-browser reads safe for fresh or missing local databases without triggering Git snapshot auto-update. diff --git a/internal/cli/cli_test.go b/internal/cli/cli_test.go index 8481c37..bf274e2 100644 --- a/internal/cli/cli_test.go +++ b/internal/cli/cli_test.go @@ -325,6 +325,7 @@ func TestStatusSearchSQLAndListings(t *testing.T) { tests := [][]string{ {"--config", cfgPath, "status"}, {"--config", cfgPath, "search", "panic"}, + {"--config", cfgPath, "search", "panic", "--limit", "1"}, {"--config", cfgPath, "search", "stack"}, {"--config", cfgPath, "search", "--include-empty", "Peter"}, {"--config", cfgPath, "messages", "--channel", "general", "--days", "7", "--all"}, diff --git a/internal/cli/query_commands.go b/internal/cli/query_commands.go index 54dca46..88d019e 100644 --- a/internal/cli/query_commands.go +++ b/internal/cli/query_commands.go @@ -25,7 +25,7 @@ func (r *runtime) runSearch(args []string) error { dm := fs.Bool("dm", false, "") guildsFlag := fs.String("guilds", "", "") guildFlag := fs.String("guild", "", "") - if err := fs.Parse(args); err != nil { + if err := fs.Parse(permuteSearchFlags(args)); err != nil { return usageErr(err) } if fs.NArg() != 1 { @@ -67,6 +67,51 @@ func (r *runtime) runSearch(args []string) error { } } +func permuteSearchFlags(args []string) []string { + valueFlags := map[string]struct{}{ + "--mode": {}, + "--channel": {}, + "--author": {}, + "--limit": {}, + "--guilds": {}, + "--guild": {}, + } + boolFlags := map[string]struct{}{ + "--include-empty": {}, + "--dm": {}, + } + flags := make([]string, 0, len(args)) + positionals := make([]string, 0, len(args)) + for i := 0; i < len(args); i++ { + arg := args[i] + if arg == "--" { + positionals = append(positionals, args[i+1:]...) + break + } + if name, _, ok := strings.Cut(arg, "="); ok { + if _, known := valueFlags[name]; known { + flags = append(flags, arg) + continue + } + if _, known := boolFlags[name]; known { + flags = append(flags, arg) + continue + } + } + if _, known := boolFlags[arg]; known { + flags = append(flags, arg) + continue + } + if _, known := valueFlags[arg]; known && i+1 < len(args) { + flags = append(flags, arg, args[i+1]) + i++ + continue + } + positionals = append(positionals, arg) + } + return append(flags, positionals...) +} + func (r *runtime) searchMessagesSemantic(opts store.SearchOptions) ([]store.SearchResult, error) { semanticOpts, err := r.semanticSearchOptions(opts) if err != nil {