Feat/genspec tui - #38
Merged
Merged
Conversation
fredbi
force-pushed
the
feat/genspec-tui
branch
8 times, most recently
from
June 17, 2026 18:53
9c48c39 to
0c2351b
Compare
fredbi
force-pushed
the
feat/genspec-tui
branch
2 times, most recently
from
July 31, 2026 12:27
f4d9bb4 to
bf1e085
Compare
❌ 6 Tests Failed:
View the top 3 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
A terminal front-end for codescan: point it at a package tree and it shows the Go source and the Swagger spec that source produces, side by side, rescanning as the files change. It is a self-contained module under cmd/genspec-tui so the library takes on none of its dependencies. Four panes — a source tree, a file view, the generated spec, and the scanner's diagnostics — over a debounced watcher that rescans on save and re-renders without losing your place. The spec pane renders JSON or YAML, searches, and keeps a line cursor that survives a rebuild by remembering the NODE it was on rather than the line number, which changes on every render. Cross-reference navigation is the reason the two halves sit together. The scanner reports, for each spec node it produces, the source position of the Go construct that produced it; that stream is indexed both ways against the exact bytes each pane draws, so a spec node resolves to its source and a source line resolves to the node it produced. From there: follow mode, where one pane drives and the other mirrors; a one-shot jump; find-references over a definition's use sites; go-to-definition on a local $ref; and a gutter marking which lines actually lead somewhere. Because every one of those is keyed on a line number, the file, the buffer, the indexes and the marks must agree on what a line is. The editor widget treats a lone CR as a line break, so a file with Windows endings would otherwise load as twice as many lines with a blank between each, and every coordinate below the first CR would name a line a growing distance from the one meant. Content is normalised to LF on the way in, giving all four one shared notion. The linker answers honestly when it cannot help. A node with no anchored ancestor was never produced from code — an overlay node legitimately has no origin — and says so instead of jumping somewhere plausible. A node that resolves but is not rendered in the active view says that instead. With unsaved edits in the buffer every position below the edit has moved, so follow mode shows a staleness badge until a save triggers a rescan. Both panes are syntax-highlighted with no highlighting library involved. The spec pane reuses the lexer that already builds its line-to-pointer index, so classification is a third product of one walk. The source pane uses go/scanner, which is error tolerant, so a buffer you are halfway through editing still highlights. Comments there get three classes rather than one, because in a spec generator a comment is not uniformly commentary: a `swagger:` line is the annotation that declares the thing, a leading grammar keyword is grammar the parser acts on, and the rest is prose. Keyword recognition goes through the parser's own table, so aliases and letter case come for free. The scanner's diagnostics are drawn on the token they name, so a finding is visible on the line you are reading rather than only in the pane below. Highlighting composes by (line, column, kind) spans rather than pre-coloured strings: the raw text is truncated at rune boundaries first and styled last, which is the only order in which a narrow pane cannot cut through an escape sequence. Positions are translated between the file's byte columns and the buffer's rune columns, since the editor widget substitutes spaces for tabs. Scanner options are editable at runtime through a grouped overlay that marks a toggle moot when the option it depends on is off, and every value-typed option is a CLI flag. A key-bindings overlay behind `h` or `?` documents the lot, with a header chip pointing at it. Diagnostics are navigable and jump to source like every other pane, and every navigable pane pages. Known limits are documented in the module README rather than left to be discovered: editing is a plain textarea that normalises tabs to spaces and CRLF endings to LF when saving, edit mode is not highlighted, and $ref resolution is a site index rather than a resolver, so chains and external refs are reported rather than chased. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
Brings the new module into the workspace so `go test work ./...` covers it and the shared CI runs it, rather than the module carrying a bespoke workflow of its own. The `go` directive moves to 1.25.8 across every module and the workspace file. That is not a preference: the JSON and YAML lexers in go-openapi/core declare go 1.25.8, and a module's directive must be at least its dependencies'. Only cmd/genspec-tui requires those lexers, so only it is forced; the rest are aligned to it deliberately, and the workspace file must be at least the highest of them. The floor moves by a patch rather than a minor, so the supported Go minors are unchanged and the toolchain-independence job's oldstable assumption still holds — its note is updated to record which value it now depends on and why, since it named the old one. Four linters are excluded for this module by path, each with its reason: the layout arithmetic that mnd flags is code where the number is the explanation, the switches exhaustive flags read open-ended keyboard and mouse input rather than a closed domain, and unparam flags helpers that keep a general signature. The library keeps all of them. Everything else the linters found is fixed rather than excused, including the module-local ordering drift. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
.gitattributes already states the rule — golden fixtures must keep LF endings
on every platform so byte comparison does not trip on a checkout defaulting to
core.autocrlf=true — but listed only *.json and two golden directories. The
polymorphism tutorial's diagnostics golden is a .txt, so on Windows it was read
back with CRLF and compared against a string joined with LF:
expected: "...discovered as a subtype of...\r\n"
actual: "...discovered as a subtype of...\n"
Extending the pattern to *.txt covers it. The three .txt files tracked here are
that golden, the spellcheck wordlist and a vendored README, so the wider glob
costs nothing and stops the next golden of that kind from slipping through.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Frederic BIDON <fredbi@yahoo.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Change type
Please select: 🆕 New feature or enhancement|🔧 Bug fix'|📃 Documentation update
Short description
Fixes
Full description
Checklist