canopus 0.1.0 → 0.2.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 +9 -0
- data/README.md +118 -86
- data/assets/canopus-editor.png +0 -0
- data/assets/logo.png +0 -0
- data/docs/adr/000-template.md +24 -0
- data/docs/adr/002-bounded-diff-engine.md +4 -4
- data/docs/adr/006-tab-close-lifetime.md +25 -0
- data/docs/adr/007-terminal-key-routing.md +24 -0
- data/lib/canopus/controller.rb +101 -23
- data/lib/canopus/language/syntax_worker.rb +1 -0
- data/lib/canopus/pane.rb +18 -2
- data/lib/canopus/settings.rb +53 -1
- data/lib/canopus/terminal/pty.rb +92 -17
- data/lib/canopus/version.rb +1 -1
- data/lib/canopus/workspace/git_aware.rb +25 -20
- data/lib/canopus/workspace/session_persistable.rb +32 -1
- data/lib/canopus/workspace/view/terminal_presentable.rb +57 -17
- data/lib/canopus/workspace/view.rb +22 -10
- data/lib/canopus/workspace.rb +303 -17
- data/lib/canopus.rb +2 -1
- data/sig/canopus.rbs +28 -1
- data/sig/controller.rbs +1 -0
- data/sig/terminal.rbs +7 -2
- data/sig/workspace_services.rbs +4 -2
- data/tools/check_dependencies.rb +1 -1
- metadata +40 -15
- data/lib/canopus/git/blame.rb +0 -50
- data/lib/canopus/git/commit.rb +0 -7
- data/lib/canopus/git/corrupt_object.rb +0 -7
- data/lib/canopus/git/diff.rb +0 -131
- data/lib/canopus/git/index.rb +0 -94
- data/lib/canopus/git/object_database.rb +0 -45
- data/lib/canopus/git/pack.rb +0 -186
- data/lib/canopus/git/repository.rb +0 -313
- data/lib/canopus/git/status.rb +0 -74
- data/lib/canopus/git/tree_entry.rb +0 -7
- data/lib/canopus/git.rb +0 -15
- data/sig/git.rbs +0 -140
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8f145122cb1995d72f9ddcf886fc40d2d00c60351b6d7a227ce69011c2ca7f61
|
|
4
|
+
data.tar.gz: 52b865cfbbda7a3e991748305282db47ce0f7f7903e50c763142defab18a0b7e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 50e3e24430e992f3961e2838444ce5f8c6ab8337c75ebc504f863554f219736212b46a140d89208f223c6316a8d754860de598b70e69881bf65601196cdcbd55
|
|
7
|
+
data.tar.gz: 7ac119f37e6947ccebae40e63d6eb54bb243bc9ff149049ad02e623c4f3d210da45999ec2a3ee520c30cb87a924c8c0189a30e3333a9c39cd2e35ef14031d9bb
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0 — 2026-09-12
|
|
4
|
+
|
|
5
|
+
- Read repositories through Thuban and keep text comparison in Porrima data objects.
|
|
6
|
+
- Use Porrima marks and indexed hunk lookup for Git gutter interactions.
|
|
7
|
+
- Delegate text diff calculation to Porrima without changing Git behavior.
|
|
8
|
+
- Add closable editor tabs and multiple terminal tabs with session persistence.
|
|
9
|
+
- Prevent duplicate `strscan` initialization in syntax workers.
|
|
10
|
+
- Avoid cross-test method replacement in background layout error coverage.
|
|
11
|
+
|
|
3
12
|
## 0.1.0 — 2026-09-11
|
|
4
13
|
|
|
5
14
|
- Initial release.
|
data/README.md
CHANGED
|
@@ -1,42 +1,80 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/logo.png" alt="Canopus logo">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<strong>Ruby-native code editor with GPU windows, language-server tools, a terminal, Git integration, and Vim bindings</strong>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://rubygems.org/gems/canopus"><img src="https://img.shields.io/gem/v/canopus.svg" alt="Gem version"></a>
|
|
11
|
+
<a href="https://rubygems.org/gems/canopus"><img src="https://img.shields.io/gem/dt/canopus.svg" alt="Gem downloads"></a>
|
|
12
|
+
<a href="https://github.com/noxdea/canopus/actions/workflows/main.yml"><img src="https://github.com/noxdea/canopus/actions/workflows/main.yml/badge.svg" alt="CI"></a>
|
|
13
|
+
<img src="https://img.shields.io/badge/CRuby-%3E%3D%203.1-cc342d.svg" alt="CRuby 3.1 or newer">
|
|
14
|
+
<a href="LICENSE.txt"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT license"></a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<a href="#features">Features</a> ·
|
|
19
|
+
<a href="#installation">Installation</a> ·
|
|
20
|
+
<a href="#quick-start">Quick start</a> ·
|
|
21
|
+
<a href="#configuration">Configuration</a> ·
|
|
22
|
+
<a href="#development">Development</a>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
Canopus is a code editor implemented in Ruby. It combines persistent UTF-8
|
|
28
|
+
buffers with native rendering through [Zaniah](https://github.com/noxdea/zaniah),
|
|
29
|
+
while keeping language servers, shells, and other external tools independently
|
|
30
|
+
installable.
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- Native GPU windows on macOS, Linux, and Windows, plus TUI and headless modes
|
|
35
|
+
- Persistent buffers, tabs, splits, sessions, and explicit save-conflict handling
|
|
36
|
+
- LSP completion, diagnostics, hover, symbols, formatting, rename, and code actions
|
|
37
|
+
- Resizable integrated terminal with multiple tabs, scrollback, selection, colors, and clickable links
|
|
38
|
+
- Git diff, blame, hunk reversal, and branch switching
|
|
39
|
+
- Editable project-wide search results and safe project file operations
|
|
40
|
+
- Optional Vim-compatible modes, motions, operators, registers, macros, and Ex commands
|
|
41
|
+
- Layered JSONC settings, keymaps, themes, snippets, and trusted Ruby plugins
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
Install the released gem:
|
|
2
46
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
47
|
+
```sh
|
|
48
|
+
gem install canopus
|
|
49
|
+
canopus --version
|
|
50
|
+
```
|
|
6
51
|
|
|
7
|
-
|
|
8
|
-
and
|
|
9
|
-
|
|
10
|
-
servers and the terminal shell are user-installed programs. Ruby libraries are
|
|
11
|
-
installed as gem dependencies; Prism is bundled with recent Ruby releases.
|
|
52
|
+
Canopus requires CRuby 3.1 or newer. The launcher enables YJIT when supported
|
|
53
|
+
and otherwise uses the interpreter. Native windows also require the `fiddle`
|
|
54
|
+
standard-library component; some Ruby distributions package it separately.
|
|
12
55
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
configuration includes it; headless rendering does not load it.
|
|
56
|
+
macOS uses Metal. Linux requires Wayland/EGL/OpenGL or X11/GLX, XKB, and
|
|
57
|
+
`zenity` for file dialogs. Windows uses WGL. See [Packaging](docs/distribution.md)
|
|
58
|
+
for source-based desktop bundles and platform details.
|
|
17
59
|
|
|
18
|
-
##
|
|
60
|
+
## Quick start
|
|
61
|
+
|
|
62
|
+
Open the current project:
|
|
19
63
|
|
|
20
64
|
```sh
|
|
21
|
-
|
|
22
|
-
bundle exec ruby exe/canopus --project . README.md
|
|
23
|
-
ruby exe/canopus --headless /tmp/canopus.png README.md
|
|
24
|
-
ruby exe/canopus --tui README.md
|
|
65
|
+
canopus --project .
|
|
25
66
|
```
|
|
26
67
|
|
|
27
|
-
|
|
28
|
-
macOS uses Metal, Linux uses Wayland/EGL or X11/GLX, and Windows uses WGL.
|
|
29
|
-
|
|
30
|
-
Install a local artifact with:
|
|
68
|
+
Open files directly, use the terminal interface, or render a headless frame:
|
|
31
69
|
|
|
32
70
|
```sh
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
canopus --
|
|
71
|
+
canopus README.md lib/canopus.rb
|
|
72
|
+
canopus --tui --project .
|
|
73
|
+
canopus --headless /tmp/canopus.png README.md
|
|
36
74
|
```
|
|
37
75
|
|
|
38
|
-
|
|
39
|
-
|
|
76
|
+
Run `canopus --help` for session, settings, replay, backend, profiling, and
|
|
77
|
+
plugin options.
|
|
40
78
|
|
|
41
79
|
## Everyday controls
|
|
42
80
|
|
|
@@ -49,43 +87,29 @@ requirements.
|
|
|
49
87
|
| All occurrences / move lines | Cmd-Shift-L / Alt-Up or Down | Ctrl-Shift-L / Alt-Up or Down |
|
|
50
88
|
| Completion / definition | Ctrl-Space / F12 | Ctrl-Space / F12 |
|
|
51
89
|
| Split / terminal | Cmd-Backslash / Ctrl-Backtick | Ctrl-Backslash / Ctrl-Backtick |
|
|
90
|
+
| Close / reopen tab | Cmd-W / Cmd-Shift-T | Ctrl-W / Ctrl-Shift-T |
|
|
91
|
+
| New terminal tab | Ctrl-Shift-Backtick | Ctrl-Shift-Backtick |
|
|
92
|
+
| Next / previous terminal | Ctrl-Shift-] / Ctrl-Shift-[ | Ctrl-Shift-] / Ctrl-Shift-[ |
|
|
52
93
|
|
|
53
|
-
The palette exposes Git
|
|
54
|
-
|
|
55
|
-
to
|
|
56
|
-
Project deletion moves files into `.canopus/trash`. Dirty documents and disk
|
|
57
|
-
save conflicts are preserved for an explicit decision.
|
|
94
|
+
The command palette also exposes Git operations, language actions, project file
|
|
95
|
+
operations, settings, themes, docks, and Vim mode. Project deletion moves files
|
|
96
|
+
to `.canopus/trash` instead of deleting them immediately.
|
|
58
97
|
|
|
59
|
-
|
|
60
|
-
Completion supports additional edits and [snippets](docs/snippets.md), including
|
|
61
|
-
mirrors, transforms, choices, and Tab / Shift-Tab navigation. Hover cards render
|
|
62
|
-
bounded Markdown; only explicitly clicked HTTP(S) links open externally.
|
|
63
|
-
Notifications are dismissible and expire automatically.
|
|
98
|
+
## Configuration
|
|
64
99
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
Search palettes use Ctrl-Alt-R for regular expressions, Ctrl-Alt-C for case sensitivity,
|
|
69
|
-
Ctrl-Alt-W for whole words and Ctrl-Alt-S for the selection captured when search opened.
|
|
70
|
-
Replacements support Ruby backreferences, and stale selections are rejected.
|
|
71
|
-
Resource-changing LSP actions show the affected paths before confirmation;
|
|
72
|
-
PageUp / PageDown scroll the list. See [workspace edits](docs/workspace_edits.md).
|
|
73
|
-
|
|
74
|
-
## Settings and extensions
|
|
75
|
-
|
|
76
|
-
`settings.open` opens `.canopus/settings.jsonc`. User settings live at
|
|
77
|
-
`$XDG_CONFIG_HOME/canopus/settings.jsonc` or
|
|
78
|
-
`~/.config/canopus/settings.jsonc`. Layers are defaults, user, project, explicit
|
|
79
|
-
`--settings`, then language overrides. Saved changes reload; invalid values
|
|
80
|
-
preserve the previous valid settings. Ctrl-Space completes setting names.
|
|
100
|
+
Run `settings.open` from the command palette to edit project settings. User
|
|
101
|
+
settings live at `$XDG_CONFIG_HOME/canopus/settings.jsonc` or
|
|
102
|
+
`~/.config/canopus/settings.jsonc`.
|
|
81
103
|
|
|
82
104
|
```jsonc
|
|
83
105
|
{
|
|
84
106
|
"theme": "auto",
|
|
85
107
|
"font_size": 14,
|
|
86
|
-
"icon_theme": null,
|
|
87
108
|
"vim_mode": false,
|
|
88
109
|
"use_tabs": false,
|
|
110
|
+
"tabs": { "activate_on_close": "history", "reopen_history_limit": 20 },
|
|
111
|
+
"terminal": { "working_directory": "project", "scrollback_lines": 10000 },
|
|
112
|
+
"dock": { "bottom": { "size": 280, "visible": false } },
|
|
89
113
|
"keymap": [
|
|
90
114
|
{ "context": "Editor && !vim_mode", "bindings": { "ctrl-k ctrl-s": "file.save" } }
|
|
91
115
|
],
|
|
@@ -94,55 +118,63 @@ preserve the previous valid settings. Ctrl-Space completes setting names.
|
|
|
94
118
|
}
|
|
95
119
|
```
|
|
96
120
|
|
|
97
|
-
|
|
98
|
-
|
|
121
|
+
Closing a dirty tab asks whether to save, discard, or cancel. Reopening restores
|
|
122
|
+
the file, selections, position, and pane while Canopus is running; discarded
|
|
123
|
+
unsaved changes are never restored. Terminal session restoration, when enabled,
|
|
124
|
+
starts fresh shells with the saved tab count and working directories and does
|
|
125
|
+
not restore processes or scrollback.
|
|
99
126
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Saved keymaps reload atomically, including palette labels; invalid expressions
|
|
105
|
-
leave the previous settings intact. Limits are 128 groups and 1,024 bindings.
|
|
127
|
+
Settings are layered from defaults through user, project, explicit `--settings`,
|
|
128
|
+
and language overrides. Invalid saved settings leave the previous valid values
|
|
129
|
+
active. Keymap groups extend defaults; later matching bindings win, and `null`
|
|
130
|
+
removes a default binding.
|
|
106
131
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
SVG subset is drawn; scripts, external references and entities are not executed.
|
|
132
|
+
Language servers are separate programs and are auto-detected or configured by
|
|
133
|
+
argument array. See [Language servers](docs/lsp.md) for configuration and
|
|
134
|
+
restart behavior.
|
|
111
135
|
|
|
112
|
-
Plugins require explicit trust:
|
|
136
|
+
Plugins require explicit trust and permissions:
|
|
113
137
|
|
|
114
138
|
```sh
|
|
115
|
-
|
|
139
|
+
canopus --plugin examples/plugins/word_count.rb \
|
|
116
140
|
--trust-plugins --grant read_buffer
|
|
117
141
|
```
|
|
118
142
|
|
|
119
|
-
The default separate process contains crashes and timeouts
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
access. `--plugins-in-process` opts into direct execution.
|
|
143
|
+
The default separate process contains plugin crashes and timeouts, but it is not
|
|
144
|
+
an OS sandbox. Trusted Ruby code retains the invoking user's filesystem and
|
|
145
|
+
network privileges.
|
|
123
146
|
|
|
124
|
-
##
|
|
147
|
+
## Documentation
|
|
148
|
+
|
|
149
|
+
- [Language servers](docs/lsp.md)
|
|
150
|
+
- [Vim mode](docs/vim.md)
|
|
151
|
+
- [Snippets](docs/snippets.md)
|
|
152
|
+
- [Workspace edits](docs/workspace_edits.md)
|
|
153
|
+
- [Packaging](docs/distribution.md)
|
|
154
|
+
- [Profiling and local crash reports](docs/performance.md)
|
|
155
|
+
- [Architecture decisions](docs/adr)
|
|
156
|
+
|
|
157
|
+
## Development
|
|
125
158
|
|
|
126
159
|
```sh
|
|
160
|
+
git clone https://github.com/noxdea/canopus.git
|
|
161
|
+
cd canopus
|
|
162
|
+
bundle install
|
|
127
163
|
bundle exec rake test
|
|
128
|
-
bundle exec
|
|
164
|
+
bundle exec rbs -I sig -r porrima -r thuban -r alhena -r antares -r denebola -r zaniah -r stringio -r strscan validate
|
|
129
165
|
bundle exec ruby tools/check_dependencies.rb test/type/smoke.rb
|
|
130
|
-
bundle exec rbs -I sig -r alhena -r antares -r denebola -r zaniah -r stringio -r strscan validate
|
|
131
166
|
```
|
|
132
167
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
unicode-emoji supply terminal-cell tables. They are installed from RubyGems.
|
|
168
|
+
Run `bundle exec rake bench` for performance checks. Contributions can be
|
|
169
|
+
submitted through [GitHub issues and pull requests](https://github.com/noxdea/canopus/issues).
|
|
136
170
|
|
|
137
|
-
|
|
138
|
-
folding. Large-file UTF-16/legacy encodings are not supported there. Rouge
|
|
139
|
-
lexers that cannot resume exactly use a documented bounded-window fallback,
|
|
140
|
-
which can approximate long-distance syntax state. Git supports SHA-1 repositories,
|
|
141
|
-
not every Git index/object extension. See the [architecture decisions](docs/adr).
|
|
171
|
+
## Limits
|
|
142
172
|
|
|
143
|
-
|
|
144
|
-
|
|
173
|
+
- Files larger than 100 MiB use a read-only UTF-8 path without wrapping or folding.
|
|
174
|
+
- Large-file UTF-16 and legacy encodings are unsupported.
|
|
175
|
+
- Git support targets SHA-1 repositories and does not implement every index or object extension.
|
|
176
|
+
- Desktop packages are unsigned and do not bundle Ruby or automatic updates.
|
|
145
177
|
|
|
146
178
|
## License
|
|
147
179
|
|
|
148
|
-
|
|
180
|
+
Canopus is released under the [MIT License](LICENSE.txt).
|
|
Binary file
|
data/assets/logo.png
ADDED
|
Binary file
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# ADR NNN: Implementation decision title
|
|
2
|
+
|
|
3
|
+
- Status: Proposed
|
|
4
|
+
- Date: YYYY-MM-DD
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
Describe the concrete implementation question and its compatibility, data,
|
|
9
|
+
runtime, or component constraints. Operational workflow and release policy do
|
|
10
|
+
not belong in this directory; see [the scope](README.md).
|
|
11
|
+
|
|
12
|
+
Name the credible alternatives. If there was no meaningful alternative, record
|
|
13
|
+
the behavior in reference documentation instead of creating an ADR.
|
|
14
|
+
|
|
15
|
+
## Decision
|
|
16
|
+
|
|
17
|
+
Describe the durable boundary or architecture choice. Leave command syntax,
|
|
18
|
+
field-by-field formats, test evidence, benchmark results, and migration steps
|
|
19
|
+
in their authoritative documents.
|
|
20
|
+
|
|
21
|
+
## Consequences
|
|
22
|
+
|
|
23
|
+
Describe the important positive and negative trade-offs, including what would
|
|
24
|
+
make this decision worth revisiting.
|
|
@@ -16,7 +16,7 @@ switching algorithms by input size.
|
|
|
16
16
|
|
|
17
17
|
## Consequences
|
|
18
18
|
|
|
19
|
-
Memory behavior and tie-breaking remain consistent across file sizes
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
Memory behavior and tie-breaking remain consistent across file sizes. Porrima
|
|
20
|
+
owns the implementation and its performance limits while Canopus retains
|
|
21
|
+
display and scheduling policy. Revisit this decision if Porrima no longer
|
|
22
|
+
provides the same bounds and stable results.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# ADR 006: Release buffers after their last live view
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-09-11
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
A buffer can be shown by editors in several panes and by a project-search
|
|
9
|
+
`MultiBuffer`. Closing one tab must dispose its editor subscriptions without
|
|
10
|
+
closing language-server documents or persistent ropes still used elsewhere.
|
|
11
|
+
The alternatives were an independent reference-counting store or deriving
|
|
12
|
+
owners from the workspace's existing editor and excerpt collections.
|
|
13
|
+
|
|
14
|
+
## Decision
|
|
15
|
+
|
|
16
|
+
Dispose the editor immediately, then derive the remaining owners from panes and
|
|
17
|
+
`MultiBuffer` excerpts in the same close operation. Release the buffer and its
|
|
18
|
+
language-server document only when no owner remains. Keep closed-tab navigation
|
|
19
|
+
state in a bounded, process-local stack; never retain discarded buffer content.
|
|
20
|
+
|
|
21
|
+
## Consequences
|
|
22
|
+
|
|
23
|
+
Ownership has one source of truth and cannot drift through unmatched increment
|
|
24
|
+
or decrement calls. The scan is linear in open views; revisit with explicit
|
|
25
|
+
owner IDs only if measured close latency becomes material.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# ADR 007: Route terminal keys with an explicit editor allowlist
|
|
2
|
+
|
|
3
|
+
- Status: Accepted
|
|
4
|
+
- Date: 2026-09-11
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
Terminal applications need control and escape sequences that overlap editor
|
|
9
|
+
bindings. Dispatching editor shortcuts first breaks shells, while sending every
|
|
10
|
+
key to the PTY makes terminal tab management and application commands
|
|
11
|
+
unreachable.
|
|
12
|
+
|
|
13
|
+
## Decision
|
|
14
|
+
|
|
15
|
+
When the terminal owns focus, dispatch only bindings whose context matches
|
|
16
|
+
`Terminal`; send every unmatched key to the active PTY. Default terminal
|
|
17
|
+
bindings cover panel and tab management, copy, paste, and the command palette.
|
|
18
|
+
User keymap groups remain later bindings and can override those defaults.
|
|
19
|
+
|
|
20
|
+
## Consequences
|
|
21
|
+
|
|
22
|
+
Shell keys pass through by default and `Cmd-W`/`Ctrl-W` close the focused
|
|
23
|
+
terminal instead of an editor tab. New global shortcuts must be added to the
|
|
24
|
+
terminal context only when interception is intentional.
|