Class: NRSER::Sys::Env::Path

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/nrser/sys/env/path.rb

Constant Summary collapse

SEPARATOR =

Character used to separate path entries in string format.

Returns:

':'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Enumerable

#assoc_by, #assoc_to, #count_by, #enumerate_as_values, #find_bounded, #find_map, #find_only, #only, #only!, #slice?, #try_find

Constructor Details

#initialize(source, env_key: nil) ⇒ Path

Instantiate a new ‘NRSER::Env::Path`.



163
164
165
166
167
# File 'lib/nrser/sys/env/path.rb', line 163

def initialize source, env_key: nil
  @env_key = env_key.to_s.freeze
  @source = source.dup.freeze
  @value = self.class.normalize source
end

Instance Attribute Details

#env_keynil | String (readonly)

Key for the value in ‘ENV` that the object represents. This is set when loading from `ENV` and used to know where to write when saving back to it.

Returns:



142
143
144
# File 'lib/nrser/sys/env/path.rb', line 142

def env_key
  @env_key
end

#sourcenil | String | #each_index (readonly)

The object that was originally provided at construction.

Returns:

  • (nil | String | #each_index)


149
150
151
# File 'lib/nrser/sys/env/path.rb', line 149

def source
  @source
end

#valueHamster::Vector<String> (readonly)

The actual internal list of paths.

Returns:



156
157
158
# File 'lib/nrser/sys/env/path.rb', line 156

def value
  @value
end

Class Method Details

.from_ENV(env_key) ⇒ Object



129
130
131
# File 'lib/nrser/sys/env/path.rb', line 129

def self.from_ENV env_key
  new ENV[env_key.to_s], env_key: env_key
end

.matches_pattern?(path, *patterns) ⇒ Boolean

See if a ‘path` matches any of `patterns`.

Short-circuits as soon as a match is found (so patterns may not all be tested).

Parameters:

  • path (String)

    Path to test against.

  • patterns (Array<String | Proc<String=>Boolean> | Regexp>)

    Patterns to test:

    • ‘String` - test if it and `path` are equal (`==`)

    • ‘Proc<String=>Boolean>` - call with `path` and evaluate result as Boolean.

    • ‘Regexp` - test if it matches `path` (`=~`)

Returns:

  • (Boolean)

    ‘true` if any of `patterns` match `path`.



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/nrser/sys/env/path.rb', line 108

def self.matches_pattern? path, *patterns
  patterns.any? do |pattern|
    case pattern
    when String
      path == pattern
    when Proc
      pattern.call path
    when Regexp
      path =~ pattern
    else
      raise TypeError.new binding.erb <<-END
        Each `*patterns` arg should be String, Proc or Regexp, found:
        
            <%= pattern.pretty_inspect %>
        
      END
    end
  end
end

.normalize(source) ⇒ return_type

TODO:

Document normalize method.

Returns @todo Document return value.

Parameters:

  • source (nil | String | #each_index)

    Path source.

Returns:

  • (return_type)

    @todo Document return value.



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
# File 'lib/nrser/sys/env/path.rb', line 54

def self.normalize source
  paths = if source.nil?
    []
  
  elsif source.is_a?( String )
    source.to_s.split SEPARATOR
    
  elsif NRSER.array_like?( source )
    # Flatten it if supported
    source = source.flatten if source.respond_to?( :flatten )
    
    # Stringify each segment, split them and concat results
    source.flat_map { |entry| entry.to_s.split SEPARATOR }
  
  else
    raise ArgumentError.new binding.erb <<-END
      Expected a string or an "array-like" source, found:
      
          <%= source.pretty_inspect %>
      
    END
  end
  
  Hamster::Vector.new paths.
    # Get rid of empty paths
    reject( &:empty? ).
    # Get rid of duplicates
    uniq.
    # Freeze all the strings
    map( &:freeze )
end

Instance Method Details

#append(source) ⇒ self

Parameters:

  • source (nil | String | #each_index)

    Path source.

Returns:

  • (self)


197
198
199
200
201
202
203
204
205
206
207
# File 'lib/nrser/sys/env/path.rb', line 197

def append source
  # Normalize the new source to a flat array of strings
  paths = self.class.normalize source
  
  # The new value is the current paths with the new paths appended, with
  # any paths in the current path removed from the new ones (de-duplication)
  @value = (@value + paths).uniq
  
  # Return self for chain-ability
  self
end

#each(&block) ⇒ self, Enumerator

Support for Enumerable mixin. Yields each path in order.

Specifically, proxies to Hamster::Vector#each

Parameters:

  • block (nil | Proc<(String)=>*>)

    When present, block will be called once for each string path in this object. First path is most prominent, down to least last.

Returns:

  • (self)

    When ‘&block` is provided.

  • (Enumerator)

    When ‘&block` is omitted.

See Also:



265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/nrser/sys/env/path.rb', line 265

def each &block
  if block
    # Proxy for yielding
    @value.each &block
    
    # Return self for chain-ability
    self
  else
    # Return the {Enumerator} from the vector
    @value.each
  end
end

#insert(source, before: nil, after: nil) ⇒ Object



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/nrser/sys/env/path.rb', line 213

def insert source, before: nil, after: nil
  paths = self.class.normalize source
  
  before_index = if before
    @value.find_index do |path|
      self.class.matches_pattern? path, *before
    end
  end
  
  after_index = if after
    index = @value.rindex { |path| self.class.matches_pattern? path, *after }
    index += 1 if index
  end
  
  insert_index = if after_index && before_index
    # Make sure the conditions don't conflict with each other
    if after_index > before_index
      raise "Conflicting bounds!"
    end
    
    # Insert as far "down" the path as allowed
    [before_index, after_index].max
  else
    # Use the one that is not `nil`, or insert at the end if they both are
    before_index || after_index || @value.length
  end
  
  @value = @value.insert( insert_index, *paths ).uniq
  
  self
end

#prepend(source) ⇒ self Also known as: unshift, >>, push, <<

Parameters:

  • source (nil | String | #each_index)

    Path source.

Returns:

  • (self)


177
178
179
180
181
182
183
184
185
186
187
# File 'lib/nrser/sys/env/path.rb', line 177

def prepend source
  # Normalize the new source to a flat array of strings
  paths = self.class.normalize source
  
  # The new value is the normalized paths followed by the current paths
  # with the new ones removed (de-duplication)
  @value = (paths + @value).uniq
  
  # Return self for chain-ability
  self
end

#to_aArray<String>

The string paths in a new stdlib ‘Array`. Mutating this array will have no effect on the Env::Path data.

Returns:



293
294
295
# File 'lib/nrser/sys/env/path.rb', line 293

def to_a
  @value.to_a
end

#to_sString

The paths joined with ‘:’.

Returns:



283
284
285
# File 'lib/nrser/sys/env/path.rb', line 283

def to_s
  @value.join SEPARATOR
end