Class: PatternPatch::Utilities

Inherits:
Object
  • Object
show all
Defined in:
lib/pattern_patch/utilities.rb

Class Method Summary collapse

Class Method Details

.apply_patch(contents, regexp, text, global, mode, offset) ⇒ Object

Add the specified text after the specified pattern. Returns a modified copy of the string.

:contents: A string to modify, e.g. the contents of a file :regexp: A regular expression specifying a pattern to be matched :text: Text to be appended to the specified pattern :global: Boolean flag. If true, patch all occurrences of the regex. :mode: :append, :prepend or :replace to specify how to apply the patch :offset: Starting position for matching



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/pattern_patch/utilities.rb', line 13

def apply_patch(contents, regexp, text, global, mode, offset)
  search_position = offset
  while (matches = regexp.match(contents, search_position))
    patched_pattern =
      case mode
      when :append
        "#{matches[0]}#{text.apply_matches matches}"
      when :prepend
        "#{text.apply_matches matches}#{matches[0]}"
      when :replace
        matches[0].sub regexp, text
      else
        raise ArgumentError, "Invalid mode argument. Specify :append, :prepend or :replace."
      end

    contents = "#{matches.pre_match}#{patched_pattern}#{matches.post_match}"
    break unless global
    search_position = matches.pre_match.length + patched_pattern.length
  end
  contents
end

.revert_patch(contents, regexp, text, global, mode, offset) ⇒ Object

Reverts a patch. Use the same arguments that were supplied to apply_patch. The mode argument can only be :append or :prepend. Patches using :replace cannot be reverted. Returns a modified copy of the string.

:contents: A string to modify, e.g. the contents of a file :regexp: A regular expression specifying a pattern to be matched :text: Text to be appended to the specified pattern :global: Boolean flag. If true, patch all occurrences of the regex. :mode: :append or :prepend. :replace patches cannot be reverted automatically. :offset: Starting position for matching



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
# File 'lib/pattern_patch/utilities.rb', line 46

def revert_patch(contents, regexp, text, global, mode, offset)
  search_position = offset
  regexp_string = regexp.to_s

  patched_regexp =
    case mode
    when :append
      /#{regexp_string}#{text}/m
    when :prepend
      # TODO: Capture groups aren't currently revertible in :prepend mode.
      # This patched regexp can turn into something like /\1.*(\d+)/.
      # The capture group reference cannot occur in the regexp before definition
      # of the group. This would have to be transformed to something like
      # /(\d+).*\1/. Patch reversion is probably not a major use case right
      # now, so ignore for the moment.
      /#{text}#{regexp_string}/m
    else
      raise ArgumentError, "Invalid mode argument. Specify :append or :prepend."
    end

  while (matches = patched_regexp.match(contents, search_position))
    reverted_text = matches[0].sub(text.apply_matches(matches), '')
    contents = "#{matches.pre_match}#{reverted_text}#{matches.post_match}"
    break unless global
    search_position = matches.pre_match.length + reverted_text.length
  end

  contents
end