Class: Cog::Helpers::FileScanner

Inherits:
Object
  • Object
show all
Defined in:
lib/cog/helpers/file_scanner.rb

Overview

Helper for scanning files for embed expansions

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename) ⇒ FileScanner

Returns a new instance of FileScanner.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/cog/helpers/file_scanner.rb', line 18

def initialize(filename)
  @filename = filename
  @f = File.open filename, 'r'
  @f = @f.binmode if @f.respond_to?(:binmode)
  @lines = []
  @mark = nil
  @cap_begin_pos = nil
  @cap_end_pos = nil
  @cap_end_lineno = nil
  @match = nil # The last match object
  @win_fudge = if RUBY_PLATFORM =~ /(mswin|mingw)/
    x = @f.readline.end_with? "\r\n"
    @f.seek 0
    @f.lineno = 0
    x ? 0 : 1
  else
    0
  end
end

Instance Attribute Details

#marked_line_numberFixnum (readonly)

Returns line number where mark! was called or -1 if mark! was not called.

Returns:

  • (Fixnum)

    line number where mark! was called or -1 if mark! was not called



79
80
81
# File 'lib/cog/helpers/file_scanner.rb', line 79

def marked_line_number
  @marked_line_number
end

#matchMatchData? (readonly)

Returns match data for the last matched pattern.

Returns:

  • (MatchData, nil)

    match data for the last matched pattern



15
16
17
# File 'lib/cog/helpers/file_scanner.rb', line 15

def match
  @match
end

Class Method Details

.scan(filename, pattern, opt = {}) {|scanner| ... } ⇒ Object?

Opens the given file for scanning.

Parameters:

  • filename (String)

    path to the file which will be scanned

  • pattern (Regexp)

    a pattern to test for

  • opt (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opt):

  • :occurrence (Fixnum) — default: 0

    0 for the first, 1 for the second, and so on

Yield Parameters:

Yield Returns:

  • (Object)

Returns:

  • (Object, nil)

    the return value of the block, or nil if the pattern was not found



51
52
53
54
55
56
57
58
59
60
# File 'lib/cog/helpers/file_scanner.rb', line 51

def self.scan(filename, pattern, opt={}, &block)
  s = new filename
  val = if s.read_until pattern, opt[:occurrence] || 0
    block.call s
  else
    nil
  end
  s.close
  val
end

Instance Method Details

#capture_until(pattern, opt = {}) ⇒ Boolean

Advances the file until the given pattern is encountered and captures lines as it reads. The line which matches the pattern will not be captured. Captured lines can later be recovered with captured_text

Parameters:

  • pattern (Regexp)

    a pattern to test for

  • opt (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opt):

  • :but_not (Array<Regexp>, Regexp) — default: nil

    if a line matching any of the provided patterns is found before the desired pattern :bad_pattern_found will be thrown

Returns:

  • (Boolean)

    whether or not the pattern was found



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/cog/helpers/file_scanner.rb', line 113

def capture_until(pattern, opt={})
  @cap_begin_pos = @f.pos - win_fudge
  but_not = opt[:but_not] || []
  but_not = [but_not] unless but_not.is_a?(Array)
  while line = @f.readline
    but_not.each do |bad_pattern|
      if bad_pattern =~ line
        return false
      end
    end
    return true if line =~ pattern
    @lines << line
    @cap_end_pos = @f.pos # win_fudge not needed here
    @cap_end_lineno = @f.lineno
  end
rescue EOFError
  false
end

#captured_textString

Returns text captured during capture_until. The last newline is stripped.

Returns:

  • (String)

    text captured during capture_until. The last newline is stripped



133
134
135
136
# File 'lib/cog/helpers/file_scanner.rb', line 133

def captured_text
  x = @lines.join('')
  x
end

#closeObject

Closes the scanned file, if it is not already closed



40
41
42
# File 'lib/cog/helpers/file_scanner.rb', line 40

def close
  @f.close unless @f.closed?
end

#insert_at_mark(value) ⇒ Boolean

Returns whether or not the operation succeeded.

Parameters:

  • value (String)

    value to be inserted into the file at the current position

Returns:

  • (Boolean)

    whether or not the operation succeeded



159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/cog/helpers/file_scanner.rb', line 159

def insert_at_mark(value)
  return false if @mark.nil?
  @f.seek 0
  @f.lineno = 0
  tmp.write @f.read(@mark)
  tmp.write value
  @f.readline # discard original
  tmp.write @f.read
  tmp.close
  close
  FileUtils.mv tmp_filename, @filename
  true
end

#mark!nil

Remember this position. A later call to insert_at_mark will insert at this marked position

Returns:

  • (nil)


68
69
70
71
# File 'lib/cog/helpers/file_scanner.rb', line 68

def mark!
  @mark = @f.pos - win_fudge
  @marked_line_number = @f.lineno + 1
end

#read_until(pattern, n = 0) ⇒ Boolean

Advances the file until the (n+1)th occurence of the given pattern is encountered, or the end of the file is reached

Parameters:

  • pattern (Regexp)

    a pattern to test for

  • n (Fixnum) (defaults to: 0)

    0 for the first, 1 for the second, and so on

Returns:

  • (Boolean)

    whether or not a match was found. Use #match to retrieve the match data



85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/cog/helpers/file_scanner.rb', line 85

def read_until(pattern, n=0)
  i = 0
  mark!
  while (line = @f.readline) && i <= n
    if @match = pattern.match(line)
      return true if i == n
      i += 1
    end
    mark!
  end
rescue EOFError
  unmark!
  false
end

#readline_matches?(pattern) ⇒ Boolean

Advances the file by one line

Parameters:

  • pattern (Regexp)

    a pattern to test for

Returns:

  • (Boolean)

    whether or not the next line matched the pattern



103
104
105
106
107
# File 'lib/cog/helpers/file_scanner.rb', line 103

def readline_matches?(pattern)
  !!(@f.readline =~ pattern)
rescue EOFError
  false
end

#replace_captured_text(value, opt = {}) ⇒ Boolean

Returns whether or not the operation succeeded.

Parameters:

  • value (String)

    value to replace the captured_text with

  • opt (Boolean) (defaults to: {})

    :once (false) if once, the cog delimiters will be removed

Returns:

  • (Boolean)

    whether or not the operation succeeded



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/cog/helpers/file_scanner.rb', line 141

def replace_captured_text(value, opt={})
  return false if @cap_begin_pos.nil? || @cap_end_pos.nil?
  @f.seek 0
  @f.lineno = 0
  tmp.write @f.read(opt[:once] ? @mark : @cap_begin_pos)
  tmp.write value
  @f.seek @cap_end_pos
  @f.lineno = @cap_end_lineno
  @f.readline if opt[:once]
  tmp.write @f.read
  tmp.close
  close
  FileUtils.mv tmp_filename, @filename
  true
end

#unmark!Object



73
74
75
76
# File 'lib/cog/helpers/file_scanner.rb', line 73

def unmark!
  @mark = nil
  @marked_line_number = -1
end

#win_fudgeObject



62
63
64
# File 'lib/cog/helpers/file_scanner.rb', line 62

def win_fudge
  (@f.lineno - 1) * @win_fudge
end