# A class for calculating locations (line, column) in a string based # on an offset. class StringLocations def initialize(string) @string, @string_length = string, string.length @line_lengths = @string.split(/\n/).map {|l| l.length} @start_pos_of_line = [0] @line_lengths.each do |l| @start_pos_of_line << @start_pos_of_line.last + l + 1 end end def location(offset) l = line(offset) return l, column(offset, l) end def column(offset, l = nil) l ||= line(offset) offset - @start_pos_of_line[l-1] end def line(offset) if offset >= @string_length raise "#{offset} is larger than the string size #{@string_length}" end line_index(offset) + 1 end # Find the index to the line where the given offset can be found. Assumes # the start_pos_of_line array has been extended so that offset is covered. def line_index(offset) index = nil for index in (0...(@start_pos_of_line.length)) if @start_pos_of_line[index] <= offset && @start_pos_of_line[index+1] > offset break end end index end end