Skip to content

Commit

Permalink
Add yielding line number to {String,IO}#each_line
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota committed Jan 5, 2019
1 parent d99c95c commit 76e77ef
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 15 deletions.
18 changes: 18 additions & 0 deletions spec/std/io/io_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,24 @@ describe IO do
lines.should eq ["a", "bb", "cc"]
end

it "does each_line with lino" do
lines = [] of String
io = SimpleIOMemory.new("a\nbb\ncc")
io.each_line do |line, lino|
lines << "#{lino}:#{line}"
end
lines.should eq ["1:a", "2:bb", "3:cc"]
end

it "does each_line with lino and offset" do
lines = [] of String
io = SimpleIOMemory.new("a\nbb\ncc")
io.each_line(offset: 10) do |line, lino|
lines << "#{lino}:#{line}"
end
lines.should eq ["11:a", "12:bb", "13:cc"]
end

it "does each_char" do
chars = [] of Char
io = SimpleIOMemory.new("あいう")
Expand Down
16 changes: 16 additions & 0 deletions spec/std/string_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2026,6 +2026,22 @@ describe "String" do
lines.should eq(["foo\n", "\n", "bar\r\n", "baz\r\n"])
end

it "gets each_line with lino" do
lines = [] of String
"foo\n\nbar\r\nbaz\r\n".each_line do |line, lino|
lines << "#{lino}:#{line}"
end.should be_nil
lines.should eq(["1:foo", "2:", "3:bar", "4:baz"])
end

it "gets each_line with lino and offset" do
lines = [] of String
"foo\n\nbar\r\nbaz\r\n".each_line(offset: 10) do |line, lino|
lines << "#{lino}:#{line}"
end.should be_nil
lines.should eq(["11:foo", "12:", "13:bar", "14:baz"])
end

it "gets each_line iterator" do
iter = "foo\nbar\r\nbaz\r\n".each_line
iter.next.should eq("foo")
Expand Down
25 changes: 18 additions & 7 deletions src/io.cr
Original file line number Diff line number Diff line change
Expand Up @@ -908,19 +908,30 @@ abstract class IO
# ```
# io = IO::Memory.new("hello\nworld")
# io.each_line do |line|
# puts line.chomp.reverse
# puts line
# end
# # output:
# # hello
# # world
# ```
#
# Output:
# The second argument yielded to the block is the line number starting at `1`.
# The optional *offset* argument is added to the first line number.
#
# ```text
# olleh
# dlrow
# ```
def each_line(*args, **options) : Nil
# io = IO::Memory.new("hello\nworld")
# io.each_line do |line|
# puts "#{lino}: #{line}"
# end
# # output:
# # 1: hello
# # 2: world
# ```
def each_line(*args, offset = 0, **options, &block : String, Int32 -> _) : Nil
line_number = offset
while line = gets(*args, **options)
yield line
line_number += 1
yield line, lino
end
end

Expand Down
33 changes: 25 additions & 8 deletions src/string.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3340,17 +3340,33 @@ class String
# even the monkey seems to want
# a little coat of straw"
# haiku.each_line do |stanza|
# puts stanza.upcase
# puts stanza
# end
# # => THE FIRST COLD SHOWER
# # => EVEN THE MONKEY SEEMS TO WANT
# # => A LITTLE COAT OF STRAW
# # output:
# # the first cold shower
# # even the monkey seems to want
# # a little coat of straw
# ```
def each_line(chomp = true) : Nil
#
# The second argument yielded to the block is the line number starting at `1`.
# The optional *offset* argument is added to the first line number.
#
# ```
# haiku = "the first cold shower
# even the monkey seems to want
# a little coat of straw"
# haiku.each_line do |stanza, lino|
# puts "#{lino}: #{stanza}"
# end
# # output:
# # 1: the first cold shower
# # 2: even the monkey seems to want
# # 3: a little coat of straw
# ```
def each_line(chomp = true, offset lino : Int32 = 0, &block : String, Int32 -> _) : Nil
return if empty?

offset = 0

while byte_index = byte_index('\n'.ord.to_u8, offset)
count = byte_index - offset + 1
if chomp
Expand All @@ -3359,13 +3375,14 @@ class String
count -= 1
end
end
lino += 1

yield unsafe_byte_slice_string(offset, count)
yield unsafe_byte_slice_string(offset, count), lino
offset = byte_index + 1
end

unless offset == bytesize
yield unsafe_byte_slice_string(offset)
yield unsafe_byte_slice_string(offset), lino + 1
end
end

Expand Down

0 comments on commit 76e77ef

Please sign in to comment.