Class: Pikuri::Lsp::Registry::StdioEntry
- Inherits:
-
Data
- Object
- Data
- Pikuri::Lsp::Registry::StdioEntry
- Defined in:
- lib/pikuri/lsp/registry.rb
Overview
One language server: the argv to launch it and the files it answers for.
files holds basename globs, not extensions, because Rakefile has
none — and it is the dispatch key, so getting it wrong sends Ruby
questions to a Java server rather than merely failing.
Instance Attribute Summary collapse
-
#command ⇒ Array<String>
readonly
Argv, e.g.
-
#env ⇒ Hash{String => String}
readonly
Extra environment for the child, merged over the de-bundlerized environment (BundlerEnv), e.g.
-
#files ⇒ Array<String>
readonly
Basename globs, e.g.
-
#id ⇒ String
readonly
This server's name in log lines, restart messages and ServerProgress#server_id, e.g.
-
#init_options ⇒ Hash?
readonly
initializationOptions, passed verbatim at handshake time and never parsed by pikuri — the home for outbound per-server glue, e.g. -
#language_id ⇒ String
readonly
The
languageIdeverydidOpencarries, e.g.
Instance Method Summary collapse
-
#claims?(path) ⇒ Boolean
Whether this server answers for
path— matched on the basename, so a directory component never decides which server sees a file. -
#initialize(id:, command:, files:, language_id: nil, env: {}, init_options: nil) ⇒ StdioEntry
constructor
A new instance of StdioEntry.
Constructor Details
#initialize(id:, command:, files:, language_id: nil, env: {}, init_options: nil) ⇒ StdioEntry
Returns a new instance of StdioEntry.
88 89 90 91 92 93 94 95 96 |
# File 'lib/pikuri/lsp/registry.rb', line 88 def initialize(id:, command:, files:, language_id: nil, env: {}, init_options: nil) raise ArgumentError, "id must be a non-empty String, got #{id.inspect}" if id.to_s.empty? raise ArgumentError, "command must be a non-empty argv Array, got #{command.inspect}" if command.to_a.empty? raise ArgumentError, "files must be a non-empty glob Array, got #{files.inspect}" if files.to_a.empty? super(id: id, command: command.freeze, files: files.freeze, language_id: language_id || Registry.derive_language_id(files, id), env: env.freeze, init_options: ) end |
Instance Attribute Details
#command ⇒ Array<String> (readonly)
Returns argv, e.g. ["jdtls", "-data", "/…/cache"].
Spawned with cwd = the workspace root, always.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/pikuri/lsp/registry.rb', line 84 StdioEntry = Data.define(:id, :command, :files, :language_id, :env, :init_options) do # @raise [ArgumentError] on an empty +id+ / +command+ / +files+, or when # +language_id:+ is omitted and no glob in +files+ carries an # extension {LANGUAGE_IDS} knows. def initialize(id:, command:, files:, language_id: nil, env: {}, init_options: nil) raise ArgumentError, "id must be a non-empty String, got #{id.inspect}" if id.to_s.empty? raise ArgumentError, "command must be a non-empty argv Array, got #{command.inspect}" if command.to_a.empty? raise ArgumentError, "files must be a non-empty glob Array, got #{files.inspect}" if files.to_a.empty? super(id: id, command: command.freeze, files: files.freeze, language_id: language_id || Registry.derive_language_id(files, id), env: env.freeze, init_options: ) end # Whether this server answers for +path+ — matched on the basename, so a # directory component never decides which server sees a file. # # @param path [String, Pathname] absolute or relative; only the basename # is read. # @return [Boolean] def claims?(path) basename = File.basename(path.to_s) files.any? { |glob| File.fnmatch?(glob, basename, File::FNM_DOTMATCH) } end end |
#env ⇒ Hash{String => String} (readonly)
Returns extra environment for the child,
merged over the de-bundlerized environment (BundlerEnv), e.g.
{"JAVA_HOME" => "/usr/lib/jvm/java-21"}. Frozen, defaults to {}.
The legitimate per-child credential channel of the "environment is
not a secret store" seam.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/pikuri/lsp/registry.rb', line 84 StdioEntry = Data.define(:id, :command, :files, :language_id, :env, :init_options) do # @raise [ArgumentError] on an empty +id+ / +command+ / +files+, or when # +language_id:+ is omitted and no glob in +files+ carries an # extension {LANGUAGE_IDS} knows. def initialize(id:, command:, files:, language_id: nil, env: {}, init_options: nil) raise ArgumentError, "id must be a non-empty String, got #{id.inspect}" if id.to_s.empty? raise ArgumentError, "command must be a non-empty argv Array, got #{command.inspect}" if command.to_a.empty? raise ArgumentError, "files must be a non-empty glob Array, got #{files.inspect}" if files.to_a.empty? super(id: id, command: command.freeze, files: files.freeze, language_id: language_id || Registry.derive_language_id(files, id), env: env.freeze, init_options: ) end # Whether this server answers for +path+ — matched on the basename, so a # directory component never decides which server sees a file. # # @param path [String, Pathname] absolute or relative; only the basename # is read. # @return [Boolean] def claims?(path) basename = File.basename(path.to_s) files.any? { |glob| File.fnmatch?(glob, basename, File::FNM_DOTMATCH) } end end |
#files ⇒ Array<String> (readonly)
Returns basename globs, e.g.
["*.rb", "*.rake", "Rakefile"]. First entry whose glob matches
wins; overlaps are not detected.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/pikuri/lsp/registry.rb', line 84 StdioEntry = Data.define(:id, :command, :files, :language_id, :env, :init_options) do # @raise [ArgumentError] on an empty +id+ / +command+ / +files+, or when # +language_id:+ is omitted and no glob in +files+ carries an # extension {LANGUAGE_IDS} knows. def initialize(id:, command:, files:, language_id: nil, env: {}, init_options: nil) raise ArgumentError, "id must be a non-empty String, got #{id.inspect}" if id.to_s.empty? raise ArgumentError, "command must be a non-empty argv Array, got #{command.inspect}" if command.to_a.empty? raise ArgumentError, "files must be a non-empty glob Array, got #{files.inspect}" if files.to_a.empty? super(id: id, command: command.freeze, files: files.freeze, language_id: language_id || Registry.derive_language_id(files, id), env: env.freeze, init_options: ) end # Whether this server answers for +path+ — matched on the basename, so a # directory component never decides which server sees a file. # # @param path [String, Pathname] absolute or relative; only the basename # is read. # @return [Boolean] def claims?(path) basename = File.basename(path.to_s) files.any? { |glob| File.fnmatch?(glob, basename, File::FNM_DOTMATCH) } end end |
#id ⇒ String (readonly)
Returns this server's name in log lines, restart messages and
ServerProgress#server_id, e.g. "ruby". Never model-facing: the
model names no server, it names a file.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/pikuri/lsp/registry.rb', line 84 StdioEntry = Data.define(:id, :command, :files, :language_id, :env, :init_options) do # @raise [ArgumentError] on an empty +id+ / +command+ / +files+, or when # +language_id:+ is omitted and no glob in +files+ carries an # extension {LANGUAGE_IDS} knows. def initialize(id:, command:, files:, language_id: nil, env: {}, init_options: nil) raise ArgumentError, "id must be a non-empty String, got #{id.inspect}" if id.to_s.empty? raise ArgumentError, "command must be a non-empty argv Array, got #{command.inspect}" if command.to_a.empty? raise ArgumentError, "files must be a non-empty glob Array, got #{files.inspect}" if files.to_a.empty? super(id: id, command: command.freeze, files: files.freeze, language_id: language_id || Registry.derive_language_id(files, id), env: env.freeze, init_options: ) end # Whether this server answers for +path+ — matched on the basename, so a # directory component never decides which server sees a file. # # @param path [String, Pathname] absolute or relative; only the basename # is read. # @return [Boolean] def claims?(path) basename = File.basename(path.to_s) files.any? { |glob| File.fnmatch?(glob, basename, File::FNM_DOTMATCH) } end end |
#init_options ⇒ Hash? (readonly)
Returns initializationOptions, passed verbatim at
handshake time and never parsed by pikuri — the home for outbound
per-server glue, e.g. jdtls's classFileContentsSupport, without
which every library symbol answers with silence. There is
deliberately no sibling settings: field for answering the
server's workspace/configuration requests: Connection replies
null to every server-initiated request, and both reference
servers tolerate that.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/pikuri/lsp/registry.rb', line 84 StdioEntry = Data.define(:id, :command, :files, :language_id, :env, :init_options) do # @raise [ArgumentError] on an empty +id+ / +command+ / +files+, or when # +language_id:+ is omitted and no glob in +files+ carries an # extension {LANGUAGE_IDS} knows. def initialize(id:, command:, files:, language_id: nil, env: {}, init_options: nil) raise ArgumentError, "id must be a non-empty String, got #{id.inspect}" if id.to_s.empty? raise ArgumentError, "command must be a non-empty argv Array, got #{command.inspect}" if command.to_a.empty? raise ArgumentError, "files must be a non-empty glob Array, got #{files.inspect}" if files.to_a.empty? super(id: id, command: command.freeze, files: files.freeze, language_id: language_id || Registry.derive_language_id(files, id), env: env.freeze, init_options: ) end # Whether this server answers for +path+ — matched on the basename, so a # directory component never decides which server sees a file. # # @param path [String, Pathname] absolute or relative; only the basename # is read. # @return [Boolean] def claims?(path) basename = File.basename(path.to_s) files.any? { |glob| File.fnmatch?(glob, basename, File::FNM_DOTMATCH) } end end |
#language_id ⇒ String (readonly)
Returns the languageId every didOpen carries, e.g.
"ruby". Derived at construction from the first extension-bearing
glob when not given — per entry, not per file, which is wrong for
the +eslint+-shaped server that claims eight extensions and right for
everything pikuri has met.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/pikuri/lsp/registry.rb', line 84 StdioEntry = Data.define(:id, :command, :files, :language_id, :env, :init_options) do # @raise [ArgumentError] on an empty +id+ / +command+ / +files+, or when # +language_id:+ is omitted and no glob in +files+ carries an # extension {LANGUAGE_IDS} knows. def initialize(id:, command:, files:, language_id: nil, env: {}, init_options: nil) raise ArgumentError, "id must be a non-empty String, got #{id.inspect}" if id.to_s.empty? raise ArgumentError, "command must be a non-empty argv Array, got #{command.inspect}" if command.to_a.empty? raise ArgumentError, "files must be a non-empty glob Array, got #{files.inspect}" if files.to_a.empty? super(id: id, command: command.freeze, files: files.freeze, language_id: language_id || Registry.derive_language_id(files, id), env: env.freeze, init_options: ) end # Whether this server answers for +path+ — matched on the basename, so a # directory component never decides which server sees a file. # # @param path [String, Pathname] absolute or relative; only the basename # is read. # @return [Boolean] def claims?(path) basename = File.basename(path.to_s) files.any? { |glob| File.fnmatch?(glob, basename, File::FNM_DOTMATCH) } end end |
Instance Method Details
#claims?(path) ⇒ Boolean
Whether this server answers for path — matched on the basename, so a
directory component never decides which server sees a file.
104 105 106 107 |
# File 'lib/pikuri/lsp/registry.rb', line 104 def claims?(path) basename = File.basename(path.to_s) files.any? { |glob| File.fnmatch?(glob, basename, File::FNM_DOTMATCH) } end |