nrser 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1518d7452a93418bee72c151693e9f6499a41d6a
4
- data.tar.gz: 5139a61976788fb0bb8c397a40eec24d20c695d7
3
+ metadata.gz: 10930bb8b3998cc81f95333c8eb86a102262d84e
4
+ data.tar.gz: ff5057aead5992fe1d053e814afd120278b80a4c
5
5
  SHA512:
6
- metadata.gz: eb32f1311827dc0190db71434a798953282e3d258b3059aea03b86f6e56b57f871b7c5e8dcfe4b99844db1ec65b8782bf0c7ef3a099f1423ceeddcdf8b5ea16b
7
- data.tar.gz: 67aad6c06d72fb6123dc74294e113bd9f2862a9eca317e64277aae9fb68169e9c48dc5e9248788ca475e1d30f2314b7cdd6958ee12792880be4ccc859c5fa6b8
6
+ metadata.gz: f64f47ddbbb195eb13f072aec1f0beb8ff8299dbf9bc40838a2dcb078fd401fc03509c6566f497041ca0b3d5fc95f4b0baee0e7cb390e7238182a0e14e51ee50
7
+ data.tar.gz: ba2da8fe57e5d3e9f2c1439fa978957327982624c1a536b1bbf950901783d66808c44042d0f01f4ce7c8ec4333a93fb29904878c3165bc010dd099eddd864265
@@ -17,10 +17,11 @@ require 'yaml'
17
17
  require 'logger'
18
18
  require 'singleton'
19
19
 
20
-
21
20
  # Deps
22
21
  # -----------------------------------------------------------------------
23
22
  require 'hamster'
23
+ require 'semantic_logger'
24
+
24
25
 
25
26
  # Hi there!
26
27
  #
@@ -47,28 +48,25 @@ require 'hamster'
47
48
  # Enjoy!
48
49
  #
49
50
  module NRSER
50
-
51
- # Absolute, expanded path to the gem's root directory.
52
- #
53
- # @return [Pathname]
54
- #
55
- ROOT = ( Pathname.new(__FILE__).dirname / '..' ).expand_path
56
-
51
+ include SemanticLogger::Loggable
57
52
  end
58
53
 
59
- # 1. Load up extension mixins first - they don't invoke anything, just define
54
+ # 1. Load up version, which has {NRSER::ROOT} in it and depends on nothing
55
+ # else
56
+ require_relative './nrser/version'
57
+
58
+ # 2. Load up extension mixins first - they don't invoke anything, just define
60
59
  # methods
61
60
  require_relative './nrser/ext'
62
61
 
63
- # 2. Then load up the refinements, which either include the extension mixins
62
+ # 3. Then load up the refinements, which either include the extension mixins
64
63
  # or directly define proxies and methods (but don't execute them).
65
64
  #
66
65
  # This way everything else should be able to use them.
67
66
  #
68
67
  require_relative './nrser/refinements'
69
68
 
70
- # 3. Then everything else...
71
- require_relative './nrser/version'
69
+ # 4. Then everything else...
72
70
  require_relative './nrser/char'
73
71
  require_relative './nrser/errors'
74
72
  require_relative './nrser/no_arg'
@@ -3,3 +3,4 @@ module NRSER::Ext; end
3
3
  require_relative './ext/enumerable'
4
4
  require_relative './ext/tree'
5
5
  require_relative './ext/pathname'
6
+ require_relative './ext/string'
@@ -64,4 +64,10 @@ module NRSER::Ext::Enumerable
64
64
  NRSER.find_map self, *args, &block
65
65
  end
66
66
 
67
+ # See {NRSER.slice?}
68
+ def slice? *args, &block
69
+ NRSER.slice? self, *args, &block
70
+ end
71
+
72
+
67
73
  end # module NRSER::Ext::Enumerable
