Class: Pikuri::Lsp::Range
- Inherits:
-
Data
- Object
- Data
- Pikuri::Lsp::Range
- Defined in:
- lib/pikuri/lsp/range.rb
Overview
A span between two Positions, in pikuri's 1-based coordinates. Servers answer with ranges everywhere — a definition's whole body, an identifier's own extent, the slice of a class file worth showing — so this is mostly a parse target:
range = Range.from_wire({ 'start' => { 'line' => 12, 'character' => 6 },
'end' => { 'line' => 12, 'character' => 22 } },
text: File.read(path), encoding: PositionEncoding::UTF8)
range.to_s # => "13:7-13:23"
range.start.line # => 13
There is deliberately no #to_wire: pikuri sends positions (an anchor
for a query), never ranges. The one client-to-server range in LSP is a
didChange edit, and pikuri re-sends didOpen instead.
Note the shadowing: inside Pikuri::Lsp, Range is this class, so
Ruby's own needs ::Range.
Instance Attribute Summary collapse
-
#end ⇒ Position
readonly
One position past the span, LSP's half-open convention, so a zero-width range has
start == end. -
#start ⇒ Position
readonly
First position inside the span.
Class Method Summary collapse
-
.from_wire(hash, text: nil, encoding: PositionEncoding::DEFAULT) ⇒ Range
Parse LSP's
Rangeobject.
Instance Method Summary collapse
-
#single_line? ⇒ Boolean
Whether the span begins and ends on one line, i.e.
-
#to_s ⇒ String
"13:7-13:23".
Instance Attribute Details
#end ⇒ Position (readonly)
Returns one position past the span, LSP's half-open
convention, so a zero-width range has start == end.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/pikuri/lsp/range.rb', line 28 Range = Data.define(:start, :end) do # Parse LSP's +Range+ object. # # @param hash [Hash{String => Hash}] +{"start" =>, "end" =>}+. # @param text [String, nil] the *whole* document the range points into, # which is what makes both columns exact; +nil+ when the text is not to # hand (see {PositionEncoding.column_for}). # @param encoding [String] the server's negotiated +positionEncoding+. # @return [Range] # @raise [KeyError] if +start+ or +end+ is missing. def self.from_wire(hash, text: nil, encoding: PositionEncoding::DEFAULT) lines = text&.lines wire_start = hash.fetch('start') wire_end = hash.fetch('end') new(start: Position.from_wire(wire_start, line_text: line_at(lines, wire_start), encoding: encoding), end: Position.from_wire(wire_end, line_text: line_at(lines, wire_end), encoding: encoding)) end # The text of the line a wire position sits on, or +nil+ when the # document text was not supplied. def self.line_at(lines, wire_position) lines && lines[Integer(wire_position.fetch('line'))] end private_class_method :line_at # @return [Boolean] whether the span begins and ends on one line, i.e. # whether a one-line snippet can show all of it. def single_line? start.line == self.end.line end # @return [String] +"13:7-13:23"+. def to_s "#{start}-#{self.end}" end end |
#start ⇒ Position (readonly)
Returns first position inside the span.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/pikuri/lsp/range.rb', line 28 Range = Data.define(:start, :end) do # Parse LSP's +Range+ object. # # @param hash [Hash{String => Hash}] +{"start" =>, "end" =>}+. # @param text [String, nil] the *whole* document the range points into, # which is what makes both columns exact; +nil+ when the text is not to # hand (see {PositionEncoding.column_for}). # @param encoding [String] the server's negotiated +positionEncoding+. # @return [Range] # @raise [KeyError] if +start+ or +end+ is missing. def self.from_wire(hash, text: nil, encoding: PositionEncoding::DEFAULT) lines = text&.lines wire_start = hash.fetch('start') wire_end = hash.fetch('end') new(start: Position.from_wire(wire_start, line_text: line_at(lines, wire_start), encoding: encoding), end: Position.from_wire(wire_end, line_text: line_at(lines, wire_end), encoding: encoding)) end # The text of the line a wire position sits on, or +nil+ when the # document text was not supplied. def self.line_at(lines, wire_position) lines && lines[Integer(wire_position.fetch('line'))] end private_class_method :line_at # @return [Boolean] whether the span begins and ends on one line, i.e. # whether a one-line snippet can show all of it. def single_line? start.line == self.end.line end # @return [String] +"13:7-13:23"+. def to_s "#{start}-#{self.end}" end end |
Class Method Details
.from_wire(hash, text: nil, encoding: PositionEncoding::DEFAULT) ⇒ Range
Parse LSP's Range object.
38 39 40 41 42 43 44 |
# File 'lib/pikuri/lsp/range.rb', line 38 def self.from_wire(hash, text: nil, encoding: PositionEncoding::DEFAULT) lines = text&.lines wire_start = hash.fetch('start') wire_end = hash.fetch('end') new(start: Position.from_wire(wire_start, line_text: line_at(lines, wire_start), encoding: encoding), end: Position.from_wire(wire_end, line_text: line_at(lines, wire_end), encoding: encoding)) end |
Instance Method Details
#single_line? ⇒ Boolean
Returns whether the span begins and ends on one line, i.e. whether a one-line snippet can show all of it.
55 56 57 |
# File 'lib/pikuri/lsp/range.rb', line 55 def single_line? start.line == self.end.line end |
#to_s ⇒ String
Returns "13:7-13:23".
60 61 62 |
# File 'lib/pikuri/lsp/range.rb', line 60 def to_s "#{start}-#{self.end}" end |