Skip to content

Commit 5f698e0

Browse files
lekemulabyroot
andcommitted
String#index(offset:) FTW 🚀
castwide#1054 (comment) Co-authored-by: Jean Boussier <[email protected]>
1 parent 2e87f96 commit 5f698e0

File tree

2 files changed

+34
-20
lines changed

2 files changed

+34
-20
lines changed

‎lib/solargraph/position.rb‎

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,21 @@ def inspect
5858
# @return [Integer]
5959
def self.to_offset text, position
6060
return 0 if text.empty?
61+
newline_index = -1
6162
cursor = 0
62-
index = -1
63-
text.each_line do |line|
64-
index += 1
65-
break if index == position.line
66-
cursor += line.length
63+
line = -1
64+
65+
last_line_index = 0
66+
while (newline_index = text.index("\n", newline_index + 1)) && line <= position.line
67+
line += 1
68+
break if line == position.line
69+
line_length = newline_index - last_line_index
70+
71+
cursor += line_length.zero? ? 1 : line_length
72+
73+
last_line_index = newline_index
6774
end
75+
6876
cursor + position.character
6977
end
7078

@@ -87,22 +95,12 @@ def self.line_char_to_offset text, line, character
8795
def self.from_offset text, offset
8896
cursor = 0
8997
line = 0
90-
character = nil
91-
text.each_line do |l|
92-
line_length = l.length
93-
94-
if l.end_with?("\n")
95-
char_length = line_length - 1
96-
else
97-
char_length = line_length
98-
end
99-
100-
if cursor + char_length >= offset
101-
character = offset - cursor
102-
break
103-
end
104-
cursor += line_length
98+
character = offset
99+
newline_index = -1
100+
101+
while (newline_index = text.index("\n", newline_index + 1)) && newline_index < offset
105102
line += 1
103+
character = offset - newline_index - 1
106104
end
107105
character = 0 if character.nil? and (cursor - offset).between?(0, 1)
108106
raise InvalidOffsetError if character.nil?

‎spec/position_spec.rb‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,22 @@
1212
expect(orig).to be(norm)
1313
end
1414

15+
it 'finds offset from position' do
16+
text = "\n class Foo\n def bar baz, boo = 'boo'\n end\n end\n "
17+
expect(Solargraph::Position.to_offset(text, Solargraph::Position.new(0, 0))).to eq(0)
18+
expect(Solargraph::Position.to_offset(text, Solargraph::Position.new(0, 4))).to eq(4)
19+
expect(Solargraph::Position.to_offset(text, Solargraph::Position.new(2, 12))).to eq(29)
20+
expect(Solargraph::Position.to_offset(text, Solargraph::Position.new(2, 27))).to eq(44)
21+
end
22+
23+
it 'constructs position from offset' do
24+
text = "\n class Foo\n def bar baz, boo = 'boo'\n end\n end\n "
25+
expect(Solargraph::Position.from_offset(text, 0)).to eq(Solargraph::Position.new(0, 0))
26+
expect(Solargraph::Position.from_offset(text, 4)).to eq(Solargraph::Position.new(1, 3))
27+
expect(Solargraph::Position.from_offset(text, 29)).to eq(Solargraph::Position.new(2, 12))
28+
expect(Solargraph::Position.from_offset(text, 44)).to eq(Solargraph::Position.new(2, 27))
29+
end
30+
1531
it "raises an error for objects that cannot be normalized" do
1632
expect {
1733
Solargraph::Position.normalize('0, 1')

0 commit comments

Comments
 (0)