@@ -0,0 +1,62 @@
1
+ # Extension methods for {String}
2
+ #
3
+ module NRSER::Ext::String
4
+
5
+ def squish
6
+ NRSER.squish self
7
+ end
8
+
9
+
10
+ def unblock
11
+ NRSER.unblock self
12
+ end
13
+
14
+
15
+ def dedent
16
+ NRSER.dedent self
17
+ end
18
+
19
+
20
+ def indent *args
21
+ NRSER.indent self, *args
22
+ end
23
+
24
+
25
+ def truncate *args
26
+ NRSER.truncate self, *args
27
+ end
28
+
29
+
30
+ # See {NRSER.constantize}
31
+ def constantize
32
+ NRSER.constantize self
33
+ end
34
+
35
+ alias_method :to_const, :constantize
36
+
37
+
38
+ # @return [Pathname]
39
+ # Convert self into a {Pathname}
40
+ #
41
+ def to_pn
42
+ Pathname.new self
43
+ end
44
+
45
+
46
+ def whitespace?
47
+ NRSER.whitespace? self
48
+ end
49
+
50
+
51
+ # Calls {NRSER.ellipsis} on `self`.
52
+ def ellipsis *args
53
+ NRSER.ellipsis self, *args
54
+ end
55
+
56
+
57
+ # Calls {NRSER.words} on `self`
58
+ def words *args, &block
59
+ NRSER::words self, *args, &block
60
+ end
61
+
62
+ end # module NRSER::Ext::String
@@ -1,5 +1,6 @@
1
1
  require_relative './enumerable/find_map'
2
2
  require_relative './enumerable/find_all_map'
3
+ require_relative './enumerable/include_slice'
3
4
 
4
5
  module NRSER
5
6
 
