You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
team-pick.ts # renderTeamPickHeader — pick-mode candidate bar (pure, no I/O)
100
103
101
104
*.test.ts # Unit tests co-located with source files
102
105
test-setup.ts # Global test setup (Bun preload)
@@ -254,3 +257,6 @@ For minor/major releases update `docs/blog/index.md` to add a row in the version
254
257
- Shell-integration tests for `install.sh` live in `install.test.bats` and require `bats-core`. Run them with `bun run test:bats`. The CI runs them in a dedicated `test-bats` job using `bats-core/bats-action`.
255
258
-`picocolors` is the only styling dependency; do not add `chalk` or similar.
256
259
- Keep `knip` clean: every exported symbol must be used; every import must resolve.
260
+
- The `--pick-team` option is repeatable (Commander collect function); each assignment resolves one combined section label to a single team. A warning is emitted on stderr when a label is not found.
261
+
-`src/render/team-pick.ts` is a pure module (no I/O) and must be consumed only via the `src/render.ts` façade — it is imported **directly** inside `render.ts` for internal use but is not re-exported publicly (knip would flag it).
262
+
-`RepoGroup.pickedFrom` (optional field in `src/types.ts`) tracks the combined label a repo was moved from; future split-mode features will use this to offer re-assignment.
team-pick.ts # Pick-mode candidate bar renderer (renderTeamPickHeader) — pure, no I/O
49
+
team-pick.test.ts # Unit tests for team-pick.ts
46
50
output.ts # Text (markdown) and JSON output formatters
47
51
output.test.ts # Unit tests for output.ts
48
52
tui.ts # Interactive keyboard-driven UI (navigation, filter mode, help overlay)
@@ -60,7 +64,7 @@ bun test # TypeScript unit tests (co-located *.test.ts files)
60
64
bun run test:bats # Shell-integration tests for install.sh (requires bats-core)
61
65
```
62
66
63
-
TypeScript tests are co-located with their source files and cover the pure functions in `aggregate.ts`, `completions.ts`, `output.ts`, `render.ts`, `render/highlight.ts`, and `upgrade.ts`.
67
+
TypeScript tests are co-located with their source files and cover the pure functions in `aggregate.ts`, `completions.ts`, `group.ts`, `output.ts`, `render.ts`, `render/highlight.ts`, `render/team-pick.ts`, and `upgrade.ts`.
64
68
65
69
Shell-integration tests use [bats-core](https://github.com/bats-core/bats-core). Install it once with:
|**Filter & aggregation**|`src/aggregate.ts`|`aggregate()` — filters `CodeMatch[]` by repository and extract exclusion lists; normalises both `repoName` and `org/repoName` forms. |
106
-
|**Team grouping**|`src/group.ts`|`groupByTeamPrefix()` — groups `RepoGroup[]` into `TeamSection[]` keyed by team slug; `flattenTeamSections()` — converts back to a flat list for the TUI row builder. |
107
-
|**Shell completions**|`src/completions.ts`|`generateCompletion(shell)` — returns the full bash/zsh/fish completion script; `detectShell()` — reads `$SHELL`; `getCompletionFilePath(shell, opts)` — resolves the XDG-aware installation path. |
108
-
|**Row builder**|`src/render/rows.ts`|`buildRows()` — converts `RepoGroup[]` into `Row[]` filtered by the active target (path / content / repo); `rowTerminalLines()` — measures wrapped height; `isCursorVisible()` — viewport clipping. |
|**Filter stats**|`src/render/filter.ts`|`buildFilterStats()` — produces the `FilterStats` object (visible repos, files, matches) used by the TUI filter bar live counter. |
111
-
|**Pattern matchers**|`src/render/filter-match.ts`|`makeExtractMatcher()` — builds a case-insensitive substring or RegExp test function for path or content targets; `makeRepoMatcher()` — wraps the same logic for repo-name matching. |
112
-
|**Selection helpers**|`src/render/selection.ts`|`applySelectAll()` — marks all visible rows as selected (respects filter target); `applySelectNone()` — deselects all visible rows. |
113
-
|**Syntax highlighter**|`src/render/highlight.ts`|`highlightFragment()` — maps file extension to a language token ruleset and applies ANSI escape sequences. Falls back to plain text for unknown extensions. |
114
-
|**Output formatter**|`src/output.ts`|`buildOutput()` — entry point for both `--format markdown` and `--format json` serialisation of the confirmed selection. |
|**Filter & aggregation**|`src/aggregate.ts`|`aggregate()` — filters `CodeMatch[]` by repository and extract exclusion lists; normalises both `repoName` and `org/repoName` forms. |
110
+
|**Team grouping**|`src/group.ts`|`groupByTeamPrefix()` — groups `RepoGroup[]` into `TeamSection[]` keyed by team slug; `flattenTeamSections()` — converts back to a flat list for the TUI row builder; `applyTeamPick()` — moves repos from a combined section to a chosen team section; `rebuildTeamSections()` — reconstructs `TeamSection[]` from a flat list (used by TUI pick mode). |
111
+
|**Shell completions**|`src/completions.ts`|`generateCompletion(shell)` — returns the full bash/zsh/fish completion script; `detectShell()` — reads `$SHELL`; `getCompletionFilePath(shell, opts)` — resolves the XDG-aware installation path. |
112
+
|**Row builder**|`src/render/rows.ts`|`buildRows()` — converts `RepoGroup[]` into `Row[]` filtered by the active target (path / content / repo); `rowTerminalLines()` — measures wrapped height; `isCursorVisible()` — viewport clipping. |
|**Filter stats**|`src/render/filter.ts`|`buildFilterStats()` — produces the `FilterStats` object (visible repos, files, matches) used by the TUI filter bar live counter. |
115
+
|**Pattern matchers**|`src/render/filter-match.ts`|`makeExtractMatcher()` — builds a case-insensitive substring or RegExp test function for path or content targets; `makeRepoMatcher()` — wraps the same logic for repo-name matching. |
116
+
|**Selection helpers**|`src/render/selection.ts`|`applySelectAll()` — marks all visible rows as selected (respects filter target); `applySelectNone()` — deselects all visible rows. |
117
+
|**Syntax highlighter**|`src/render/highlight.ts`|`highlightFragment()` — maps file extension to a language token ruleset and applies ANSI escape sequences. Falls back to plain text for unknown extensions. |
118
+
|**Team pick bar**|`src/render/team-pick.ts`|`renderTeamPickHeader()` — renders the ANSI pick-mode candidate bar shown when the user presses `p` on a multi-team section header. Focused candidate is highlighted in bold magenta; others are dimmed. |
119
+
|**Output formatter**|`src/output.ts`|`buildOutput()` — entry point for both `--format markdown` and `--format json` serialisation of the confirmed selection. |
115
120
116
121
## Design principles
117
122
118
123
-**No I/O.** Every component in this layer is a pure function: given the same inputs it always returns the same outputs. This makes them straightforward to test with Bun's built-in test runner.
119
124
-**Single responsibility.** Each component owns exactly one concern (rows, summary, selection, …). The TUI composes them at render time rather than duplicating logic.
120
125
-**`types.ts` as the contract.** All components share the interfaces defined in `src/types.ts` (`TextMatchSegment`, `TextMatch`, `CodeMatch`, `RepoGroup`, `Row`, `TeamSection`, `OutputFormat`, `OutputType`, `FilterTarget`). Changes to these types require updating all components.
121
-
-**`render.ts` as façade.** External consumers import from `src/render.ts`, which re-exports all symbols from the `src/render/` sub-modules plus the top-level `renderGroups()` and `renderHelpOverlay()` functions.
126
+
-**`render.ts` as façade.** External consumers import from `src/render.ts`, which re-exports all symbols from the `src/render/` sub-modules plus the top-level `renderGroups()` and `renderHelpOverlay()` functions.`renderTeamPickHeader` is consumed internally by `render.ts` and is not re-exported (it is not part of the public façade).
0 commit comments