Class: Textbringer::LSP::Client
- Inherits:
-
Object
- Object
- Textbringer::LSP::Client
- Defined in:
- lib/textbringer/lsp/client.rb,
sig/lib/textbringer/lsp/client.rbs
Defined Under Namespace
Classes: ServerError, TimeoutError
Instance Attribute Summary collapse
-
#root_path ⇒ Object
readonly
Returns the value of attribute root_path.
-
#server_capabilities ⇒ Object
readonly
Returns the value of attribute server_capabilities.
-
#server_name ⇒ Object
readonly
Returns the value of attribute server_name.
Instance Method Summary collapse
- #client_capabilities ⇒ Hash[untyped, untyped]
-
#completion(uri:, line:, character:, context: nil, &callback) ⇒ Object
Completion.
- #completion_item_kind_name(kind) ⇒ Object
- #did_change(uri:, version:, text: nil, range: nil, range_length: nil) ⇒ Object
- #did_close(uri:) ⇒ Object
-
#did_open(uri:, language_id:, version:, text:) ⇒ Object
Document synchronization.
- #document_open?(uri) ⇒ Boolean
-
#initialize(command:, args: [], root_path:, server_name: nil, workspace_folders: nil) ⇒ Client
constructor
A new instance of Client.
- #initialized? ⇒ Boolean
- #normalize_completion_item(item) ⇒ Hash[untyped, untyped]
- #normalize_completion_result(result) ⇒ Object
- #running? ⇒ Boolean
-
#signature_help(uri:, line:, character:, context: nil, &callback) ⇒ Object
Signature Help.
- #start ⇒ Object
- #stop ⇒ Object
Constructor Details
#initialize(command:, args: [], root_path:, server_name: nil, workspace_folders: nil) ⇒ Client
Returns a new instance of Client.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/textbringer/lsp/client.rb', line 13 def initialize(command:, args: [], root_path:, server_name: nil, workspace_folders: nil) @command = command @args = args @root_path = root_path @server_name = server_name || command @workspace_folders = Array(workspace_folders || @root_path) @stdin = nil @stdout = nil @stderr = nil @wait_thr = nil @request_id = 0 @pending_requests = {} @running = false @initialized = false @reader_thread = nil @mutex = Mutex.new @open_documents = {} @server_capabilities = {} end |
Instance Attribute Details
#root_path ⇒ Object (readonly)
Returns the value of attribute root_path.
11 12 13 |
# File 'lib/textbringer/lsp/client.rb', line 11 def root_path @root_path end |
#server_capabilities ⇒ Object (readonly)
Returns the value of attribute server_capabilities.
11 12 13 |
# File 'lib/textbringer/lsp/client.rb', line 11 def server_capabilities @server_capabilities end |
#server_name ⇒ Object (readonly)
Returns the value of attribute server_name.
11 12 13 |
# File 'lib/textbringer/lsp/client.rb', line 11 def server_name @server_name end |
Instance Method Details
#client_capabilities ⇒ Hash[untyped, untyped]
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/textbringer/lsp/client.rb', line 248 def client_capabilities { textDocument: { completion: { completionItem: { snippetSupport: false, deprecatedSupport: true, labelDetailsSupport: true }, completionItemKind: { valueSet: (1..25).to_a }, contextSupport: true }, signatureHelp: { signatureInformation: { documentationFormat: ["plaintext"], parameterInformation: { labelOffsetSupport: true } }, contextSupport: true }, synchronization: { didSave: true, willSave: false, willSaveWaitUntil: false, dynamicRegistration: false } }, workspace: { workspaceFolders: true } } end |
#completion(uri:, line:, character:, context: nil, &callback) ⇒ Object
Completion
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/textbringer/lsp/client.rb', line 131 def completion(uri:, line:, character:, context: nil, &callback) return unless @initialized params = { textDocument: { uri: uri }, position: { line: line, character: character } } params[:context] = context if context send_request("textDocument/completion", params) do |result, error| if error callback.call(nil, error) if callback else items = normalize_completion_result(result) callback.call(items, nil) if callback end end end |
#completion_item_kind_name(arg0) ⇒ String #completion_item_kind_name(arg0) ⇒ nil #completion_item_kind_name(arg0) ⇒ nil
563 564 565 |
# File 'lib/textbringer/lsp/client.rb', line 563 def completion_item_kind_name(kind) COMPLETION_ITEM_KINDS[kind] end |
#did_change(uri:, version:, text: nil, range: nil, range_length: nil) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/textbringer/lsp/client.rb', line 89 def did_change(uri:, version:, text: nil, range: nil, range_length: nil) return unless @initialized return unless @open_documents.key?(uri) # Support both full and incremental sync content_change = if range # Incremental change change = { range: range } change[:rangeLength] = range_length if range_length change[:text] = text if text change else # Full document sync { text: text } end send_notification("textDocument/didChange", { textDocument: { uri: uri, version: version }, contentChanges: [content_change] }) @open_documents[uri] = version end |
#did_close(uri:) ⇒ Object
115 116 117 118 119 120 121 122 123 |
# File 'lib/textbringer/lsp/client.rb', line 115 def did_close(uri:) return unless @initialized return unless @open_documents.key?(uri) send_notification("textDocument/didClose", { textDocument: { uri: uri } }) @open_documents.delete(uri) end |
#did_open(uri:, language_id:, version:, text:) ⇒ Object
Document synchronization
75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/textbringer/lsp/client.rb', line 75 def did_open(uri:, language_id:, version:, text:) return unless @initialized send_notification("textDocument/didOpen", { textDocument: { uri: uri, languageId: language_id, version: version, text: text } }) @open_documents[uri] = version end |
#document_open?(uri) ⇒ Boolean
125 126 127 |
# File 'lib/textbringer/lsp/client.rb', line 125 def document_open?(uri) @open_documents.key?(uri) end |
#initialized? ⇒ Boolean
69 70 71 |
# File 'lib/textbringer/lsp/client.rb', line 69 def initialized? @initialized end |
#normalize_completion_item(item) ⇒ Hash[untyped, untyped]
524 525 526 527 528 529 530 531 532 533 |
# File 'lib/textbringer/lsp/client.rb', line 524 def normalize_completion_item(item) { label: item["label"], insert_text: item["insertText"] || item["textEdit"]&.dig("newText") || item["label"], detail: item["detail"], kind: completion_item_kind_name(item["kind"]), sort_text: item["sortText"] || item["label"], filter_text: item["filterText"] || item["label"] } end |
#normalize_completion_result(arg0) ⇒ Array[untyped] #normalize_completion_result(arg0) ⇒ Array[untyped] #normalize_completion_result(arg0) ⇒ Array[untyped]
510 511 512 513 514 515 516 517 518 519 520 521 522 |
# File 'lib/textbringer/lsp/client.rb', line 510 def normalize_completion_result(result) return [] if result.nil? items = if result.is_a?(Array) result elsif result.is_a?(Hash) && result["items"] result["items"] else [] end items.map { |item| normalize_completion_item(item) } end |
#running? ⇒ Boolean
65 66 67 |
# File 'lib/textbringer/lsp/client.rb', line 65 def running? @running end |
#signature_help(uri:, line:, character:, context: nil, &callback) ⇒ Object
Signature Help
152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/textbringer/lsp/client.rb', line 152 def signature_help(uri:, line:, character:, context: nil, &callback) return unless @initialized params = { textDocument: { uri: uri }, position: { line: line, character: character } } params[:context] = context if context send_request("textDocument/signatureHelp", params) do |result, error| callback.call(result, error) if callback end end |
#start ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/textbringer/lsp/client.rb', line 33 def start return if @running begin # Use Bundler's clean environment if available if defined?(Bundler) Bundler.with_unbundled_env do @stdin, @stdout, @stderr, @wait_thr = Open3.popen3(@command, *@args) end else @stdin, @stdout, @stderr, @wait_thr = Open3.popen3(@command, *@args) end rescue Errno::ENOENT Utils.("LSP server command not found: #{@command}") return end @running = true initialize_server_sync start_reader_thread end |
#stop ⇒ Object
57 58 59 60 61 62 63 |
# File 'lib/textbringer/lsp/client.rb', line 57 def stop return unless @running shutdown exit_server cleanup end |