@@ -0,0 +1,84 @@
1
+ require_relative './include_slice/array_include_slice'
2
+
3
+ using NRSER
4
+
5
+ module NRSER
6
+
7
+ # @!group Enumerable Functions
8
+
9
+ # See if an `enum` includes a `slice`, using an optional block to do custom
10
+ # matching.
11
+ #
12
+ # @example Order matters
13
+ # NRSER.slice? [1, 2, 3], [2, 3]
14
+ # # => true
15
+ #
16
+ # NRSER.slice? [1, 2, 3], [3, 2]
17
+ # # => false
18
+ #
19
+ # @example The empty slice is always present
20
+ # NRSER.slice? [1, 2, 3], []
21
+ # # => true
22
+ #
23
+ # NRSER.slice? [], []
24
+ # # => true
25
+ #
26
+ # @example Custom `&is_match` block to prefix-match
27
+ # NRSER.slice?(
28
+ # ['neil', 'mica', 'hudie'],
29
+ # ['m', 'h']
30
+ # ) { |enum_entry, slice_entry|
31
+ # enum_entry.start_with? slice_entry
32
+ # }
33
+ # # => true
34
+ #
35
+ # @note
36
+ # Right now, just forwards to {NRSER.array_include_slice?}, which requires
37
+ # that the {Enumerable}s support {Array}-like `#length` and `#slice`. I
38
+ # took a swing at the general case but it came out messy and only partially
39
+ # correct.
40
+ #
41
+ # @param [Enumerable] enum
42
+ # Sequence to search in.
43
+ #
44
+ # @param [Enumerable] slice
45
+ # Slice to search for.
46
+ #
47
+ # @return [Boolean]
48
+ # `true` if `enum` has a slice matching `slice`.
49
+ #
50
+ def self.include_slice? enum, slice, &is_match
51
+ # Check that both args are {Enumerable}
52
+ unless Enumerable === enum &&
53
+ Enumerable === slice
54
+ raise TypeError.new binding.erb <<-END
55
+ Both `enum` and `slice` must be {Enumerable}
56
+
57
+ enum (<%= enum.class.name %>):
58
+
59
+ <%= enum.pretty_inspect %>
60
+
61
+ slice (<%= slice.class.name %>):
62
+
63
+ <%= slice.pretty_inspect %>
64
+
65
+ END
66
+ end
67
+
68
+ if [enum, slice].all? { |e|
69
+ e.respond_to?( :length ) && e.respond_to?( :slice )
70
+ }
71
+ return array_include_slice? enum, slice, &is_match
72
+ end
73
+
74
+ raise NotImplementedError.new binding.erb <<-END
75
+ Sorry, but general {Enumerable} slice include has not been implemented
76
+
77
+ It's kinda complicated, or at least seems that way at first, so I'm
78
+ going to punt for now...
79
+ END
80
+ end
81
+
82
+ singleton_class.send :alias_method, :slice?, :include_slice?
83
+
84
+ end # module NRSER
@@ -0,0 +1,80 @@
1
+
2
+ module NRSER
3
+
4
+ # @!group Enumerable Functions
5
+
6
+ # Test slice inclusion when both the `slice` and the `enum` that we're
7
+ # going to look for it in support `#length` and `#slice`
8
+ # in the same manner that {Array} does (hence the name).
9
+ #
10
+ # This is much simpler and more efficient than the "general" {Enumerable}
11
+ # case where we can't necessarily find out how many entries are in the
12
+ # enumerables or really do much of anything with them except iterate through
13
+ # (at least, with my current grasp of {Enumerable} and {Enumerator} it
14
+ # seems painfully complex... in fact it may never terminate for infinite
15
+ # enumerables).
16
+ #
17
+ # @param [Enumerable<E> & #length & #slice] enum
18
+ # The {Enumerable} that we want test for `slice` inclusion. Must
19
+ # support `#length` and `#slice` like {Array} does.
20
+ #
21
+ # @param [Enumerable<S> & #length & #slice] slice
22
+ # The {Enumerable} slice that we want to see if `enum` includes. Must
23
+ # support `#length` and `#slice` like {Array} does.
24
+ #
25
+ # @param [Proc<(E, S)=>Boolean>] &is_match
26
+ # Optional {Proc} that accepts an entry from `enum` and an entry from
27
+ # `slice` and returns if they match.
28
+ #
29
+ # @return [Boolean]
30
+ # `true` if there is a slice of `enum` for which each entry matches the
31
+ # corresponding entry in `slice` according to `&is_match`.
32
+ #
33
+ def self.array_include_slice? enum, slice, &is_match
34
+ slice_length = slice.length
35
+
36
+ # Short-circuit on empty slice - it's *always* present
37
+ return true if slice_length == 0
38
+
39
+ enum_length = enum.length
40
+
41
+ # Short-circuit if slice is longer than enum since we can't possibly
42
+ # match
43
+ return false if slice_length > enum_length
44
+
45
+ # Create a default `#==` matcher if we weren't provided one.
46
+ if is_match.nil?
47
+ is_match = ->(enum_entry, slice_entry) {
48
+ enum_entry == slice_entry
49
+ }
50
+ end
51
+
52
+ enum.each_with_index do |enum_entry, enum_start_index|
53
+ # Compute index in `enum` that we would need to match up to
54
+ enum_end_index = enum_start_index + slice_length - 1
55
+
56
+ # Short-circuit if can't match (more slice entries than enum ones left)
57
+ return false if enum_end_index >= enum_length
58
+
59
+ # Create the slice to test against
60
+ enum_slice = enum[enum_start_index..enum_end_index]
61
+
62
+ # See if every entry in the slice from `enum` matches the corresponding
63
+ # one in `slice`
64
+ return true if enum_slice.zip( slice ).all?( &is_match )
65
+
66
+ # Otherwise, just continue on through `enum` looking for that first
67
+ # match until the number of `enum` entries left is too few for `slice`
68
+ # to possibly match
69
+ end
70
+
71
+ # We never matched the first `slice` entry to a `enum` entry (and `slice`
72
+ # had to be of length 1 so that the "too long" short-circuit never fired).
73
+ #
74
+ # So, we don't have a match.
75
+ false
76
+ end
77
+
78
+ singleton_class.send :alias_method, :array_slice?, :array_include_slice?
79
+
80
+ end # module NRSER
@@ -1,3 +1,4 @@
1
1
  require_relative './text/lines'
2
2
  require_relative './text/word_wrap'
