Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions changelog.d/unreleased/1426.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
category: fixed
issues:
- 1426
affected:
- src/CodeIndex/Cli/ConsoleUi.cs
- tests/CodeIndex.Tests/ConsoleUiTests.cs
---

## English

- **Wrapped exact-match help text to fit 80-column terminals (#1426)** — `--exact`, `--exact-substring`, and `--exact-name` usage text now avoids unpredictable mid-word wrapping in narrow terminals and CI logs.

## 日本語

- **exact-match 系ヘルプを 80 カラム端末に収まるよう折り返しました (#1426)** — `--exact`、`--exact-substring`、`--exact-name` の usage 表示が、狭い端末や CI ログで単語途中に折り返されにくくなりました。
15 changes: 12 additions & 3 deletions src/CodeIndex/Cli/ConsoleUi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -705,9 +705,18 @@ public static void PrintUsage(bool showBanner = true)
Console.WriteLine(" --focus-column <n> excerpt: column to keep centered when clamping (must be within the focused line)");
Console.WriteLine(" --focus-length <n> excerpt: width of the focused span (default: 1, requires --focus-column)");
Console.WriteLine($" --fts Use raw FTS5 query syntax for search (search query max {QueryLimits.MaxQueryLength} chars; raw FTS parser max {DbReader.MaxRawFtsQueryLength} chars, {DbReader.MaxRawFtsBooleanOperators} boolean ops, {DbReader.MaxRawFtsNearOperators} NEAR ops; trailing * is a prefix shorthand in literal-safe mode)");
Console.WriteLine(" --exact Backward-compatible shorthand. Prefer --exact-substring for search, keep --exact for find, and prefer --exact-name for symbols/definition/references/callers/callees/inspect. Pass at most one of --exact, --exact-substring, --exact-name; combining two or more is rejected.");
Console.WriteLine(" --exact-substring Search only: case-sensitive exact substring (no FTS5)");
Console.WriteLine(" --exact-name symbols/definition/references/callers/callees/inspect: NFKC + Unicode CaseFold exact name match (legacy/stale-fold DBs fall back to ASCII NOCASE; use `cdidx backfill-fold` or check `status --json` fold_ready)");
Console.WriteLine(" --exact Backward-compatible shorthand.");
Console.WriteLine(" Prefer --exact-substring for search,");
Console.WriteLine(" --exact for find,");
Console.WriteLine(" and --exact-name for symbol/graph lookups.");
Console.WriteLine(" Combining exact-match flags is rejected.");
Console.WriteLine(" --exact-substring Search only: case-sensitive exact substring");
Console.WriteLine(" (no FTS5)");
Console.WriteLine(" --exact-name Exact name match for symbols, definition,");
Console.WriteLine(" references, callers, callees, and inspect.");
Console.WriteLine(" Uses NFKC + Unicode CaseFold when ready.");
Console.WriteLine(" Legacy/stale-fold DBs fall back to ASCII NOCASE;");
Console.WriteLine(" run `cdidx backfill-fold` or check fold_ready.");
Console.WriteLine(" --kind <kind> definition/symbols/hotspots/unused: symbol kind; references: reference kind (call/instantiate/subscribe/attribute/annotation); callers/callees: call-graph kinds only (call/instantiate/subscribe — metadata kinds rejected, use references instead); validate: issue kind");
Console.WriteLine(" --visibility <v[,v]> Filter symbols/definitions/unused/hotspots by visibility: public, protected, internal, private");
Console.WriteLine(" --exclude-visibility <v[,v]> Exclude symbols/definitions/unused/hotspots by visibility");
Expand Down
40 changes: 37 additions & 3 deletions tests/CodeIndex.Tests/ConsoleUiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,18 @@ public void PrintUsage_WithoutBanner_HidesAsciiArtAndEasterEggFlags()
Assert.Contains("--max-line-width <n> search/references/find/excerpt/inspect only: clamp very long single-line snippet/context/excerpt payloads (`0` disables clamping; default: 512)", output);
Assert.Contains("cdidx find <query> --path <glob>", output);
Assert.Contains("--fts Use raw FTS5 query syntax for search (search query max 1000 chars; raw FTS parser max 2000 chars, 64 boolean ops, 16 NEAR ops", output);
Assert.Contains("--exact-substring Search only: case-sensitive exact substring (no FTS5)", output);
Assert.Contains("--exact-name symbols/definition/references/callers/callees/inspect: NFKC + Unicode CaseFold exact name match", output);
Assert.Contains("--exact Backward-compatible shorthand.", output);
Assert.Contains(" Prefer --exact-substring for search,", output);
Assert.Contains(" --exact for find,", output);
Assert.Contains(" and --exact-name for symbol/graph lookups.", output);
Assert.Contains(" Combining exact-match flags is rejected.", output);
Assert.Contains("--exact-substring Search only: case-sensitive exact substring", output);
Assert.Contains(" (no FTS5)", output);
Assert.Contains("--exact-name Exact name match for symbols, definition,", output);
Assert.Contains(" references, callers, callees, and inspect.", output);
Assert.Contains(" Uses NFKC + Unicode CaseFold when ready.", output);
Assert.Contains(" Legacy/stale-fold DBs fall back to ASCII NOCASE;", output);
Assert.Contains(" run `cdidx backfill-fold` or check fold_ready.", output);
Assert.Contains("--kind <kind> definition/symbols/hotspots/unused: symbol kind; references: reference kind (call/instantiate/subscribe/attribute/annotation); callers/callees: call-graph kinds only (call/instantiate/subscribe — metadata kinds rejected, use references instead); validate: issue kind", output);
Assert.Contains("--count Count only; search/definition/references/callers/callees/symbols/files/find/unused ignore --limit, impact/hotspots still use visible page counts", output);
Assert.Contains("--commits <id> [id ...] Update only files changed in the specified git commits (preferred after commits)", output);
Expand Down Expand Up @@ -108,7 +118,8 @@ public void PrintUsage_WithoutBanner_HidesAsciiArtAndEasterEggFlags()
Assert.Contains("backfill-fold", output);
Assert.Contains("optimize Optimize FTS5 segments in an existing index DB", output);
Assert.Contains("find <query> Find literal substring matches inside known indexed files", output);
Assert.Contains("Prefer --exact-substring for search, keep --exact for find", output);
Assert.Contains("Prefer --exact-substring for search", output);
Assert.Contains("--exact for find", output);
Assert.Contains("impact <query> Show transitive callers; type queries may return heuristic file-level dependency hints", output);
Assert.Contains("hotspots Find high-impact symbols; duplicate-name families may fall back conservatively", output);
Assert.Contains("cdidx find guard --path src/Auth.cs --after 2", output);
Expand All @@ -123,6 +134,29 @@ public void PrintUsage_WithoutBanner_HidesAsciiArtAndEasterEggFlags()
Assert.DoesNotContain("--random-spinner", output);
}

[Fact]
public void PrintUsage_ExactMatchOptionLines_FitWithinEightyColumns()
{
var output = CaptureUsageOutput(showBanner: false);
var lines = output.Split(Environment.NewLine);
var exactStart = Array.FindIndex(lines, line => line.StartsWith(" --exact ", StringComparison.Ordinal));
var exactSubstringStart = Array.FindIndex(lines, line => line.StartsWith(" --exact-substring", StringComparison.Ordinal));
var exactNameStart = Array.FindIndex(lines, line => line.StartsWith(" --exact-name", StringComparison.Ordinal));
var kindStart = Array.FindIndex(lines, line => line.StartsWith(" --kind <kind>", StringComparison.Ordinal));

Assert.True(exactStart >= 0);
Assert.True(exactSubstringStart > exactStart);
Assert.True(exactNameStart > exactSubstringStart);
Assert.True(kindStart > exactNameStart);

var exactMatchLines = lines[exactStart..kindStart]
.Where(line => line.Length > 0)
.ToArray();

Assert.NotEmpty(exactMatchLines);
Assert.All(exactMatchLines, line => Assert.True(line.Length <= 80, $"Line exceeds 80 columns ({line.Length}): {line}"));
}

[Fact]
public void PrintUsage_ShowsCommitUpdateWorkflowClearly()
{
Expand Down
Loading