Tags: caffienerd/struct-cli
Tags
feat: overhaul CLI syntax, fix search bugs, improve help UX
Major UX pass on argument parsing, search correctness, and help output.
All changes battle-tested through three rounds of edge case testing.
---
- Removed `-p`/`--path` flag — PATH is now a bare positional argument
- Removed `-d`/`--depth` flag for tree mode — DEPTH is now a bare positional
- New syntax: `struct [DEPTH] [PATH] [FLAGS]` (both optional, any order)
- Search depth is now also positional: `struct search "PAT" [PATH] [DEPTH]`
- **First attempt**: used clap `trailing_var_arg = true` — caused critical bug
where flags like `--gr` after a positional were swallowed as positional strings
instead of being parsed as flags (`struct 0 --gr path` would crash)
- **Final approach**: `preprocess_argv()` manually extracts DEPTH and PATH from
`args()` before clap sees them. Clap only ever receives flags. This cleanly
solves the ambiguity: first bare integer = DEPTH, first non-integer bare
token = PATH, all further bare tokens silently discarded (previously caused
"unrecognized subcommand" errors)
- All clap flags marked `hide = true` — removes the verbose auto-generated
`Arguments` / `Options` section that printed each flag on its own line
- `-h`/`--help` intercepted before clap formats it; prints hand-written `HELP`
const instead — compact, example-driven, covers all modes in one screen
- `-n`/`--no-ignore` now accepts multiple values via `ArgAction::Append`
(`-n defaults -n config` works, equivalent to `-n all`)
- When multiple git flags are given (e.g. `--gu --gs`), priority chain picks
highest: Changed > Staged > Untracked > Tracked > History
- Documented in help text
- Fixed: `struct 0 --gr path` previously crashed because `--gr` was being
consumed as a positional string instead of a flag
- Now works correctly: git root is resolved, then summary is displayed
---
- **Old behavior**: every pattern wrapped in `^...$` regex anchors, so `"py"`
only matched a file/dir named exactly `py`, and `"pycache"` never matched
`__pycache__`
- **New behavior**: patterns without `*` or `?` = case-insensitive substring
match (`contains`); patterns with wildcards = glob compiled to regex
- Examples: `search "py"` finds anything with `py` in the name;
`search "*.py"` still does exact glob matching; `search "__pycache__"` finds
`__pycache__` dirs
- **Old behavior**: `filter_entry` pruned ignored dirs (like `__pycache__`,
`.git`) before they could be reported as matches — `search "__pycache__"`
found nothing
- **New behavior**: if a dir's name matches the search pattern, `filter_entry`
allows it through (so it gets reported) but does NOT descend into it (so we
don't walk inside `.git` looking for more matches)
- `search ""` previously matched every single file (Rust's `str::contains("")`
is always true) and also walked into `.git` and other ignored dirs
- Now rejected immediately: `error: pattern cannot be empty — use "*" to match everything`
- Added `-i`/`--ignore` to the `search` subcommand — inline ignore patterns
during search, merged with config patterns
- Example: `struct search "*.wav" . -i "windows,Linux"`
- Flat mode now correctly renders matched directories with trailing `/`
---
- `struct ~/path` — no longer errors "invalid digit found in string"
- `struct 2 ~/projects` — depth + path both work
- `struct ~/projects 2` — path then depth also works
- `struct 0 --gr path` — summary + git root no longer crashes
- `struct --gr subdir/` — correctly walks up to git root
- `struct -n defaults -n config` — no longer errors "cannot use multiple times"
- `struct path1 extra_token` — extra tokens silently discarded, no error
- `struct 1 2 3 path` — first number = depth, path = path, rest discarded
- `search "__pycache__"` — finds all __pycache__ dirs correctly
- `search "py"` — substring match, finds anything containing "py"
- `search ""` — clean error instead of matching everything
- `-s 0` / `-s 999999` — both behave correctly (edge values, not bugs)
- `search "*" path 0` — depth 0 in search = infinite (correct)
- `--gur _repo` where _repo is not a git repo — correct "not in a git repository" error
v0.4.2: major refactor with modular architecture and comprehensive gi… …t integration - Refactored monolithic main.rs. - Added comprehensive git integration: - for tracked files only - for untracked files - for staged files - for modified/changed files - flag to start from git root with any git mode - Color-coded output (staged=green, changed=yellow, untracked=red) - Git branch display in output - Fixed /home/turtle/_projects/03_rust/struct-cli (master) Cargo.toml /home/turtle/_projects/03_rust/struct-cli/Cargo.toml 750B src/ /home/turtle/_projects/03_rust/struct-cli/src total: 7 files · 41.2K types: rs(7) Cargo.lock /home/turtle/_projects/03_rust/struct-cli/Cargo.lock 21.1K .gitignore /home/turtle/_projects/03_rust/struct-cli/.gitignore 58B README.md /home/turtle/_projects/03_rust/struct-cli/README.md 12.1K docs/ /home/turtle/_projects/03_rust/struct-cli/docs total: 3 files · 35.9K types: html(1) js(1) css(1) install.sh /home/turtle/_projects/03_rust/struct-cli/install.sh 5.9K uninstall.sh /home/turtle/_projects/03_rust/struct-cli/uninstall.sh 3.4K .cargoignore /home/turtle/_projects/03_rust/struct-cli/.cargoignore 47B .github/ /home/turtle/_projects/03_rust/struct-cli/.github total: 2 dirs · 3 files · 1.2K types: md(2) yml(1) ── ignored (top level) ── .git(168 files), target(2399 files) · 2567 files · 751.5M vs . (git:master) ├── .git/ (168 files ignored) ├── .github/ ├── docs/ ├── src/ ├── target/ (2399 files ignored) ├── .cargoignore ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── install.sh ├── README.md └── uninstall.sh: 0=detailed summary, 1=simple one-level tree - Enhanced search to find both files AND directories - Added flag (pulls from Cargo.toml) - Improved path handling with canonicalization for git mode - Created interactive install.sh and uninstall.sh scripts - Updated README with comprehensive documentation