3
3
  require_relative './text/indentation'
4
+ require_relative './text/words'
@@ -0,0 +1,23 @@
1
+ module NRSER
2
+
3
+ # Regexp {NRSER.words} uses to split strings. Probably not great but it's
4
+ # what I have for the moment.
5
+ #
6
+ # @return {Regexp}
7
+ #
8
+ SPLIT_WORDS_RE = /[\W_\-\/]+/
9
+
10
+
11
+ # Split a string into 'words' for word-based matching.
12
+ #
13
+ # @param [String] string
14
+ # Input string.
15
+ #
16
+ # @return [Array<String>]
17
+ # Array of non-empty words in `string`.
18
+ #
19
+ def self.words string
20
+ string.split(/[\W_\-\/]+/).reject { |w| w.empty? }
21
+ end # .words
22
+
23
+ end # module NRSER
@@ -0,0 +1,13 @@
1
+ # Namespace for new ideas I'm trying out. Totally unstable. May be gone
2
+ # completely tomorrow, etc.
3
+ #
4
+ # While, yes, the entire package is alpha, and there is no guarantee against
5
+ # change and breakage, I'm generally at a point where I'm trying to keep
6
+ # things that work mostly working.
7
+ #
8
+ # Stuff in here has no such consideration.
9
+ #
10
+ # There may be some tests for it, but they are going to be skipped by default
11
+ # and certainly won't prevent releases, if they're even run at all.
12
+ #
13
+ module NRSER::Labs; end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Requirements
4
+ # =======================================================================
5
+
6
+ # Stdlib
7
+ # -----------------------------------------------------------------------
8
+
9
+ # Deps
10
+ # -----------------------------------------------------------------------
11
+
12
+ # Project / Package
13
+ # -----------------------------------------------------------------------
14
+
15
+
16
+ # Refinements
17
+ # =======================================================================
18
+
19
+
20
+ # Declarations
21
+ # =======================================================================
22
+
23
+ module NRSER::Labs; end
24
+
25
+
26
+ # Definitions
27
+ # =======================================================================
28
+
29
+
30
+ # @todo document NRSER::Labs::Globlin class.
31
+ class NRSER::Labs::Globlin
32
+
33
+
34
+ # @todo document Matcher class.
35
+ class Matcher
36
+ def match entry
37
+ if entry.is_a?( NRSER::Globlin )
38
+
39
+ else
40
+
41
+ end
42
+ end
43
+ end # class Matcher
44
+
45
+
46
+ # Constants
47
+ # ======================================================================
48
+
49
+
50
+ # Class Methods
51
+ # ======================================================================
52
+
53
+
54
+ # Attributes
55
+ # ======================================================================
56
+
57
+
58
+ # Constructor
59
+ # ======================================================================
60
+
61
+ # Instantiate a new `NRSER:Globlin`.
62
+ def initialize split:, ignore: nil
63
+ @split = Array split
64
+
65
+
66
+ end # #initialize
67
+
68
+
69
+ # Instance Methods
70
+ # ======================================================================
71
+
72
+ def matcher_for search_string
73
+ @split.each
74
+ end
75
+
76
+
77
+ def find_only! search_string
78
+ matcher = matcher_for search_string
79
+
80
+ # Search entries that have the same seg count first
81
+ found = @seg_count_index[matcher.seg_count].find_all_map { |entry|
82
+ matcher.match entry
83
+ }
84
+
85
+ case found.length
86
+ when 0
87
+ # move on..
88
+ when 1
89
+ return found[0]
90
+ else
91
+ raise TooManyError.new found
92
+ end
93
+
94
+ # Ok, try slice matches for entries with *more* segments only
95
+ slice_matches = @seg_count_index.keys.
96
+ select { |count| count > matcher.seg_count }.
97
+ map { |key| @seg_count_index[key] }.
98
+ reduce( :+ ).
99
+ select { |entry|
100
+ matcher.match_slice entry
101
+ }
102
+
103
+
104
+ end
105
+
106
+ end # class NRSER::Labs::Globlin