Skip to content

Commit d7d1c0a

Browse files
authored
Merge pull request #81 from fulll/feat/shell-completions
feat: shell completions — bash, zsh and fish
2 parents 900ea04 + 66c67c8 commit d7d1c0a

17 files changed

Lines changed: 1159 additions & 165 deletions

.github/instructions/bug-fixing.instructions.md

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,21 @@ If the report is incomplete, do not guess. Review the relevant module(s) to loca
2121

2222
Use the module map in `AGENTS.md` to identify where the bug likely lives:
2323

24-
| Symptom | Look in |
25-
| -------------------------------------- | ---------------------------------- |
26-
| Wrong grouping / filtering of results | `src/aggregate.ts`, `src/group.ts` |
27-
| Incorrect markdown / JSON output | `src/output.ts` |
28-
| Wrong syntax highlighting | `src/render/highlight.ts` |
29-
| Bad row navigation or visibility | `src/render/rows.ts` |
30-
| Incorrect select-all / select-none | `src/render/selection.ts` |
31-
| Wrong stats / summary line | `src/render/summary.ts` |
32-
| Filter stats incorrect | `src/render/filter.ts` |
33-
| API pagination or rate-limit issue | `src/api.ts` |
34-
| TUI keyboard handling / display glitch | `src/tui.ts` |
35-
| Upgrade failure | `src/upgrade.ts` |
36-
| CLI option parsing / defaults | `github-code-search.ts` |
24+
| Symptom | Look in |
25+
| -------------------------------------------------- | -------------------------------------- |
26+
| Wrong grouping / filtering of results | `src/aggregate.ts`, `src/group.ts` |
27+
| Incorrect markdown / JSON output | `src/output.ts` |
28+
| Wrong syntax highlighting | `src/render/highlight.ts` |
29+
| Bad row navigation or visibility | `src/render/rows.ts` |
30+
| Incorrect select-all / select-none | `src/render/selection.ts` |
31+
| Wrong stats / summary line | `src/render/summary.ts` |
32+
| Filter stats incorrect | `src/render/filter.ts` |
33+
| API pagination or rate-limit issue | `src/api.ts` |
34+
| TUI keyboard handling / display glitch | `src/tui.ts` |
35+
| Upgrade failure | `src/upgrade.ts` |
36+
| CLI option parsing / defaults | `github-code-search.ts` |
37+
| Completion script wrong / not refreshed on upgrade | `src/completions.ts`, `src/upgrade.ts` |
38+
| Completion file written to wrong path | `src/completions.ts` |
3739

3840
## 3. Write a failing test before fixing
3941

.github/workflows/ci.yaml

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
name: CI
22

33
on:
4-
push:
5-
branches: ["**"]
64
pull_request:
75
branches: ["main"]
86

97
jobs:
108
test:
11-
name: Unit tests
9+
name: Test · Format · Lint · Dead code
1210
runs-on: ubuntu-latest
1311
permissions:
1412
pull-requests: write
@@ -30,28 +28,12 @@ jobs:
3028

3129
- name: Post LCOV coverage comment
3230
if: always() && github.event_name == 'pull_request'
33-
uses: romeovs/lcov-reporter-action@v0.3.1
31+
uses: romeovs/lcov-reporter-action@87a815f34ec27a5826abba44ce09bbc688da58fd # v0.4.0
3432
with:
3533
github-token: ${{ secrets.GITHUB_TOKEN }}
3634
lcov-file: coverage/lcov.info
3735
continue-on-error: true
3836

39-
quality:
40-
name: Format · Lint · Dead code
41-
runs-on: ubuntu-latest
42-
43-
steps:
44-
- name: Checkout
45-
uses: actions/checkout@v6
46-
47-
- name: Setup Bun
48-
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2
49-
with:
50-
bun-version: latest
51-
52-
- name: Install dependencies
53-
run: bun install --frozen-lockfile
54-
5537
- name: Check formatting (oxfmt)
5638
run: bun run format:check
5739

@@ -60,3 +42,26 @@ jobs:
6042

