canopus 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -0
- data/README.md +191 -19
- data/assets/keymaps/emacs.jsonc +5 -0
- data/assets/keymaps/jetbrains.jsonc +5 -0
- data/assets/keymaps/sublime.jsonc +5 -0
- data/assets/keymaps/vscode.jsonc +5 -0
- data/docs/debugging.md +143 -0
- data/docs/distribution.md +40 -9
- data/docs/lsp.md +131 -0
- data/docs/performance.md +18 -0
- data/docs/providers.md +36 -0
- data/docs/release-log.md +12 -0
- data/docs/tasks.md +64 -0
- data/docs/testing.md +49 -0
- data/docs/vim.md +3 -0
- data/exe/canopus +4 -1
- data/lib/canopus/buffer.rb +291 -50
- data/lib/canopus/cli.rb +5 -2
- data/lib/canopus/command.rb +13 -4
- data/lib/canopus/controller.rb +183 -40
- data/lib/canopus/debug/breakpoints.rb +550 -0
- data/lib/canopus/debug/configuration.rb +291 -0
- data/lib/canopus/debug/console.rb +243 -0
- data/lib/canopus/debug/panel.rb +487 -0
- data/lib/canopus/debug/session.rb +354 -0
- data/lib/canopus/decoration.rb +4 -2
- data/lib/canopus/denebola_compat.rb +27 -0
- data/lib/canopus/diagnostics.rb +173 -0
- data/lib/canopus/display_map/overlay_map.rb +6 -2
- data/lib/canopus/editor/snippet_expandable.rb +3 -2
- data/lib/canopus/editor.rb +122 -31
- data/lib/canopus/git/state.rb +100 -0
- data/lib/canopus/language/background_analysis.rb +93 -14
- data/lib/canopus/language/document.rb +70 -34
- data/lib/canopus/language/symbol.rb +1 -0
- data/lib/canopus/language/syntax_worker.rb +61 -9
- data/lib/canopus/language.rb +3 -0
- data/lib/canopus/minimap.rb +201 -0
- data/lib/canopus/patch.rb +3 -1
- data/lib/canopus/plugins/api.rb +4 -2
- data/lib/canopus/plugins/isolated_runtime.rb +64 -7
- data/lib/canopus/plugins/registry.rb +114 -3
- data/lib/canopus/plugins.rb +8 -7
- data/lib/canopus/project.rb +15 -6
- data/lib/canopus/provider.rb +192 -0
- data/lib/canopus/regexp_compat.rb +36 -4
- data/lib/canopus/selection.rb +12 -0
- data/lib/canopus/settings/schema.rb +201 -0
- data/lib/canopus/settings.rb +328 -49
- data/lib/canopus/task/configuration.rb +356 -0
- data/lib/canopus/task/problem_matcher.rb +264 -0
- data/lib/canopus/task/runner.rb +314 -0
- data/lib/canopus/test_runner/bounded_ignore.rb +144 -0
- data/lib/canopus/test_runner/discovery.rb +97 -0
- data/lib/canopus/test_runner/execution.rb +194 -0
- data/lib/canopus/test_runner/minitest.rb +116 -0
- data/lib/canopus/test_runner/rspec.rb +103 -0
- data/lib/canopus/test_runner/safe_walker.rb +37 -0
- data/lib/canopus/test_runner.rb +54 -0
- data/lib/canopus/theme/import.rb +131 -0
- data/lib/canopus/theme.rb +28 -4
- data/lib/canopus/version.rb +1 -1
- data/lib/canopus/vim/motionable.rb +1 -1
- data/lib/canopus/vim.rb +10 -16
- data/lib/canopus/workspace/auto_savable.rb +83 -0
- data/lib/canopus/workspace/debug_aware.rb +600 -0
- data/lib/canopus/workspace/edit/plan.rb +2 -2
- data/lib/canopus/workspace/editor_configurable.rb +113 -0
- data/lib/canopus/workspace/file_change_aware.rb +11 -3
- data/lib/canopus/workspace/git_aware.rb +80 -34
- data/lib/canopus/workspace/git_blame.rb +175 -0
- data/lib/canopus/workspace/git_conflict_resolution.rb +410 -0
- data/lib/canopus/workspace/git_diff_view.rb +641 -0
- data/lib/canopus/workspace/git_history.rb +171 -0
- data/lib/canopus/workspace/git_remote.rb +267 -0
- data/lib/canopus/workspace/git_staging.rb +583 -0
- data/lib/canopus/workspace/hierarchy_aware.rb +477 -0
- data/lib/canopus/workspace/keymap_aware.rb +66 -0
- data/lib/canopus/workspace/language_aware.rb +3721 -135
- data/lib/canopus/workspace/language_server_configurable.rb +287 -71
- data/lib/canopus/workspace/persistent_undo.rb +169 -0
- data/lib/canopus/workspace/problems_aware.rb +131 -0
- data/lib/canopus/workspace/project_searchable.rb +88 -11
- data/lib/canopus/workspace/project_tree_editable.rb +3 -1
- data/lib/canopus/workspace/recoverable.rb +204 -0
- data/lib/canopus/workspace/session_persistable.rb +85 -13
- data/lib/canopus/workspace/settings_aware.rb +76 -2
- data/lib/canopus/workspace/task_aware.rb +194 -0
- data/lib/canopus/workspace/test_aware.rb +394 -0
- data/lib/canopus/workspace/trust.rb +73 -0
- data/lib/canopus/workspace/view/terminal_presentable.rb +298 -47
- data/lib/canopus/workspace/view.rb +399 -74
- data/lib/canopus/workspace.rb +688 -44
- data/lib/canopus.rb +20 -2
- data/sig/canopus.rbs +138 -31
- data/sig/controller.rbs +10 -3
- data/sig/debug.rbs +121 -0
- data/sig/decoration.rbs +12 -2
- data/sig/diagnostics.rbs +26 -0
- data/sig/minimap.rbs +20 -0
- data/sig/provider.rbs +29 -0
- data/sig/services.rbs +1 -16
- data/sig/task.rbs +92 -0
- data/sig/test_runner.rbs +109 -0
- data/sig/trust.rbs +17 -0
- data/sig/workspace_edits.rbs +2 -2
- data/sig/workspace_services.rbs +234 -2
- data/tools/check_dependencies.rb +21 -2
- data/tools/package.rb +172 -14
- data/tools/package_signature_test.rb +33 -0
- data/tools/package_test.rb +29 -0
- data/tools/sign_package.rb +123 -0
- data/tools/update.rb +189 -0
- data/tools/update_test.rb +71 -0
- metadata +206 -31
- data/lib/canopus/lsp/client.rb +0 -307
- data/lib/canopus/lsp/error.rb +0 -7
- data/lib/canopus/lsp/future/subscription.rb +0 -9
- data/lib/canopus/lsp/future.rb +0 -87
- data/lib/canopus/lsp/protocol.rb +0 -83
- data/lib/canopus/lsp/server_error.rb +0 -13
- data/lib/canopus/lsp/timeout.rb +0 -7
- data/lib/canopus/lsp/transport.rb +0 -123
- data/lib/canopus/lsp.rb +0 -19
- data/lib/canopus/project/search.rb +0 -164
- data/lib/canopus/project/search_worker/cancelled.rb +0 -3
- data/lib/canopus/project/search_worker/runner.rb +0 -9
- data/lib/canopus/project/search_worker.rb +0 -108
- data/lib/canopus/terminal/cell.rb +0 -7
- data/lib/canopus/terminal/grid.rb +0 -321
- data/lib/canopus/terminal/pty.rb +0 -178
- data/lib/canopus/terminal/scrollback.rb +0 -38
- data/lib/canopus/terminal/vt.rb +0 -398
- data/lib/canopus/terminal.rb +0 -13
- data/sig/lsp.rbs +0 -99
- data/sig/terminal.rbs +0 -130
data/docs/lsp.md
CHANGED
|
@@ -21,11 +21,142 @@ An absent or `null` entry auto-detects the language's default executable; it doe
|
|
|
21
21
|
not disable the server. If no executable is found, Canopus leaves that language
|
|
22
22
|
without a server. Invalid settings keep the previous working connection.
|
|
23
23
|
|
|
24
|
+
Configure multiple ordered servers with option objects and explicit feature
|
|
25
|
+
routing. The first matching server handles single-result features such as
|
|
26
|
+
formatting and definition; completion, diagnostics, and code actions are merged
|
|
27
|
+
from every matching server:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"language_servers": {
|
|
32
|
+
"ruby": [
|
|
33
|
+
{"command": ["ruby-lsp"], "features": ["completion", "definition", "hover", "formatting"]},
|
|
34
|
+
{"command": ["rubocop", "--lsp"], "features": ["diagnostics", "codeAction"]}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Omit `features` to route from negotiated server capabilities. The legacy
|
|
41
|
+
argument array (`"ruby": ["ruby-lsp"]`) remains a single-server command. The
|
|
42
|
+
status bar shows each connection, and `language.restart_server` restarts one
|
|
43
|
+
selected server without disturbing the others.
|
|
44
|
+
|
|
24
45
|
Changes to the command, environment, or initialization options restart the
|
|
25
46
|
connection and reopen its documents. A configuration-only change sends
|
|
26
47
|
`workspace/didChangeConfiguration` without restarting. Resource-changing server
|
|
27
48
|
requests require confirmation as described in [workspace edits](workspace_edits.md).
|
|
28
49
|
|
|
50
|
+
Save-time actions are opt-in and run before the file write. Formatting runs
|
|
51
|
+
first, followed by the first enabled action returned for each configured kind:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"format_on_save": true,
|
|
56
|
+
"code_actions_on_save": ["source.organizeImports", "source.fixAll"],
|
|
57
|
+
"format_on_save_timeout": 2000
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The timeout covers the complete sequence. A timeout, stale or invalid edit, or
|
|
62
|
+
server failure is reported without preventing the save; edits to the saved
|
|
63
|
+
document accepted before a later failure remain grouped as one undo step.
|
|
64
|
+
Server edits use the normal version-checked workspace-edit path. Resource
|
|
65
|
+
operations are rejected during an automatic save action. An untitled document
|
|
66
|
+
establishes its URI on the first Save As, so its save-time actions begin with
|
|
67
|
+
the next save.
|
|
68
|
+
|
|
69
|
+
Published diagnostics are shown as severity-colored wave underlines. The most
|
|
70
|
+
severe message on each line is also shown at line end by default. Configure this
|
|
71
|
+
with `diagnostics.inline`, `diagnostics.inline_max_length`, and the minimum
|
|
72
|
+
`diagnostics.severity` (`error`, `warning`, `information`, or `hint`).
|
|
73
|
+
|
|
74
|
+
The Problems panel groups validated local-file diagnostics by file and also
|
|
75
|
+
accepts task and test sources through the diagnostics registry. Selecting a
|
|
76
|
+
problem opens its exact source position. `problems.filter` filters the tree by
|
|
77
|
+
free text and optional terms such as `severity:warning` and `source:task`; the
|
|
78
|
+
status bar shows current error and warning totals.
|
|
79
|
+
|
|
80
|
+
Task and test integrations publish the same validated LSP-shaped records with
|
|
81
|
+
`workspace.diagnostics.publish(:task, uri, diagnostics)` or `:test`. Publishing
|
|
82
|
+
an empty array removes that source's records for the URI.
|
|
83
|
+
|
|
84
|
+
Inlay hints are fetched for the visible source lines plus 50 lines of context and
|
|
85
|
+
shown inline. Label parts with a server-provided location are clickable. Configure
|
|
86
|
+
type and parameter-name hints, or their display limit, with `inlay_hints.types`,
|
|
87
|
+
`inlay_hints.parameter_names`, and `inlay_hints.max_length`; set
|
|
88
|
+
`inlay_hints.enabled` to `false` to disable requests.
|
|
89
|
+
|
|
90
|
+
Code lenses are cached for each document version and shown above their source
|
|
91
|
+
line. Unresolved lenses are resolved only as they enter the viewport; click a
|
|
92
|
+
lens to execute its server command. Set `code_lens.enabled` to `false` to
|
|
93
|
+
disable requests and hide cached lenses.
|
|
94
|
+
|
|
95
|
+
When supported, `textDocument/documentHighlight` automatically marks reads,
|
|
96
|
+
writes, and textual occurrences at each visible editor's caret. Results are
|
|
97
|
+
kept per split and caret, and are discarded when the caret or document changes,
|
|
98
|
+
the tab closes, or the language server is replaced.
|
|
99
|
+
|
|
100
|
+
`textDocument/documentLink` results are underlined and clickable in each visible
|
|
101
|
+
editor. Links without a target are resolved only when clicked. Canopus opens
|
|
102
|
+
HTTP(S) targets through the platform and local `file` targets in an editor;
|
|
103
|
+
remote file URIs and executable or custom URI schemes are rejected. Cached links
|
|
104
|
+
and pending resolutions are discarded after edits, hidden tabs, document close,
|
|
105
|
+
settings changes, or server replacement.
|
|
106
|
+
|
|
107
|
+
`editor.fold` prefers cached `textDocument/foldingRange` results and folds the
|
|
108
|
+
smallest range containing the caret's source line. Servers without folding
|
|
109
|
+
support, null or failed responses, and unconfigured languages fall back to
|
|
110
|
+
asynchronous Antares structure analysis; the UI thread never waits for either
|
|
111
|
+
source.
|
|
112
|
+
|
|
113
|
+
`Alt-Up` expands every selection through its nested
|
|
114
|
+
`textDocument/selectionRange` chain and `Alt-Down` restores the exact previous
|
|
115
|
+
selection. Unsupported, null, failed, or invalid responses fall back to
|
|
116
|
+
asynchronous Antares structure analysis. Move-line shortcuts use
|
|
117
|
+
`Alt-Shift-Up` and `Alt-Shift-Down`.
|
|
118
|
+
|
|
119
|
+
`F2` asks servers advertising rename preparation to validate the exact document
|
|
120
|
+
version and caret before opening the rename dialog. The prepared range,
|
|
121
|
+
placeholder, or client-side identifier pre-fills the dialog; edits, caret moves,
|
|
122
|
+
hidden tabs, server replacement, and settings reload cancel the snapshot. Servers
|
|
123
|
+
without preparation support, and unconfigured languages, keep the regular rename
|
|
124
|
+
dialog.
|
|
125
|
+
|
|
126
|
+
Run `language.linked_editing` from the command palette to request
|
|
127
|
+
`textDocument/linkedEditingRange`. Canopus maps the current primary selection's
|
|
128
|
+
relative anchor and caret to every validated, non-overlapping linked range and
|
|
129
|
+
creates multiple selections. The request is cancelled when the selection,
|
|
130
|
+
document, visible tab, settings, or server changes. Continuous linked editing
|
|
131
|
+
is intentionally left to the editor's normal multi-selection behavior. If no
|
|
132
|
+
server is available, or the server does not support the request, returns null,
|
|
133
|
+
fails, or times out, HTML and XML use a bounded fallback for unambiguous matching
|
|
134
|
+
opening and closing tag names. HTML names are ASCII case-insensitive; XML names
|
|
135
|
+
are exact and may contain Unicode. Self-closing and HTML void elements are not
|
|
136
|
+
linked.
|
|
137
|
+
|
|
138
|
+
Run `language.call_hierarchy` or `language.type_hierarchy` from the command
|
|
139
|
+
palette to prepare a hierarchy at the caret. If the server returns more than
|
|
140
|
+
one root, choose one from the palette. The right-side Hierarchy panel loads
|
|
141
|
+
incoming and outgoing calls, or supertypes and subtypes, only as branches are
|
|
142
|
+
expanded. Selecting an item opens its local file and source range; remote file
|
|
143
|
+
URIs are rejected.
|
|
144
|
+
|
|
145
|
+
Press Cmd-T on macOS or Ctrl-T elsewhere, or run
|
|
146
|
+
`language.workspace_symbols`, and enter a query. Canopus requests
|
|
147
|
+
`workspace/symbol` from every active server routed to `workspaceSymbol` under
|
|
148
|
+
one ten-second deadline, keeps configuration order while removing duplicate
|
|
149
|
+
results, and uses Spica to refine the returned locations. Selecting a result
|
|
150
|
+
opens its local file and range. If no routed server is running, or every routed
|
|
151
|
+
provider fails, a background Alkaid content search supplies bounded local-file
|
|
152
|
+
matches using the project's ignore rules. Queries are limited to 256 bytes and
|
|
153
|
+
results to 10,000 entries.
|
|
154
|
+
|
|
155
|
+
Sticky scroll prefers `textDocument/documentSymbol` when the server advertises
|
|
156
|
+
it and uses cached Antares structure regions otherwise. Requests and normalized
|
|
157
|
+
symbol trees are tied to the current buffer version and discarded after edits,
|
|
158
|
+
document close, or server retirement; painting never waits for either source.
|
|
159
|
+
|
|
29
160
|
Editor positions use UTF-8 byte offsets internally and are converted to LSP
|
|
30
161
|
UTF-16 positions. Servers selecting another position encoding are rejected.
|
|
31
162
|
Messages are limited to 32 MiB, crashes fail pending requests, and a connection
|
data/docs/performance.md
CHANGED
|
@@ -29,8 +29,17 @@ private directory with appropriate ACLs.
|
|
|
29
29
|
|
|
30
30
|
Developers can produce current, reproducible measurements with:
|
|
31
31
|
|
|
32
|
+
```sh
|
|
33
|
+
BUDGET=1 ruby bench/require.rb
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The require-only budget is 300 ms in a fresh Ruby process. It covers the
|
|
37
|
+
library load, not window creation or the first rendered frame; those remain
|
|
38
|
+
measured by the startup benchmark below.
|
|
39
|
+
|
|
32
40
|
```sh
|
|
33
41
|
ruby --yjit bench/frame_profile.rb --frames 120 --output /tmp/frames.json
|
|
42
|
+
ruby --yjit bench/minimap.rb
|
|
34
43
|
ruby bench/startup.rb --runs 3
|
|
35
44
|
ruby --yjit tools/native_check.rb --idle /tmp/native-check.png
|
|
36
45
|
```
|
|
@@ -38,3 +47,12 @@ ruby --yjit tools/native_check.rb --idle /tmp/native-check.png
|
|
|
38
47
|
Compare results only when the platform, renderer, viewport, Ruby/JIT mode,
|
|
39
48
|
warmup, and diagnostic options match. Headless software rendering is a regression
|
|
40
49
|
check, not a hardware-GPU performance result.
|
|
50
|
+
|
|
51
|
+
Bracket colors and indentation guides are requested and cached by visible source
|
|
52
|
+
rows. Structural analysis stays in the bounded language worker; files on the
|
|
53
|
+
large read-only path skip these decorations instead of scanning on the UI thread.
|
|
54
|
+
|
|
55
|
+
`bench/minimap.rb` renders a 10,000-line file through the real headless renderer.
|
|
56
|
+
It asserts the per-frame cold-generation bound, texture reuse while scrolling,
|
|
57
|
+
one-row regeneration after an edit, and warm p95 against a same-run minimap-off
|
|
58
|
+
baseline. Compare raw timings only on the same Ruby, font, scale factor, and renderer.
|
data/docs/providers.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Completion providers
|
|
2
|
+
|
|
3
|
+
`workspace.providers` combines completion sources without coupling the editor to
|
|
4
|
+
a particular language server. Canopus registers LSP completion itself; plugins
|
|
5
|
+
and embedders can add sources with `register_completion`:
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
workspace.providers.register_completion(:project_terms, priority: 20) do |buffer, offset, context|
|
|
9
|
+
[Canopus::Provider::Completion.new(
|
|
10
|
+
"ProjectName", "ProjectName", :constant, "Project term", nil,
|
|
11
|
+
nil, nil, [], :project_terms
|
|
12
|
+
)]
|
|
13
|
+
end
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The block runs away from the UI thread and receives the current buffer, UTF-8
|
|
17
|
+
byte offset, and a context hash whose `:query` is the word prefix. It returns an
|
|
18
|
+
array of `Completion` records, or an awaitable with `await(timeout:)`. Results
|
|
19
|
+
are fuzzy-ranked with Spica; higher source priority is the stable tie-break. Duplicate
|
|
20
|
+
label/insertion pairs keep the higher-ranked source. Invalid, oversized, or
|
|
21
|
+
failed sources are omitted without hiding results from healthy sources. All
|
|
22
|
+
sources share a ten-second completion deadline, rather than multiplying that
|
|
23
|
+
deadline by the number of registered providers.
|
|
24
|
+
|
|
25
|
+
Use source `:snippet` (or kind `:snippet`) when `insert_text` contains LSP/
|
|
26
|
+
TextMate snippet syntax. Additional edits are `[Range, String]` pairs and are
|
|
27
|
+
preflighted with the main insertion before editing.
|
|
28
|
+
|
|
29
|
+
Ghost-text integrations can register a block with
|
|
30
|
+
`register_inline_completion(source)`. `inline_completion(buffer, offset)` uses
|
|
31
|
+
the first registered provider that returns a valid non-nil string. Canopus only
|
|
32
|
+
provides this boundary today; AI, word, and path providers belong to their
|
|
33
|
+
respective later features or plugins.
|
|
34
|
+
|
|
35
|
+
At most 64 providers of each kind, 10,000 combined completion records, 1,000
|
|
36
|
+
additional edits per record, and 64 KiB per string are accepted.
|
data/docs/release-log.md
CHANGED
|
@@ -2,4 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
| Date | Repository | Version | Canopus follow-up | Reason |
|
|
4
4
|
| --- | --- | --- | --- | --- |
|
|
5
|
+
| 2026-09-18 | kochab | 0.2.0 | 2026-09-18 | Settings schema metadata and safe layer merge API |
|
|
6
|
+
| 2026-09-18 | tarazed | 0.2.4 | 2026-09-18 | Explicit command-history clearing for terminal consumers |
|
|
7
|
+
| 2026-09-18 | tarazed | 0.2.3 | 2026-09-18 | Shell executable detection for argument-bearing and Windows commands |
|
|
8
|
+
| 2026-09-17 | thuban | 0.6.0 | 2026-09-17 | Transactional merge-conflict snapshots and resolution |
|
|
9
|
+
| 2026-09-17 | thuban | 0.5.0 | 2026-09-17 | Atomic partial staging and managed Git transfers |
|
|
10
|
+
| 2026-09-17 | thuban | 0.4.1 | 2026-09-17 | Lazy remote provider loading for headless startup |
|
|
11
|
+
| 2026-09-17 | tarazed | 0.2.2 | 2026-09-17 | Drain final Windows ConPTY output after process exit |
|
|
12
|
+
| 2026-09-16 | megrez | 0.1.1 | 2026-09-16 | Debug Adapter Protocol session lifecycle |
|
|
13
|
+
| 2026-09-16 | antares | 0.2.1 | 2026-09-16 | CRLF-safe selection range columns |
|
|
14
|
+
| 2026-09-16 | denebola | 0.2.1 | 2026-09-16 | Deterministic same-offset edit and anchor mapping |
|
|
15
|
+
| 2026-09-15 | thuban | 0.4.0 | 2026-09-17 | Git write, commit, history, stash, and remote APIs |
|
|
16
|
+
| 2026-09-15 | porrima | 0.2.0 | 2026-09-17 | Structured three-way merge conflict resolution |
|
|
5
17
|
| 2026-09-14 | thuban | 0.2.0 | 2026-09-14 | Public `IgnoreMatcher` API |
|
data/docs/tasks.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Tasks
|
|
2
|
+
|
|
3
|
+
Project tasks live in `.canopus/tasks.jsonc`. Open **Run Task** from the command
|
|
4
|
+
palette or press Cmd-Shift-B on macOS / Ctrl-Shift-B on Linux and Windows.
|
|
5
|
+
|
|
6
|
+
```jsonc
|
|
7
|
+
{
|
|
8
|
+
"problem_matchers": {
|
|
9
|
+
"ruby": {
|
|
10
|
+
"owner": "ruby",
|
|
11
|
+
"file_location": ["relative", "${workspaceFolder}"],
|
|
12
|
+
"pattern": {
|
|
13
|
+
"regexp": "^(.+):(\\d+):(?:(\\d+):)?\\s*(warning|error):\\s*(.+)$",
|
|
14
|
+
"file": 1, "line": 2, "column": 3, "severity": 4, "message": 5,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
"tasks": [
|
|
19
|
+
{
|
|
20
|
+
"label": "rake test",
|
|
21
|
+
"command": ["bundle", "exec", "rake", "test"],
|
|
22
|
+
"cwd": "${workspaceFolder}",
|
|
23
|
+
"problem_matcher": "ruby",
|
|
24
|
+
"presentation": { "panel": "output", "reveal": "always" },
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Commands are argument arrays and are passed directly to `Tarazed::PTY`; Canopus
|
|
31
|
+
does not interpolate a shell command string. Each task has one Output tab.
|
|
32
|
+
Running the same label again replaces its previous process and tab. Select a
|
|
33
|
+
tab and run **Stop Task** (Ctrl-C while its output is focused) to stop only that
|
|
34
|
+
task. Output supports terminal colors and interactive input.
|
|
35
|
+
|
|
36
|
+
The available variables are `${workspaceFolder}`, `${file}`,
|
|
37
|
+
`${lineNumber}`, `${selectedText}`, and `${env:NAME}`. Missing variables are
|
|
38
|
+
errors. `cwd` and file variables must stay inside the canonical workspace;
|
|
39
|
+
symlink escapes are rejected.
|
|
40
|
+
|
|
41
|
+
`presentation.panel` is currently `output`. `reveal` accepts `always` (show at
|
|
42
|
+
start), `silent` (show only after a failing exit), or `never`.
|
|
43
|
+
|
|
44
|
+
A problem matcher can use one `pattern` object or an array of up to eight
|
|
45
|
+
patterns for a multi-line diagnostic. Captures are 1-based and may specify
|
|
46
|
+
`file`, `line`, `column`, `end_line`, `end_column`, `severity`, and `message`;
|
|
47
|
+
`file`, `line`, and `message` are required across the sequence. Matching files
|
|
48
|
+
must already exist inside the canonical workspace. Matches are published with
|
|
49
|
+
source `task`, so they appear in editor diagnostics and the Problems panel.
|
|
50
|
+
|
|
51
|
+
Long-running tasks can add `background` with `begins_pattern`, `ends_pattern`,
|
|
52
|
+
and optional `active_on_start`. A begin match starts a fresh cycle and clears
|
|
53
|
+
the previous cycle's diagnostics; an end match pauses matching until the next
|
|
54
|
+
begin marker. `active_on_start` defaults to `false`.
|
|
55
|
+
|
|
56
|
+
Task files and expansion are limited to 1 MiB, 128 definitions, and 32 retained
|
|
57
|
+
Output tabs. Each PTY uses the configured terminal scrollback and queue limits,
|
|
58
|
+
and all output parsing remains frame-budgeted. Matcher lines and unfinished
|
|
59
|
+
input are limited to 64 KiB, each matcher retains at most 1,000 diagnostics,
|
|
60
|
+
and regular expressions use a timeout. A matcher that times out is disabled for
|
|
61
|
+
the rest of that task run while its already-published diagnostics are retained.
|
|
62
|
+
On Ruby 3.1, one timeout on a complete line is deferred to the next frame before
|
|
63
|
+
disabling, which avoids dropping a matcher after a transient scheduler delay;
|
|
64
|
+
an unterminated final line is disabled on its first timeout.
|
data/docs/testing.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Test explorer
|
|
2
|
+
|
|
3
|
+
Open the **Tests** panel with `panel.test`. Canopus discovers tests in the
|
|
4
|
+
background the first time the panel opens. Run `test.refresh` after changing
|
|
5
|
+
test declarations; filesystem changes also refresh an explorer that has
|
|
6
|
+
already been opened.
|
|
7
|
+
|
|
8
|
+
Discovery uses Alkaid's workspace walker and the same Git and project ignore
|
|
9
|
+
rules as project search. Ruby files in `test/`, ending in `_test.rb`, or named
|
|
10
|
+
`test_*.rb` use the Minitest adapter; files in `spec/` or ending in `_spec.rb`
|
|
11
|
+
use the RSpec adapter. An explicit `_test.rb` or `_spec.rb` suffix takes
|
|
12
|
+
precedence over a containing directory name.
|
|
13
|
+
Prism parses each candidate and adapters inspect its AST; comments, strings,
|
|
14
|
+
and syntactically invalid files are not treated as tests.
|
|
15
|
+
|
|
16
|
+
The Minitest adapter recognizes `test_` methods in classes, `test` blocks, and
|
|
17
|
+
Minitest spec-style `describe` / `context` groups with `it` or `specify`
|
|
18
|
+
examples. The RSpec adapter recognizes nested `describe`, `context`, and
|
|
19
|
+
`feature` groups plus their focused and skipped aliases, and `it`, `specify`,
|
|
20
|
+
`example`, and `scenario` examples. Test nodes retain only their framework,
|
|
21
|
+
workspace-relative path, static name, group path, source position, and bounded
|
|
22
|
+
framework selector.
|
|
23
|
+
Selecting a test opens its current source line after rechecking that the file
|
|
24
|
+
is still a regular file inside the canonical workspace. Each discovered test
|
|
25
|
+
also has a gutter button. The marker changes from run to running, passed,
|
|
26
|
+
failed, or skipped; clicking it starts that one static test through the shared
|
|
27
|
+
Task Output runner. Multiple declarations on one line run together.
|
|
28
|
+
|
|
29
|
+
Minitest runs use an exact suite/method filter. RSpec combines the discovered
|
|
30
|
+
source line with an exact full-description filter. Commands are fixed argument
|
|
31
|
+
arrays rather than shell strings. A regular workspace `Gemfile` is run with
|
|
32
|
+
`bundle exec`; inherited editor bundle state is
|
|
33
|
+
removed before the child starts. Output remains available in the bounded
|
|
34
|
+
Output panel and stopping or closing its tab cancels the run.
|
|
35
|
+
|
|
36
|
+
Failed runs publish a `test` diagnostic and retain a 256 KiB tail of output to
|
|
37
|
+
locate the test frame. Selecting a failed test, or its Problems entry, opens
|
|
38
|
+
that failure line. If no safe frame is present, Canopus falls back to the
|
|
39
|
+
discovered declaration.
|
|
40
|
+
|
|
41
|
+
Discovery does not follow symlinks. It scans at most 50,000 workspace files,
|
|
42
|
+
2,000 candidate test files, and 10,000 tests, with a maximum traversal depth of
|
|
43
|
+
64. Candidate files are limited to 1 MiB, names to 4 KiB, and adapter AST walks
|
|
44
|
+
to 100,000 nodes per file. Invalid UTF-8, NUL-containing, inaccessible,
|
|
45
|
+
oversized, and escaped paths are skipped. Refresh cancels stale work and keeps
|
|
46
|
+
at most one discovery worker active; closing the workspace cancels and joins
|
|
47
|
+
that worker.
|
|
48
|
+
|
|
49
|
+
Generating a debug launch remains a separate feature.
|
data/docs/vim.md
CHANGED
|
@@ -22,3 +22,6 @@ Vimscript, arbitrary shell commands, and user mappings are not interpreted.
|
|
|
22
22
|
Clipboard registers `+` and `*` are in-memory registers rather than OS clipboard
|
|
23
23
|
integrations. Counts are capped at 10,000; macro playback allows 10 nested calls
|
|
24
24
|
and 10,000 keys.
|
|
25
|
+
|
|
26
|
+
Insert and Replace modes follow Vim's literal insertion behavior and do not
|
|
27
|
+
apply the editor's `auto_pairs` setting.
|
data/exe/canopus
CHANGED
|
@@ -13,7 +13,10 @@ unless RUBY_PLATFORM.match?(/mswin|mingw/) || RbConfig::CONFIG["YJIT_SUPPORT"] !
|
|
|
13
13
|
exec(RbConfig.ruby, *flags, __FILE__, *ARGV)
|
|
14
14
|
end
|
|
15
15
|
ENV.delete("CANOPUS_YJIT_REEXEC")
|
|
16
|
-
|
|
16
|
+
canopus_root = File.expand_path("..", __dir__)
|
|
17
|
+
Gem::Specification.find_all_by_name("canopus")
|
|
18
|
+
.find { |specification| File.expand_path(specification.full_gem_path) == canopus_root }&.activate
|
|
19
|
+
$LOAD_PATH.unshift(File.join(canopus_root, "lib"))
|
|
17
20
|
require "canopus"
|
|
18
21
|
require "canopus/cli"
|
|
19
22
|
exit Canopus::CLI.main(ARGV)
|