1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
module Tins
class LinesFile
module LineExtension
attr_reader :line_number
def filename
lines_file.filename.dup
end
end
def self.for_filename(filename, line_number = nil)
obj = new(File.readlines(filename), line_number)
obj.filename = filename
obj
end
def self.for_file(file, line_number = nil)
obj = new(file.readlines, line_number)
obj.filename = file.path
obj
end
def self.for_lines(lines, line_number = nil)
new(lines, line_number)
end
def initialize(lines, line_number = nil)
@lines = lines
@lines.each_with_index do |line, i|
line.extend LineExtension
line.instance_variable_set :@line_number, i + 1
line.instance_variable_set :@lines_file, self
end
instance_variable_set :@line_number, line_number || (@lines.empty? ? 0 : 1)
end
attr_accessor :filename
attr_reader :line_number
def rewind
self.line_number = 1
self
end
def next!
old = line_number
self.line_number += 1
line_number > old ? self : nil
end
def previous!
old = line_number
self.line_number -= 1
line_number < old ? self : nil
end
def line_number=(number)
number = number.to_i
if number > 0 && number <= last_line_number
@line_number = number
end
end
def last_line_number
@lines.size
end
def empty?
@lines.empty?
end
def each(&block)
empty? and return self
old_line_number = line_number
1.upto(last_line_number) do |number|
self.line_number = number
block.call(line)
end
self
ensure
self.line_number = old_line_number
end
include Enumerable
def line
index = line_number - 1
@lines[index] if index >= 0
end
def file_linenumber
"#{filename}:#{line_number}"
end
def match_backward(regexp, previous_after_match = false)
begin
if line =~ regexp
previous_after_match and previous!
return $~.captures
end
end while previous!
end
def match_forward(regexp, next_after_match = false)
begin
if line =~ regexp
next_after_match and next!
return $~.captures
end
end while next!
end
def to_s
"#{line_number} #{line.chomp}"
end
def inspect
"#<#{self.class}: #{to_s.inspect}>"
end
end
end
require 'tins/alias'
|