canopus 0.1.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 +7 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +148 -0
- data/docs/adr/001-runtime-gem-components.md +24 -0
- data/docs/adr/002-bounded-diff-engine.md +22 -0
- data/docs/adr/003-background-language-analysis.md +22 -0
- data/docs/adr/004-persistent-display-map.md +23 -0
- data/docs/adr/005-windows-runtime.md +27 -0
- data/docs/adr/README.md +36 -0
- data/docs/distribution.md +27 -0
- data/docs/lsp.md +38 -0
- data/docs/performance.md +40 -0
- data/docs/snippets.md +32 -0
- data/docs/vim.md +24 -0
- data/docs/workspace_edits.md +32 -0
- data/examples/native_smoke.rb +25 -0
- data/examples/plugins/word_count.rb +11 -0
- data/exe/canopus +19 -0
- data/lib/canopus/block_map.rb +19 -0
- data/lib/canopus/buffer.rb +293 -0
- data/lib/canopus/cli.rb +171 -0
- data/lib/canopus/controller.rb +507 -0
- data/lib/canopus/data_compat.rb +25 -0
- data/lib/canopus/display_map/line_builder.rb +54 -0
- data/lib/canopus/display_map/line_set.rb +8 -0
- data/lib/canopus/display_map/pending_line_set.rb +9 -0
- data/lib/canopus/display_map/summary.rb +23 -0
- data/lib/canopus/display_map/worker.rb +89 -0
- data/lib/canopus/display_map.rb +350 -0
- data/lib/canopus/display_point.rb +5 -0
- data/lib/canopus/editor/snippet_expandable.rb +281 -0
- data/lib/canopus/editor.rb +445 -0
- data/lib/canopus/error.rb +5 -0
- data/lib/canopus/fold_map.rb +87 -0
- data/lib/canopus/git/blame.rb +50 -0
- data/lib/canopus/git/commit.rb +7 -0
- data/lib/canopus/git/corrupt_object.rb +7 -0
- data/lib/canopus/git/diff.rb +131 -0
- data/lib/canopus/git/index.rb +94 -0
- data/lib/canopus/git/object_database.rb +45 -0
- data/lib/canopus/git/pack.rb +186 -0
- data/lib/canopus/git/repository.rb +313 -0
- data/lib/canopus/git/status.rb +74 -0
- data/lib/canopus/git/tree_entry.rb +7 -0
- data/lib/canopus/git.rb +15 -0
- data/lib/canopus/icon_theme.rb +43 -0
- data/lib/canopus/language/background_analysis/job.rb +12 -0
- data/lib/canopus/language/background_analysis/scheduler.rb +70 -0
- data/lib/canopus/language/background_analysis.rb +280 -0
- data/lib/canopus/language/definition.rb +7 -0
- data/lib/canopus/language/document.rb +143 -0
- data/lib/canopus/language/symbol.rb +7 -0
- data/lib/canopus/language/syntax_worker.rb +91 -0
- data/lib/canopus/language.rb +42 -0
- data/lib/canopus/lazy_rope.rb +218 -0
- data/lib/canopus/lsp/client.rb +299 -0
- data/lib/canopus/lsp/error.rb +7 -0
- data/lib/canopus/lsp/future/subscription.rb +9 -0
- data/lib/canopus/lsp/future.rb +87 -0
- data/lib/canopus/lsp/protocol.rb +83 -0
- data/lib/canopus/lsp/server_error.rb +13 -0
- data/lib/canopus/lsp/timeout.rb +7 -0
- data/lib/canopus/lsp/transport.rb +123 -0
- data/lib/canopus/lsp.rb +19 -0
- data/lib/canopus/markdown.rb +69 -0
- data/lib/canopus/match_data_compat.rb +17 -0
- data/lib/canopus/multi_buffer.rb +266 -0
- data/lib/canopus/pane.rb +61 -0
- data/lib/canopus/patch/composite.rb +12 -0
- data/lib/canopus/patch/reload.rb +18 -0
- data/lib/canopus/patch.rb +27 -0
- data/lib/canopus/performance_recorder.rb +207 -0
- data/lib/canopus/plugins/api.rb +50 -0
- data/lib/canopus/plugins/isolated_runtime.rb +167 -0
- data/lib/canopus/plugins/local_runtime.rb +25 -0
- data/lib/canopus/plugins/permission_denied.rb +7 -0
- data/lib/canopus/plugins/registry.rb +30 -0
- data/lib/canopus/plugins.rb +11 -0
- data/lib/canopus/project/ignore_matcher.rb +104 -0
- data/lib/canopus/project/search.rb +164 -0
- data/lib/canopus/project/search_worker/cancelled.rb +3 -0
- data/lib/canopus/project/search_worker/runner.rb +9 -0
- data/lib/canopus/project/search_worker.rb +108 -0
- data/lib/canopus/project/tree.rb +48 -0
- data/lib/canopus/project/watcher.rb +59 -0
- data/lib/canopus/project.rb +127 -0
- data/lib/canopus/regexp_compat.rb +30 -0
- data/lib/canopus/save_conflict.rb +5 -0
- data/lib/canopus/selection.rb +11 -0
- data/lib/canopus/settings.rb +118 -0
- data/lib/canopus/snippet/transform.rb +209 -0
- data/lib/canopus/snippet.rb +183 -0
- data/lib/canopus/tab_map.rb +30 -0
- data/lib/canopus/terminal/cell.rb +7 -0
- data/lib/canopus/terminal/grid.rb +321 -0
- data/lib/canopus/terminal/pty.rb +103 -0
- data/lib/canopus/terminal/scrollback.rb +38 -0
- data/lib/canopus/terminal/vt.rb +398 -0
- data/lib/canopus/terminal.rb +13 -0
- data/lib/canopus/theme.rb +43 -0
- data/lib/canopus/version.rb +5 -0
- data/lib/canopus/vim/commandable.rb +148 -0
- data/lib/canopus/vim/motionable.rb +321 -0
- data/lib/canopus/vim/operator_capable.rb +377 -0
- data/lib/canopus/vim/text_object_selectable.rb +141 -0
- data/lib/canopus/vim.rb +426 -0
- data/lib/canopus/workspace/edit/executable.rb +139 -0
- data/lib/canopus/workspace/edit/node.rb +8 -0
- data/lib/canopus/workspace/edit/plan.rb +170 -0
- data/lib/canopus/workspace/edit/resource_preparable.rb +98 -0
- data/lib/canopus/workspace/edit.rb +6 -0
- data/lib/canopus/workspace/file_change_aware.rb +40 -0
- data/lib/canopus/workspace/file_previewable.rb +31 -0
- data/lib/canopus/workspace/git_aware.rb +140 -0
- data/lib/canopus/workspace/language_aware.rb +413 -0
- data/lib/canopus/workspace/language_server_configurable.rb +181 -0
- data/lib/canopus/workspace/project_searchable.rb +208 -0
- data/lib/canopus/workspace/project_tree_editable.rb +82 -0
- data/lib/canopus/workspace/session_persistable.rb +153 -0
- data/lib/canopus/workspace/settings_aware.rb +91 -0
- data/lib/canopus/workspace/view/terminal_presentable.rb +185 -0
- data/lib/canopus/workspace/view.rb +643 -0
- data/lib/canopus/workspace.rb +525 -0
- data/lib/canopus/wrap_map.rb +108 -0
- data/lib/canopus.rb +24 -0
- data/sig/canopus.rbs +375 -0
- data/sig/controller.rbs +55 -0
- data/sig/display_stages.rbs +49 -0
- data/sig/git.rbs +140 -0
- data/sig/lsp.rbs +99 -0
- data/sig/markdown.rbs +11 -0
- data/sig/performance_recorder.rbs +23 -0
- data/sig/search_services.rbs +8 -0
- data/sig/services.rbs +81 -0
- data/sig/snippet.rbs +42 -0
- data/sig/terminal.rbs +125 -0
- data/sig/vim.rbs +27 -0
- data/sig/workspace_edits.rbs +11 -0
- data/sig/workspace_services.rbs +117 -0
- data/tools/certify_snippet_regex.rb +35 -0
- data/tools/check_dependencies.rb +80 -0
- data/tools/native_check.rb +70 -0
- data/tools/package.rb +113 -0
- data/tools/package_test.rb +32 -0
- metadata +314 -0
data/sig/lsp.rbs
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
module Canopus
|
|
2
|
+
module LSP
|
|
3
|
+
type json = nil | bool | Integer | Float | String | Array[json] | Hash[String | Symbol, json]
|
|
4
|
+
type object = Hash[String | Symbol, json]
|
|
5
|
+
type semantic_token = { line: Integer, character: Integer, length: Integer, type: Integer, modifiers: Integer }
|
|
6
|
+
|
|
7
|
+
class Error < StandardError
|
|
8
|
+
end
|
|
9
|
+
class Timeout < Error
|
|
10
|
+
end
|
|
11
|
+
class ServerError < Error
|
|
12
|
+
attr_reader code: Integer
|
|
13
|
+
attr_reader data: json
|
|
14
|
+
def initialize: (Hash[String, json] error) -> void
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
module Protocol
|
|
18
|
+
def self.uri: (String path) -> String
|
|
19
|
+
def self.path: (String uri) -> String
|
|
20
|
+
def self.position: (Denebola::Rope rope, Integer offset) -> { line: Integer, character: Integer }
|
|
21
|
+
def self.offset: (Denebola::Rope rope, Hash[String, Integer] position) -> Integer
|
|
22
|
+
def self.range: (Denebola::Rope rope, Range[Integer] range) -> object
|
|
23
|
+
def self.uint?: (untyped value) -> bool
|
|
24
|
+
def self.diagnostics: (Array[object] values) -> Array[object]
|
|
25
|
+
def self.semantic_delta: (Array[Integer] data, Array[Hash[String, json]] edits) -> Array[Integer]
|
|
26
|
+
def self.semantic_tokens: (Array[Integer] data, ?legend: Hash[String, Array[String]]?) -> Array[semantic_token]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
class Future
|
|
30
|
+
class Subscription
|
|
31
|
+
def initialize: () { () -> untyped } -> void
|
|
32
|
+
def detach: () -> untyped
|
|
33
|
+
end
|
|
34
|
+
attr_reader id: Integer | String | nil
|
|
35
|
+
attr_reader callback_errors: Array[Error]
|
|
36
|
+
def initialize: (Integer | String | nil id, ?on_error: ^(Error) -> untyped) ?{ (Integer | String | nil) -> untyped } -> void
|
|
37
|
+
def fulfill: (?untyped value, ?error: Exception?) -> Future?
|
|
38
|
+
def then: () { (untyped, Exception?) -> untyped } -> Future
|
|
39
|
+
def done?: () -> bool
|
|
40
|
+
def on_complete: () { () -> untyped } -> Subscription
|
|
41
|
+
def await: (?timeout: Numeric?) -> untyped
|
|
42
|
+
def cancel: () -> bool
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class Transport
|
|
46
|
+
MAX_MESSAGE: Integer
|
|
47
|
+
attr_reader stderr_lines: Array[String]
|
|
48
|
+
attr_reader pid: Integer
|
|
49
|
+
def initialize: (Array[String] command, ?cwd: String?, ?env: Hash[String, String?]) { (Hash[String, json]?, Exception?) -> untyped } -> void
|
|
50
|
+
def self.read_message: (IO | StringIO io) -> Hash[String, json]?
|
|
51
|
+
def self.validate_message: (untyped message) -> Hash[String, json]
|
|
52
|
+
def write: (object message) -> untyped
|
|
53
|
+
def alive?: () -> bool
|
|
54
|
+
def close: () -> untyped
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
class Client
|
|
58
|
+
attr_reader capabilities: Hash[String, json]
|
|
59
|
+
attr_reader transport: Transport?
|
|
60
|
+
attr_reader diagnostics: Hash[String, Array[object]]
|
|
61
|
+
attr_reader state: :stopped | :starting | :running | :failed
|
|
62
|
+
attr_reader errors: Array[Error]
|
|
63
|
+
attr_reader server_info: Hash[String, json]?
|
|
64
|
+
attr_reader position_encoding: String?
|
|
65
|
+
def initialize: (command: Array[String], ?root: String, ?dispatch: ^() { () -> untyped } -> untyped, ?restart: bool, ?env: Hash[String, String?], ?initialization_options: json, ?configuration: object) -> void
|
|
66
|
+
def start: (?timeout: Numeric) -> self
|
|
67
|
+
def stop: () -> untyped
|
|
68
|
+
def request: (String | Symbol method, ?json params) -> Future
|
|
69
|
+
def notify: (String | Symbol method, ?json params) -> untyped
|
|
70
|
+
def on: (String | Symbol method) { (untyped) -> untyped } -> Proc
|
|
71
|
+
def supports?: (String | Symbol capability) -> bool
|
|
72
|
+
def workspace_symbols: (String query) -> Future
|
|
73
|
+
def resolve_completion: (object item) -> Future
|
|
74
|
+
def resolve_code_action: (object action) -> Future
|
|
75
|
+
def resolve_code_lens: (object lens) -> Future
|
|
76
|
+
def execute_command: (String command, ?arguments: Array[json]) -> Future
|
|
77
|
+
def open_document: (Buffer buffer, language_id: String) -> String
|
|
78
|
+
def close_document: (String uri) -> untyped
|
|
79
|
+
def save_document: (String uri) -> untyped
|
|
80
|
+
def at: (String method, Buffer buffer, Integer offset, **json params) -> Future
|
|
81
|
+
def completion: (Buffer buffer, Integer offset, **json params) -> Future
|
|
82
|
+
def hover: (Buffer buffer, Integer offset, **json params) -> Future
|
|
83
|
+
def definition: (Buffer buffer, Integer offset, **json params) -> Future
|
|
84
|
+
def typeDefinition: (Buffer buffer, Integer offset, **json params) -> Future
|
|
85
|
+
def implementation: (Buffer buffer, Integer offset, **json params) -> Future
|
|
86
|
+
def references: (Buffer buffer, Integer offset, **json params) -> Future
|
|
87
|
+
def rename: (Buffer buffer, Integer offset, **json params) -> Future
|
|
88
|
+
def signatureHelp: (Buffer buffer, Integer offset, **json params) -> Future
|
|
89
|
+
def documentSymbol: (Buffer buffer, **json params) -> Future
|
|
90
|
+
def formatting: (Buffer buffer, **json params) -> Future
|
|
91
|
+
def codeAction: (Buffer buffer, **json params) -> Future
|
|
92
|
+
def inlayHint: (Buffer buffer, **json params) -> Future
|
|
93
|
+
def codeLens: (Buffer buffer, **json params) -> Future
|
|
94
|
+
def diagnostic: (Buffer buffer, **json params) -> Future
|
|
95
|
+
def semantic_tokens: (Buffer buffer) -> Array[semantic_token]
|
|
96
|
+
def apply_text_edits: (Buffer buffer, Array[object] edits) -> untyped
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
data/sig/markdown.rbs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Canopus
|
|
2
|
+
class Markdown
|
|
3
|
+
class Run < Data
|
|
4
|
+
attr_reader text: String
|
|
5
|
+
attr_reader style: Symbol | String
|
|
6
|
+
attr_reader url: String?
|
|
7
|
+
end
|
|
8
|
+
def initialize: (String source, ?width: Integer, ?max_rows: Integer, ?markup: bool) -> void
|
|
9
|
+
attr_reader rows: Array[Array[Run]]
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Canopus
|
|
2
|
+
class PerformanceRecorder
|
|
3
|
+
type statistics = {
|
|
4
|
+
frames: Integer, retained_frames: Integer, last_frame_ms: Float?,
|
|
5
|
+
last_allocations: Integer?, last_draw_calls: Integer?, median_frame_ms: Numeric,
|
|
6
|
+
p95_frame_ms: Numeric, max_frame_ms: Numeric, mean_allocations: Numeric,
|
|
7
|
+
sampling_samples: Integer
|
|
8
|
+
}
|
|
9
|
+
def initialize: (Zaniah::Platform::Headless::Window window, ?trace_allocations: bool, ?sampling: bool,
|
|
10
|
+
?capacity: Integer, ?sample_capacity: Integer, ?interval: Numeric) -> void
|
|
11
|
+
attr_reader sampler: Thread?
|
|
12
|
+
def start: () -> self
|
|
13
|
+
def stop: () -> self
|
|
14
|
+
def measure: [A] () { () -> A } -> A
|
|
15
|
+
def statistics: () -> statistics
|
|
16
|
+
def report: () -> Hash[Symbol, untyped]
|
|
17
|
+
def write: (String path) -> String
|
|
18
|
+
def self.context: (?Zaniah::Platform::Headless::Window? window) -> Hash[Symbol, untyped]
|
|
19
|
+
def self.validate_paths: (Array[String?] paths, ?protected: Array[String?]) -> Array[String]
|
|
20
|
+
def self.write_json: (String path, untyped report) -> String
|
|
21
|
+
def self.write_crash: (String path, Exception exception, ?window: Zaniah::Platform::Headless::Window?) -> String
|
|
22
|
+
end
|
|
23
|
+
end
|
data/sig/services.rbs
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module Canopus
|
|
2
|
+
class Project
|
|
3
|
+
interface _NativeWatcher
|
|
4
|
+
def poll: (?timeout: Numeric) -> Array[untyped]
|
|
5
|
+
def close: () -> void
|
|
6
|
+
end
|
|
7
|
+
attr_reader root: String
|
|
8
|
+
def initialize: (String root) -> void
|
|
9
|
+
def path: (String relative) -> String
|
|
10
|
+
def files: (?include_hidden: bool, ?follow_symlinks: bool, ?include_symlinks: bool, ?include_directories: bool, ?extensions: Array[String]?, ?max_size: Integer?) -> Enumerator[String, self]
|
|
11
|
+
| (?include_hidden: bool, ?follow_symlinks: bool, ?include_symlinks: bool, ?include_directories: bool, ?extensions: Array[String]?, ?max_size: Integer?) { (String) -> void } -> self
|
|
12
|
+
def ignored?: (String relative, ?directory: bool) -> bool
|
|
13
|
+
def search: (String | Regexp pattern, ?workers: Integer, ?max_size: Integer?, ?extensions: Array[String]?, ?limit: Integer?, ?case_sensitive: bool, ?cancelled: ^() -> bool, ?paths: Array[String]?) ?{ (Search::Match) -> void } -> Array[Search::Match]
|
|
14
|
+
def replace: (String | Regexp pattern, String replacement, ?workers: Integer, ?max_size: Integer?, ?extensions: Array[String]?, ?limit: Integer?, ?case_sensitive: bool, ?cancelled: ^() -> bool, ?paths: Array[String]?) -> Hash[String, Integer]
|
|
15
|
+
def watcher: (?interval: Numeric, ?native: _NativeWatcher?) -> Watcher
|
|
16
|
+
|
|
17
|
+
class Search
|
|
18
|
+
DEFAULT_MAX_SIZE: Integer
|
|
19
|
+
class Match < Struct[untyped]
|
|
20
|
+
attr_accessor path: String
|
|
21
|
+
attr_accessor line: Integer
|
|
22
|
+
attr_accessor column: Integer
|
|
23
|
+
attr_accessor byte_offset: Integer
|
|
24
|
+
attr_accessor text: String
|
|
25
|
+
attr_accessor match: String
|
|
26
|
+
def self.new: (path: String, line: Integer, column: Integer, byte_offset: Integer, text: String, match: String) -> instance
|
|
27
|
+
end
|
|
28
|
+
def initialize: (Project project) -> void
|
|
29
|
+
def call: (String | Regexp pattern, ?workers: Integer, ?max_size: Integer?, ?extensions: Array[String]?, ?limit: Integer?, ?case_sensitive: bool, ?cancelled: ^() -> bool, ?paths: Array[String]?) ?{ (Match) -> void } -> Array[Match]
|
|
30
|
+
end
|
|
31
|
+
class IgnoreMatcher
|
|
32
|
+
class Rule < Struct[untyped]
|
|
33
|
+
attr_accessor base: String
|
|
34
|
+
attr_accessor expression: Regexp
|
|
35
|
+
attr_accessor negated: bool
|
|
36
|
+
attr_accessor directory: bool
|
|
37
|
+
def self.new: (base: String, expression: Regexp, negated: bool, directory: bool) -> instance
|
|
38
|
+
end
|
|
39
|
+
def initialize: (?Array[Rule] rules) -> void
|
|
40
|
+
def add: (String source, ?base: String) -> instance
|
|
41
|
+
def ignored?: (String path, ?directory: bool) -> bool
|
|
42
|
+
end
|
|
43
|
+
class Watcher
|
|
44
|
+
class Event < Struct[untyped]
|
|
45
|
+
attr_accessor type: :created | :modified | :deleted
|
|
46
|
+
attr_accessor path: String
|
|
47
|
+
def self.new: (type: :created | :modified | :deleted, path: String) -> instance
|
|
48
|
+
end
|
|
49
|
+
attr_reader backend: :native | :polling
|
|
50
|
+
attr_reader snapshot: Hash[String, [Integer, Integer, Time, Time]]
|
|
51
|
+
def initialize: (Project project, ?interval: Numeric, ?native: _NativeWatcher?) -> void
|
|
52
|
+
def poll: (?timeout: Numeric) -> Array[Event]
|
|
53
|
+
def start: () { (Event) -> void } -> self
|
|
54
|
+
def close: () -> self
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
class MultiBuffer < Buffer
|
|
59
|
+
class Excerpt < Struct[untyped]
|
|
60
|
+
attr_accessor buffer: Buffer
|
|
61
|
+
attr_accessor first: Buffer::Anchor
|
|
62
|
+
attr_accessor last: Buffer::Anchor
|
|
63
|
+
attr_accessor title: String
|
|
64
|
+
attr_accessor view_start: Integer?
|
|
65
|
+
attr_accessor view_end: Integer?
|
|
66
|
+
def self.new: (Buffer buffer, Buffer::Anchor first, Buffer::Anchor last, String title, ?Integer? view_start, ?Integer? view_end) -> instance
|
|
67
|
+
end
|
|
68
|
+
attr_reader excerpts: Array[Excerpt]
|
|
69
|
+
def initialize: (?excerpts: Array[[Buffer, Range[Integer]] | [Buffer, Range[Integer], String?]]) -> void
|
|
70
|
+
def add_excerpt: (Buffer buffer, Range[Integer] range, ?title: String?) -> self
|
|
71
|
+
def attach_sources: (Hash[Buffer, Buffer] replacements) -> self
|
|
72
|
+
def dirty?: () -> bool
|
|
73
|
+
def begin_undo_group: () -> self
|
|
74
|
+
def end_undo_group: () -> Array[Buffer]
|
|
75
|
+
def edit: (changes changes, ?kind: Symbol, ?selections: Array[Selection], ?before_selections: Array[Selection], ?time: Numeric, ?group: bool) -> patch?
|
|
76
|
+
def undo: () -> bool
|
|
77
|
+
def redo: () -> bool
|
|
78
|
+
def save: (?String? path, ?force: bool) -> self
|
|
79
|
+
def close: () -> void
|
|
80
|
+
end
|
|
81
|
+
end
|
data/sig/snippet.rbs
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Canopus
|
|
2
|
+
class Snippet
|
|
3
|
+
MAX_SOURCE: Integer
|
|
4
|
+
MAX_OUTPUT: Integer
|
|
5
|
+
MAX_DEPTH: Integer
|
|
6
|
+
MAX_NODES: Integer
|
|
7
|
+
VARIABLES: Array[String]
|
|
8
|
+
|
|
9
|
+
def initialize: (String source, ?variables: Hash[String | Symbol, String?]) -> void
|
|
10
|
+
attr_reader text: String
|
|
11
|
+
attr_reader tabstops: Hash[Integer, Array[Range[Integer]]]
|
|
12
|
+
attr_reader choices: Hash[Integer, Array[String]]
|
|
13
|
+
attr_reader transforms: Array[Occurrence]
|
|
14
|
+
attr_reader occurrences: Array[Occurrence]
|
|
15
|
+
|
|
16
|
+
class Occurrence < Data
|
|
17
|
+
attr_reader index: Integer
|
|
18
|
+
attr_reader range: Range[Integer]
|
|
19
|
+
attr_reader transform: Transform?
|
|
20
|
+
attr_reader parents: Array[Integer]
|
|
21
|
+
def self.new: (Integer index, Range[Integer] range, Transform? transform, Array[Integer] parents) -> instance
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class Transform
|
|
25
|
+
TIMEOUT: Float
|
|
26
|
+
attr_reader pattern: String
|
|
27
|
+
attr_reader flags: String
|
|
28
|
+
def apply: (String value) -> String
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class Editor
|
|
33
|
+
def insert_snippet: (String source, ?variables: Hash[String | Symbol, String?], ?workspace_root: String?, ?clipboard: String?) -> Snippet
|
|
34
|
+
def next_snippet: () -> bool
|
|
35
|
+
def previous_snippet: () -> bool
|
|
36
|
+
def snippet_active?: () -> bool
|
|
37
|
+
def snippet_choices: () -> Array[String]?
|
|
38
|
+
def choose_snippet: (String | Integer value) -> bool
|
|
39
|
+
def clear_snippet: () -> nil
|
|
40
|
+
def snippet_variables: (?workspace_root: String?, ?clipboard: String?, ?now: Time, ?selection: Selection, ?cursor_index: Integer) -> Hash[String, String?]
|
|
41
|
+
end
|
|
42
|
+
end
|
data/sig/terminal.rbs
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
module Canopus
|
|
2
|
+
module Terminal
|
|
3
|
+
type color = Integer | [Integer, Integer, Integer] | nil
|
|
4
|
+
type attributes = Hash[Symbol, bool | Integer | [Integer, Integer, Integer]]
|
|
5
|
+
type mouse_action = :press | :move | :release
|
|
6
|
+
class Cell < Struct[untyped]
|
|
7
|
+
attr_accessor text: String
|
|
8
|
+
attr_accessor width: Integer
|
|
9
|
+
attr_accessor foreground: color
|
|
10
|
+
attr_accessor background: color
|
|
11
|
+
attr_accessor attributes: attributes
|
|
12
|
+
attr_accessor hyperlink: String?
|
|
13
|
+
def self.new: (text: String, width: Integer, ?foreground: color, ?background: color, attributes: attributes, ?hyperlink: String?) -> instance
|
|
14
|
+
end
|
|
15
|
+
class Scrollback
|
|
16
|
+
include Enumerable[Array[Cell]]
|
|
17
|
+
class Count < Struct[untyped]
|
|
18
|
+
attr_accessor lines: Integer
|
|
19
|
+
def self.new: (Integer lines) -> instance
|
|
20
|
+
def self.zero: () -> instance
|
|
21
|
+
def +: (Count other) -> Count
|
|
22
|
+
end
|
|
23
|
+
class Row < Struct[untyped]
|
|
24
|
+
attr_accessor cells: Array[Cell]
|
|
25
|
+
def self.new: (Array[Cell] cells) -> instance
|
|
26
|
+
def summary: () -> Count
|
|
27
|
+
end
|
|
28
|
+
attr_reader tree: Denebola::Tree
|
|
29
|
+
attr_reader limit: Integer
|
|
30
|
+
def initialize: (Integer limit) -> void
|
|
31
|
+
def clear: () -> Denebola::Tree
|
|
32
|
+
def length: () -> Integer
|
|
33
|
+
alias size length
|
|
34
|
+
def []: (Integer index) -> Array[Cell]?
|
|
35
|
+
def each: () -> Enumerator[Array[Cell], Denebola::Tree]
|
|
36
|
+
| () { (Array[Cell]) -> void } -> Denebola::Tree
|
|
37
|
+
def push: (Array[Cell] cells) -> Denebola::Tree?
|
|
38
|
+
end
|
|
39
|
+
class Grid
|
|
40
|
+
attr_reader columns: Integer
|
|
41
|
+
attr_reader rows: Integer
|
|
42
|
+
attr_reader cells: Array[Array[Cell]]
|
|
43
|
+
attr_reader scrollback: Scrollback
|
|
44
|
+
attr_reader cursor_x: Integer
|
|
45
|
+
attr_reader cursor_y: Integer
|
|
46
|
+
attr_reader scroll_top: Integer
|
|
47
|
+
attr_reader scroll_bottom: Integer
|
|
48
|
+
attr_accessor foreground: color
|
|
49
|
+
attr_accessor background: color
|
|
50
|
+
attr_accessor attributes: attributes
|
|
51
|
+
attr_accessor hyperlink: String?
|
|
52
|
+
attr_accessor autowrap: bool
|
|
53
|
+
attr_accessor insert_mode: bool
|
|
54
|
+
attr_accessor origin_mode: bool
|
|
55
|
+
attr_accessor cursor_visible: bool
|
|
56
|
+
def initialize: (?columns: Integer, ?rows: Integer, ?scrollback: Integer) -> void
|
|
57
|
+
def reset: () -> void
|
|
58
|
+
def []: (Integer row, ?nil column) -> Array[Cell]?
|
|
59
|
+
| (Integer row, Integer column) -> Cell?
|
|
60
|
+
def alternate?: () -> bool
|
|
61
|
+
def lines: () -> Array[String]
|
|
62
|
+
def text: () -> String
|
|
63
|
+
def put: (String char) -> void
|
|
64
|
+
def self.width: (String char) -> Integer
|
|
65
|
+
def move: (?x: Integer, ?y: Integer, ?relative: bool) -> void
|
|
66
|
+
def position: (Integer row, Integer column) -> void
|
|
67
|
+
def carriage_return: () -> void
|
|
68
|
+
def backspace: () -> void
|
|
69
|
+
def linefeed: () -> void
|
|
70
|
+
def reverse_index: () -> void
|
|
71
|
+
def tab: (?Integer count, ?backward: bool) -> void
|
|
72
|
+
def tab_set: () -> Array[Integer]
|
|
73
|
+
def tab_clear: (?all: bool) -> void
|
|
74
|
+
def margins: (?Integer top, ?Integer bottom) -> void
|
|
75
|
+
def scroll_up: (?Integer count) -> void
|
|
76
|
+
def scroll_down: (?Integer count) -> void
|
|
77
|
+
def erase_display: (?Integer mode) -> void
|
|
78
|
+
def erase_line: (?Integer mode) -> void
|
|
79
|
+
def erase_characters: (?Integer count) -> void
|
|
80
|
+
def insert_characters: (?Integer count) -> void
|
|
81
|
+
def delete_characters: (?Integer count) -> void
|
|
82
|
+
def insert_lines: (?Integer count) -> void
|
|
83
|
+
def delete_lines: (?Integer count) -> void
|
|
84
|
+
def save_cursor: () -> void
|
|
85
|
+
def restore_cursor: () -> void
|
|
86
|
+
def alternate: (bool enable, ?save: bool) -> void
|
|
87
|
+
def resize: (columns: Integer, rows: Integer) -> void
|
|
88
|
+
def selection: ([Integer, Integer] start, [Integer, Integer] finish, ?history: bool) -> String
|
|
89
|
+
def links: (Integer row) -> Array[{url: String, column: Integer, end_column: Integer}]
|
|
90
|
+
def file_paths: (Integer row, ?cwd: String) -> Array[{path: String, line: Integer, column: Integer}]
|
|
91
|
+
end
|
|
92
|
+
class VT
|
|
93
|
+
DEC_GRAPHICS: Hash[String, String]
|
|
94
|
+
attr_reader grid: Grid
|
|
95
|
+
attr_reader title: String?
|
|
96
|
+
attr_reader cwd: String?
|
|
97
|
+
attr_reader modes: Hash[Integer, bool]
|
|
98
|
+
attr_reader replies: Array[String]
|
|
99
|
+
attr_reader bell_count: Integer
|
|
100
|
+
def initialize: (?Grid grid) ?{ (String) -> void } -> void
|
|
101
|
+
def feed: (String bytes) -> self
|
|
102
|
+
def paste: (String text) -> String
|
|
103
|
+
def mouse: (button: Symbol | Integer | nil, column: Integer, row: Integer, ?action: mouse_action, ?shift: bool, ?alt: bool, ?control: bool) -> String
|
|
104
|
+
def key: (String | Symbol name, ?shift: bool, ?alt: bool, ?control: bool) -> String
|
|
105
|
+
end
|
|
106
|
+
class PTY
|
|
107
|
+
attr_reader reader: IO?
|
|
108
|
+
attr_reader writer: IO?
|
|
109
|
+
attr_reader pid: Integer
|
|
110
|
+
attr_reader grid: Grid
|
|
111
|
+
attr_reader vt: VT
|
|
112
|
+
attr_reader status: Process::Status?
|
|
113
|
+
def initialize: (?command: String | Array[String], ?cwd: String, ?columns: Integer, ?rows: Integer, ?env: Hash[String, String?], ?scrollback: Integer) -> void
|
|
114
|
+
def read: (?timeout: Numeric?, ?max_bytes: Integer) -> String?
|
|
115
|
+
def write: (String bytes) -> Integer
|
|
116
|
+
def paste: (String text) -> Integer
|
|
117
|
+
def key: (String | Symbol name, ?shift: bool, ?alt: bool, ?control: bool) -> Integer
|
|
118
|
+
def mouse: (button: Symbol | Integer | nil, column: Integer, row: Integer, ?action: mouse_action, ?shift: bool, ?alt: bool, ?control: bool) -> Integer
|
|
119
|
+
def resize: (columns: Integer, rows: Integer) -> void
|
|
120
|
+
def signal: (?String | Integer name) -> void
|
|
121
|
+
def alive?: () -> bool
|
|
122
|
+
def close: () -> void
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
data/sig/vim.rbs
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Canopus
|
|
2
|
+
class Vim
|
|
3
|
+
type mode = :normal | :insert | :replace | :visual | :visual_line | :visual_block
|
|
4
|
+
type register = [String, bool | :block] | [String, :block, Integer]
|
|
5
|
+
|
|
6
|
+
OPERATORS: Array[String]
|
|
7
|
+
VISUAL_MODES: Array[Symbol]
|
|
8
|
+
|
|
9
|
+
def initialize: (Editor editor) -> void
|
|
10
|
+
attr_reader mode: mode
|
|
11
|
+
attr_reader registers: Hash[String, register]
|
|
12
|
+
attr_reader marks: Hash[String, Buffer::Anchor]
|
|
13
|
+
attr_reader macros: Hash[String, Array[String]]
|
|
14
|
+
attr_reader command_line: String?
|
|
15
|
+
attr_reader status: String
|
|
16
|
+
attr_accessor on_command: (^(String) -> void)?
|
|
17
|
+
|
|
18
|
+
# Input is a single grapheme or a normalized key such as "esc" or "ctrl-v".
|
|
19
|
+
def feed: (String key) -> void
|
|
20
|
+
# Zero-based UTF-8 byte offset of the active edge, including visual mode.
|
|
21
|
+
def cursor_position: () -> Integer
|
|
22
|
+
# On blur: finish insert history and return to Normal, preserving registers.
|
|
23
|
+
def deactivate: () -> self
|
|
24
|
+
# On close: finish history and release every owned buffer anchor.
|
|
25
|
+
def dispose: () -> void
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Canopus
|
|
2
|
+
module Workspace::Edit
|
|
3
|
+
# A preflighted, single-use plan. Resource changes still require explicit UI
|
|
4
|
+
# confirmation at Workspace#apply_workspace_edit; construction does not write.
|
|
5
|
+
class Plan
|
|
6
|
+
def initialize: (Workspace workspace, LSP::object edit) -> void
|
|
7
|
+
def apply: () -> LSP::object
|
|
8
|
+
def close: () -> void
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
module Canopus
|
|
2
|
+
class Project::Tree
|
|
3
|
+
class Entry < Data
|
|
4
|
+
attr_reader path: String
|
|
5
|
+
attr_reader name: String
|
|
6
|
+
attr_reader depth: Integer
|
|
7
|
+
attr_reader directory: bool
|
|
8
|
+
attr_reader expanded: bool
|
|
9
|
+
def self.new: (String path, String name, Integer depth, bool directory, bool expanded) -> instance
|
|
10
|
+
end
|
|
11
|
+
attr_reader expanded: Set[String]
|
|
12
|
+
def initialize: (Array[String] files, ?expanded: Set[String]) -> void
|
|
13
|
+
def toggle: (String path) -> void
|
|
14
|
+
def reveal: (String path) -> void
|
|
15
|
+
def visible: () -> Array[Entry]
|
|
16
|
+
end
|
|
17
|
+
class IconTheme
|
|
18
|
+
FILE: String
|
|
19
|
+
FOLDER: String
|
|
20
|
+
def initialize: (?String? path) -> void
|
|
21
|
+
def texture: (String path, ?directory: bool, ?expanded: bool, ?size: Numeric, ?scale: Numeric, ?color: String) -> Zaniah::GPU::Texture
|
|
22
|
+
end
|
|
23
|
+
class Workspace
|
|
24
|
+
type layout_node = {pane: Pane} | {direction: :horizontal | :vertical, children: Array[layout_node]}
|
|
25
|
+
type palette_state = Hash[Symbol, untyped]
|
|
26
|
+
type search_options = { ?case_sensitive: bool, ?whole_word: bool, ?range: Range[Integer] }
|
|
27
|
+
type semantic_style = {line: Integer, character: Integer, length: Integer, type: Integer, modifiers: Integer, name: String?}
|
|
28
|
+
attr_reader actions: Zaniah::Input::ActionRegistry
|
|
29
|
+
attr_reader project: Project?
|
|
30
|
+
attr_reader docks: Hash[Symbol, {visible: bool, size: Numeric}]
|
|
31
|
+
attr_reader panels: Hash[String, [Symbol, ^() -> (Zaniah::Element | String)]]
|
|
32
|
+
attr_accessor window: Zaniah::Platform::Headless::Window?
|
|
33
|
+
attr_reader palette: palette_state?
|
|
34
|
+
def palette=: (palette_state? value) -> void
|
|
35
|
+
attr_accessor terminal: Terminal::PTY?
|
|
36
|
+
attr_accessor selected_project_path: String?
|
|
37
|
+
attr_reader hover_card: String?
|
|
38
|
+
attr_reader hover_markup: bool?
|
|
39
|
+
attr_reader semantic_styles: Hash[Buffer, [Integer, Array[semantic_style]]]?
|
|
40
|
+
def layout: () -> layout_node
|
|
41
|
+
def project_tree: () -> Project::Tree
|
|
42
|
+
def project_path: (String relative) -> String
|
|
43
|
+
def create_project_entry: (String relative, ?directory: bool) -> String
|
|
44
|
+
def rename_project_entry: (String relative, String destination) -> String
|
|
45
|
+
def trash_project_entry: (String relative) -> String
|
|
46
|
+
def file_preview: (String path) -> Array[String]
|
|
47
|
+
def start_watching: () -> void
|
|
48
|
+
def poll_changes: () -> void
|
|
49
|
+
def icon_theme: () -> IconTheme
|
|
50
|
+
def settings_path: () -> String
|
|
51
|
+
def open_settings: () -> Editor
|
|
52
|
+
def settings_completions: () -> palette_state
|
|
53
|
+
def settings_document?: (Buffer buffer) -> bool?
|
|
54
|
+
def configure_text_system: (?cache_dir: String?) -> Zaniah::TextSystem::Renderer
|
|
55
|
+
def apply_settings: () -> void
|
|
56
|
+
def poll_settings: (?force: bool) -> void
|
|
57
|
+
def dismiss_hover: () -> nil
|
|
58
|
+
def close_language_documents: (?Buffer? buffer) -> void
|
|
59
|
+
def semantic_spans_for: (Buffer buffer, Integer row) -> Array[[Integer, Integer, String]]
|
|
60
|
+
def accept_language_result: (palette_state palette, Integer index) -> void
|
|
61
|
+
def show_diagnostics: () -> void
|
|
62
|
+
def show_outline: () -> void
|
|
63
|
+
def git: () -> Git::Repository?
|
|
64
|
+
def git_status: () -> Hash[String, String]
|
|
65
|
+
def invalidate_git: () -> nil
|
|
66
|
+
def poll_git_changes: (?now: Numeric) -> void
|
|
67
|
+
def git_relative_path: (?Buffer buffer) -> String
|
|
68
|
+
def git_hunks: (?Buffer buffer, ?async: bool) -> Array[Git::Diff::Hunk]
|
|
69
|
+
def show_git_diff: () -> Language::Document
|
|
70
|
+
def toggle_git_hunk: (?Editor current, ?row: Integer?) -> bool
|
|
71
|
+
def show_git_blame: () -> String
|
|
72
|
+
def revert_current_hunk: () -> patch?
|
|
73
|
+
def checkout_branch: (String name) -> String
|
|
74
|
+
def search_query: (String query, palette_state state) -> [String | Regexp, search_options]
|
|
75
|
+
def search_project: (String query, ?regexp: bool, ?case_sensitive: bool, ?whole_word: bool, ?async: bool) -> (Thread | MultiBuffer | nil)
|
|
76
|
+
def replace_in_buffer: (String | Regexp pattern, String replacement, ?case_sensitive: bool, ?whole_word: bool, ?range: Range[Integer]?) -> Integer
|
|
77
|
+
def fold_current: () -> untyped
|
|
78
|
+
def language_ready: (Editor editor, Language::Document document) -> void
|
|
79
|
+
end
|
|
80
|
+
class Editor
|
|
81
|
+
def replace_selections: (String | Array[String] texts, ?kind: Symbol, ?group: bool, ?cursor_back: Integer, ?before_selections: Array[Selection]) -> Array[Selection]
|
|
82
|
+
end
|
|
83
|
+
class Language::Document
|
|
84
|
+
def invalidate: (patch patch) -> void
|
|
85
|
+
# Prism is a lazy optional parser; its native types are not a runtime or RBS
|
|
86
|
+
# dependency for applications which use other languages/headless rendering.
|
|
87
|
+
def ruby_syntax: () -> untyped
|
|
88
|
+
end
|
|
89
|
+
module Plugins
|
|
90
|
+
class API
|
|
91
|
+
def initialize: (Workspace workspace, Array[String] permissions) -> void
|
|
92
|
+
def permit!: (String permission) -> void
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
class Buffer::Transaction
|
|
96
|
+
attr_writer before: rope
|
|
97
|
+
attr_writer after: rope
|
|
98
|
+
attr_writer before_selections: Array[Selection]
|
|
99
|
+
attr_writer after_selections: Array[Selection]
|
|
100
|
+
attr_writer patch: patch
|
|
101
|
+
attr_writer kind: Symbol
|
|
102
|
+
attr_writer time: Numeric
|
|
103
|
+
end
|
|
104
|
+
class Snippet::Transform
|
|
105
|
+
type format_nodes = Array[String | Format]
|
|
106
|
+
class Format < Data
|
|
107
|
+
attr_reader index: Integer
|
|
108
|
+
attr_reader operation: String | Symbol
|
|
109
|
+
attr_reader positive: format_nodes
|
|
110
|
+
attr_reader negative: format_nodes
|
|
111
|
+
def self.new: (Integer index, String | Symbol operation, format_nodes positive, format_nodes negative) -> instance
|
|
112
|
+
end
|
|
113
|
+
def self.parse: (StringScanner scanner, Integer depth) -> instance
|
|
114
|
+
def self.parse_format: (StringScanner scanner, Array[String] endings, Integer depth, ?Array[Integer] budget) -> format_nodes
|
|
115
|
+
def initialize: (String pattern, format_nodes replacement, String flags) -> void
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Development oracle only. Node is never required by Canopus at runtime.
|
|
4
|
+
require "json"
|
|
5
|
+
require "open3"
|
|
6
|
+
require_relative "../lib/canopus"
|
|
7
|
+
|
|
8
|
+
patterns = ["", "a", ".", ".*", "^", "$", "^.$", "^a", "a$", '[a-z]+', '[^a]', '(a)?', '(a+)(b*)',
|
|
9
|
+
'(?=a)', '(?<=a)b', '(?:a|b)+', '\d+', '\w+', '\s+', '\S+', '\b', '\B', '[a\s]', '[\S]', '[a[b]']
|
|
10
|
+
flags = ["", "g", "i", "gi", "m", "gm", "s", "gs", "u", "gu", "ims", "gimsu"]
|
|
11
|
+
values = ["", "a", "A", "ab", "aab", "abc123", "aa\nbb", "a\r\nb", "a\rb", "\n", "日本", "a日本b",
|
|
12
|
+
"\u00a0", "x\ufeffy", "a\u2028b", "a\u2029b", "😀", "a😀b"]
|
|
13
|
+
cases = patterns.product(flags, values).reject { |pattern, options, value| (!options.include?("u") || pattern == '\B') && value.match?(/[\u{10000}-\u{10ffff}]/) }
|
|
14
|
+
javascript = <<~JS
|
|
15
|
+
let input = '';
|
|
16
|
+
process.stdin.setEncoding('utf8');
|
|
17
|
+
process.stdin.on('data', part => input += part);
|
|
18
|
+
process.stdin.on('end', () => {
|
|
19
|
+
const result = JSON.parse(input).map(([pattern, flags, value]) =>
|
|
20
|
+
Buffer.from(value.replace(new RegExp(pattern, flags), (...args) => {
|
|
21
|
+
const captures = args.slice(0, -2);
|
|
22
|
+
return [0, 1, 2].map(index => '[' + (captures[index] || '') + ']').join('');
|
|
23
|
+
})).toString('base64')
|
|
24
|
+
);
|
|
25
|
+
process.stdout.write(JSON.stringify(result));
|
|
26
|
+
});
|
|
27
|
+
JS
|
|
28
|
+
output, error, status = Open3.capture3("node", "-e", javascript, stdin_data: JSON.generate(cases))
|
|
29
|
+
abort error unless status.success?
|
|
30
|
+
expected = JSON.parse(output).map { |encoded| encoded.unpack1("m0").force_encoding(Encoding::UTF_8) }
|
|
31
|
+
cases.each_with_index do |(pattern, options, value), index|
|
|
32
|
+
snippet = Canopus::Snippet.new("${VALUE/#{pattern}/[$0][$1][$2]/#{options}}", variables: {"VALUE" => value})
|
|
33
|
+
abort "Mismatch #{cases[index].inspect}: expected #{expected[index].inspect}, got #{snippet.text.inspect}" unless snippet.text == expected[index]
|
|
34
|
+
end
|
|
35
|
+
puts "Certified #{cases.length} snippet transform cases against JavaScript RegExp (#{patterns.length} patterns, #{flags.length} flag combinations, #{values.length} inputs)."
|