Class: FastIgnore::GitignoreRuleBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/fast_ignore/gitignore_rule_builder.rb

Overview

rubocop:disable Metrics/ClassLength

Direct Known Subclasses

GitignoreIncludeRuleBuilder

Instance Method Summary collapse

Constructor Details

#initialize(rule, expand_path_with: nil) ⇒ GitignoreRuleBuilder

Returns a new instance of GitignoreRuleBuilder.



5
6
7
8
9
10
11
12
13
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 5

def initialize(rule, expand_path_with: nil)
  @re = ::FastIgnore::PathRegexpBuilder.new
  @s = ::FastIgnore::GitignoreRuleScanner.new(rule)

  @expand_path_with = expand_path_with
  @negation = false
  @anchored = false
  @dir_only = false
end

Instance Method Details

#anchored!Object



31
32
33
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 31

def anchored!
  @anchored ||= true
end

#blank!Object



19
20
21
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 19

def blank!
  throw :abort_build, []
end

#break!Object



15
16
17
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 15

def break!
  throw :break
end

#buildObject



198
199
200
201
202
203
204
205
206
207
208
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 198

def build
  catch :abort_build do
    blank! if @s.hash?
    negated! if @s.exclamation_mark?
    process_rule

    @anchored = false if @anchored == :never

    build_rule
  end
end

#build_ruleObject



189
190
191
192
193
194
195
196
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 189

def build_rule
  @re.prepend(prefix)
  if @negation
    ::FastIgnore::Matchers::AllowPathRegexp.new(@re.to_regexp, @anchored, @dir_only)
  else
    ::FastIgnore::Matchers::IgnorePathRegexp.new(@re.to_regexp, @anchored, @dir_only)
  end
end

#dir_only!Object



39
40
41
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 39

def dir_only!
  @dir_only = true
end

#emit_any_dirObject



52
53
54
55
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 52

def emit_any_dir
  anchored!
  @re.append_any_dir
end

#emit_dirObject



47
48
49
50
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 47

def emit_dir
  anchored!
  @re.append_dir
end

#emit_endObject



57
58
59
60
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 57

def emit_end
  @re.append_end_anchor
  break!
end

#expand_rule_path!Object



210
211
212
213
214
215
216
217
218
219
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 210

def expand_rule_path!
  anchored! unless @s.match?(/\*/) # rubocop:disable Performance/StringInclude # it's StringScanner#match?
  return unless @s.match?(%r{(?:[~/]|\.{1,2}/|.*/\.\./)})

  dir_only! if @s.match?(%r{.*/\s*\z})

  @s.string.replace(PathExpander.expand_path(@s.rest, @expand_path_with))
  @s.string.delete_prefix!(@expand_path_with)
  @s.pos = 0
end

#negated!Object



27
28
29
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 27

def negated!
  @negation = true
end

#never_anchored!Object



35
36
37
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 35

def never_anchored!
  @anchored = :never
end

#nothing_emitted?Boolean

Returns:

  • (Boolean)


43
44
45
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 43

def nothing_emitted?
  @re.empty?
end

#prefixObject



178
179
180
181
182
183
184
185
186
187
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 178

def prefix
  out = ::FastIgnore::PathRegexpBuilder.new

  if @anchored
    out.append_start_anchor
  else
    out.append_dir_or_start_anchor
  end
  out
end

#process_backslashObject



62
63
64
65
66
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 62

def process_backslash
  return unless @s.backslash?

  @re.append_escaped(@s.next_character) || unmatchable_rule!
end

#process_character_classObject

rubocop:disable Metrics/MethodLength



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 118

def process_character_class # rubocop:disable Metrics/MethodLength
  return unless @s.character_class_start?

  @re.append_character_class_open
  @re.append_character_class_negation if @s.character_class_negation?
  unmatchable_rule! if @s.character_class_end?

  until @s.character_class_end?
    next if process_character_class_range
    next if process_backslash
    next if @re.append_escaped(@s.character_class_literal)

    unmatchable_rule!
  end

  @re.append_character_class_close
end

#process_character_class_rangeObject



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 136

def process_character_class_range
  start = @s.character_class_range_start
  return unless start

  start = start.delete_prefix('\\')

  @re.append_escaped(start)

  finish = @s.character_class_range_end.delete_prefix('\\')

  return true unless start < finish

  @re.append_character_class_dash
  @re.append_escaped(finish)
end

#process_endObject



152
153
154
155
156
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 152

def process_end
  blank! if nothing_emitted?

  emit_end
end

#process_ruleObject

rubocop:disable Metrics/MethodLength, Metrics/AbcSize



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 158

def process_rule # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
  expand_rule_path! if @expand_path_with
  anchored! if @s.slash?

  catch :break do
    loop do
      next if process_backslash
      next if process_slash
      next if process_two_stars
      next @re.append_any_non_dir if @s.star?
      next @re.append_one_non_dir if @s.question_mark?
      next if process_character_class
      next if @re.append_escaped(@s.literal)
      next if @re.append_escaped(@s.significant_whitespace)

      process_end
    end
  end
end

#process_slashObject



86
87
88
89
90
91
92
93
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 86

def process_slash
  return unless @s.slash?
  return dir_only! if @s.end?
  return unmatchable_rule! if @s.slash?

  emit_dir
  process_star_end_after_slash
end

#process_star_end_after_slashObject

rubocop:disable Metrics/MethodLength



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 68

def process_star_end_after_slash # rubocop:disable Metrics/MethodLength
  if @s.star_end?
    @re.append_many_non_dir
    emit_end
  elsif @s.two_star_end?
    break!
  elsif @s.star_slash_end?
    @re.append_many_non_dir
    dir_only!
    emit_end
  elsif @s.two_star_slash_end?
    dir_only!
    break!
  else
    true
  end
end

#process_two_starsObject

rubocop:disable Metrics/MethodLength



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 95

def process_two_stars # rubocop:disable Metrics/MethodLength
  return unless @s.two_stars?
  return break! if @s.end?

  if @s.slash?
    if @s.end?
      @re.append_any_non_dir
      dir_only!
    elsif @s.slash?
      unmatchable_rule!
    else
      if nothing_emitted?
        never_anchored!
      else
        emit_any_dir
      end
      process_star_end_after_slash
    end
  else
    @re.append_any_non_dir
  end
end

#unmatchable_rule!Object



23
24
25
# File 'lib/fast_ignore/gitignore_rule_builder.rb', line 23

def unmatchable_rule!
  throw :abort_build, []
end