6143
- name: Dead code detection (knip)
6244
run: bun run knip
45+
46+
test-bats:
47+
name: Shell tests (bats)
48+
runs-on: ubuntu-latest
49+
permissions:
50+
contents: read
51+
52+
steps:
53+
- name: Checkout
54+
uses: actions/checkout@v6
55+
56+
- name: Setup Bats
57+
uses: bats-core/bats-action@77d6fb60505b4d0d1d73e48bd035b55074bbfb43 # v4.0.0
58+
with:
59+
support-install: false
60+
assert-install: false
61+
detik-install: false
62+
file-install: false
63+
github-token: ${{ secrets.GITHUB_TOKEN }}
64+
65+
- name: Run install.sh shell tests
66+
shell: bash
67+
run: bats install.test.bats

AGENTS.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,14 @@ The build script (`build.ts`) injects the git commit SHA, target OS and architec
3838
## Running tests
3939

4040
```bash
41-
bun test # run the whole test suite
41+
bun test # run the whole TypeScript test suite
4242
bun test --watch # re-run on file changes (development)
43+
bun run test:bats # run the shell-integration tests for install.sh (requires bats-core)
4344
```
4445

45-
All tests use Bun's built-in test runner (`@jest/globals`-compatible API: `describe`, `it`, `expect`). No additional testing library is needed. The setup file is `src/test-setup.ts` (referenced in `bunfig.toml`).
46+
All TypeScript tests use Bun's built-in test runner (`@jest/globals`-compatible API: `describe`, `it`, `expect`). No additional testing library is needed. The setup file is `src/test-setup.ts` (referenced in `bunfig.toml`).
47+
48+
Shell-integration tests use [bats-core](https://github.com/bats-core/bats-core) (`brew install bats-core` or install via your package manager). They cover `install_completions()` from `install.sh` and are located in `install.test.bats`.
4649

4750
## Linting & formatting
4851

@@ -58,7 +61,7 @@ Always run `bun run lint` and `bun run format:check` before considering a change
5861
## Project layout
5962

6063
```
61-
github-code-search.ts # CLI entry point — Commander subcommands: query, upgrade
64+
github-code-search.ts # CLI entry point — Commander subcommands: query, upgrade, completions
6265
build.ts # Build script (Bun.build)
6366
bunfig.toml # Bun configuration (smol install, test preload)
6467
tsconfig.json # TypeScript configuration
@@ -74,13 +77,16 @@ src/
7477
cache.ts # Disk cache for the team list (getCacheDir, getCacheKey,
7578
# readCache, writeCache) — performs filesystem I/O
7679
aggregate.ts # Result grouping & filtering (applyFiltersAndExclusions)
80+
completions.ts # Pure shell-completion generators: generateCompletion(),
81+
# detectShell(), getCompletionFilePath() — no I/O
7782
group.ts # groupByTeamPrefix — team-prefix grouping logic
7883
render.ts # Façade re-exporting sub-modules + top-level
7984
# renderGroups() / renderHelpOverlay()
8085
tui.ts # Interactive keyboard-driven UI (navigation, filter mode,
8186
# help overlay, selection)
8287
output.ts # Text (markdown) and JSON output formatters
8388
upgrade.ts # Auto-upgrade logic (fetch latest GitHub release, replace binary)
89+
# + refreshCompletions() — overwrites existing completion file
8490
8591
render/
8692
highlight.ts # Syntax highlighting (language detection + token rules)
@@ -108,6 +114,7 @@ src/
108114
- Only pure functions need tests; `tui.ts` and `api.ts` are not unit-tested.
109115
`api-utils.ts` is the exception: its helpers are unit-tested by mocking `globalThis.fetch`.
110116
`cache.ts` is also tested: it uses the `GITHUB_CODE_SEARCH_CACHE_DIR` env var override to redirect to a temp directory, so tests have no filesystem side effects on the real cache dir.
117+
`completions.ts` is fully unit-tested (`completions.test.ts`). Tests that exercise `getCompletionFilePath()` must unset `XDG_CONFIG_HOME`, `XDG_DATA_HOME`, and `ZDOTDIR` in `beforeEach` (and restore them in `afterEach`) to avoid contamination from the CI runner environment.
111118
- When adding a function to an existing module, add the corresponding test case in the existing `<module>.test.ts`.
112119
- When creating a new module that contains pure functions, create a companion `<module>.test.ts`.
113120
- Tests must be self-contained: no network calls, no filesystem side effects.
@@ -229,5 +236,8 @@ For minor/major releases update `docs/blog/index.md` to add a row in the version
229236
- The `--exclude-repositories` and `--exclude-extracts` options accept both short (`repoName`) and long (`org/repoName`) forms — this normalisation happens in `aggregate.ts`.
230237
- The `--group-by-team-prefix` option requires a `read:org` GitHub token scope; this is documented in `README.md`.
231238
- The `upgrade` subcommand replaces the running binary in-place using `src/upgrade.ts`; be careful with filesystem operations there.
239+
- After a successful upgrade, `refreshCompletions()` (in `src/upgrade.ts`) silently overwrites the existing completion file if one is already present. It never creates a file from scratch — installation is the user's responsibility (via `install.sh` or the `completions` subcommand).
240+
- The `completions` subcommand (in `github-code-search.ts`) prints the completion script for the detected (or specified) shell to stdout. It is a thin wrapper around `generateCompletion()` in `src/completions.ts`.
241+
- 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`.
232242
- `picocolors` is the only styling dependency; do not add `chalk` or similar.
233243
- Keep `knip` clean: every exported symbol must be used; every import must resolve.

CONTRIBUTING.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ bun install
1818
## Project structure
1919

2020
```
21-
github-code-search.ts # CLI entry point (Commander subcommands: query, upgrade)
21+
github-code-search.ts # CLI entry point (Commander subcommands: query, upgrade, completions)
2222
build.ts # Build script (compiles the standalone binary)
2323
src/
2424
types.ts # Shared TypeScript types (TextMatchSegment, CodeMatch, RepoGroup, Row, FilterTarget, …)
@@ -30,6 +30,8 @@ src/
3030
cache.test.ts # Unit tests for cache.ts
3131
aggregate.ts # Result grouping and filtering logic
3232
aggregate.test.ts # Unit tests for aggregate.ts
33+
completions.ts # Pure shell-completion generators (generateCompletion, detectShell, getCompletionFilePath)
34+
completions.test.ts # Unit tests for completions.ts
3335
render.ts # Façade: re-exports sub-modules + TUI renderGroups/renderHelpOverlay
3436
render.test.ts # Unit tests for render.ts (rows, filter, selection, rendering)
3537
render/
@@ -44,18 +46,28 @@ src/
4446
output.ts # Text (markdown) and JSON output formatters
4547
output.test.ts # Unit tests for output.ts
4648
tui.ts # Interactive keyboard-driven UI (navigation, filter mode, help overlay)
47-
upgrade.ts # Auto-upgrade logic (fetch latest release, replace binary)
49+
upgrade.ts # Auto-upgrade logic (fetch latest release, replace binary) + refreshCompletions()
4850
upgrade.test.ts # Unit tests for upgrade.ts
4951
dist/ # Compiled binary (git-ignored)
52+
install.sh # Install script (binary download + shell completions installation)
53+
install.test.bats # Shell-integration tests for install.sh (bats-core)
5054
```
5155

5256
## Running tests
5357

5458
```bash
55-
bun test
59+
bun test # TypeScript unit tests (co-located *.test.ts files)
60+
bun run test:bats # Shell-integration tests for install.sh (requires bats-core)
5661
```
5762

58-
Tests are co-located with their source files and cover the pure functions in `aggregate.ts`, `output.ts`, `render.ts`, `render/highlight.ts`, and `upgrade.ts`.
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`.
64+
65+
Shell-integration tests use [bats-core](https://github.com/bats-core/bats-core). Install it once with:
66+
67+
```bash
68+
brew install bats-core # macOS
69+
# or: sudo apt-get install -y bats # Debian/Ubuntu
70+
```
5971

6072
## Building a self-contained binary
6173

0 commit comments

Comments
 (0)