nrser 0.3.9 → 0.3.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nrser/char/alpha_numeric_sub.rb +9 -19
  3. data/lib/nrser/char/special.rb +5 -5
  4. data/lib/nrser/core_ext/array.rb +36 -13
  5. data/lib/nrser/core_ext/enumerable.rb +1 -0
  6. data/lib/nrser/core_ext/enumerable/find_map.rb +1 -1
  7. data/lib/nrser/core_ext/hash/bury.rb +3 -0
  8. data/lib/nrser/core_ext/hash/extract_values_at.rb +2 -2
  9. data/lib/nrser/core_ext/method/full_name.rb +1 -1
  10. data/lib/nrser/core_ext/module/method_objects.rb +1 -1
  11. data/lib/nrser/core_ext/module/source_locations.rb +27 -15
  12. data/lib/nrser/core_ext/object/lazy_var.rb +1 -1
  13. data/lib/nrser/core_ext/pathname.rb +67 -12
  14. data/lib/nrser/core_ext/pathname/subpath.rb +86 -0
  15. data/lib/nrser/core_ext/string.rb +28 -1
  16. data/lib/nrser/core_ext/symbol.rb +11 -12
  17. data/lib/nrser/errors/README.md +154 -0
  18. data/lib/nrser/errors/attr_error.rb +146 -53
  19. data/lib/nrser/errors/count_error.rb +61 -12
  20. data/lib/nrser/errors/nicer_error.rb +42 -71
  21. data/lib/nrser/errors/value_error.rb +53 -58
  22. data/lib/nrser/functions.rb +0 -2
  23. data/lib/nrser/functions/enumerable.rb +5 -17
  24. data/lib/nrser/functions/enumerable/associate.rb +14 -5
  25. data/lib/nrser/functions/enumerable/find_all_map.rb +1 -1
  26. data/lib/nrser/functions/enumerable/include_slice/array_include_slice.rb +1 -1
  27. data/lib/nrser/functions/hash/bury.rb +2 -12
  28. data/lib/nrser/functions/merge_by.rb +2 -2
  29. data/lib/nrser/functions/module/method_objects.rb +2 -2
  30. data/lib/nrser/functions/path.rb +185 -165
  31. data/lib/nrser/functions/path/normalized.rb +84 -0
  32. data/lib/nrser/functions/string.rb +4 -4
  33. data/lib/nrser/functions/text/README.md +4 -0
  34. data/lib/nrser/functions/text/format.rb +53 -0
  35. data/lib/nrser/functions/text/indentation.rb +6 -6
  36. data/lib/nrser/functions/text/word_wrap.rb +2 -2
  37. data/lib/nrser/functions/tree/map_leaves.rb +3 -3
  38. data/lib/nrser/functions/tree/map_tree.rb +2 -2
  39. data/lib/nrser/functions/tree/transform.rb +1 -18
  40. data/lib/nrser/gem_ext/README.md +4 -0
  41. data/lib/nrser/labs/README.md +8 -0
  42. data/lib/nrser/labs/config.rb +163 -0
  43. data/lib/nrser/labs/i8.rb +49 -159
  44. data/lib/nrser/labs/i8/struct.rb +167 -0
  45. data/lib/nrser/labs/i8/struct/hash.rb +140 -0
  46. data/lib/nrser/labs/i8/struct/vector.rb +149 -0
  47. data/lib/nrser/labs/i8/surjection.rb +211 -0
  48. data/lib/nrser/labs/lots/consumer.rb +19 -0
  49. data/lib/nrser/labs/lots/parser.rb +21 -1
  50. data/lib/nrser/labs/stash.rb +4 -4
  51. data/lib/nrser/log.rb +25 -21
  52. data/lib/nrser/log/appender/sync.rb +15 -11
  53. data/lib/nrser/log/formatters/color.rb +0 -3
  54. data/lib/nrser/log/formatters/mixin.rb +4 -4
  55. data/lib/nrser/log/logger.rb +54 -6
  56. data/lib/nrser/log/mixin.rb +2 -1
  57. data/lib/nrser/log/plugin.rb +6 -6
  58. data/lib/nrser/log/types.rb +46 -29
  59. data/lib/nrser/mean_streak.rb +0 -8
  60. data/lib/nrser/mean_streak/document.rb +1 -4
  61. data/lib/nrser/message.rb +3 -3
  62. data/lib/nrser/meta/README.md +4 -0
  63. data/lib/nrser/meta/lazy_attr.rb +2 -2
  64. data/lib/nrser/meta/source/location.rb +1 -1
  65. data/lib/nrser/props.rb +34 -3
  66. data/lib/nrser/props/class_methods.rb +2 -1
  67. data/lib/nrser/props/instance_methods.rb +9 -9
  68. data/lib/nrser/props/metadata.rb +4 -12
  69. data/lib/nrser/props/mutable/stash.rb +5 -2
  70. data/lib/nrser/props/prop.rb +10 -19
  71. data/lib/nrser/rspex.rb +1 -20
  72. data/lib/nrser/rspex/example_group/describe_attribute.rb +3 -0
  73. data/lib/nrser/rspex/example_group/describe_called_with.rb +9 -4
  74. data/lib/nrser/rspex/example_group/describe_case.rb +1 -0
  75. data/lib/nrser/rspex/example_group/describe_class.rb +2 -0
  76. data/lib/nrser/rspex/example_group/describe_group.rb +1 -1
  77. data/lib/nrser/rspex/example_group/describe_instance.rb +3 -1
  78. data/lib/nrser/rspex/example_group/describe_message.rb +1 -1
  79. data/lib/nrser/rspex/example_group/describe_method.rb +64 -30
  80. data/lib/nrser/rspex/example_group/describe_response_to.rb +1 -1
  81. data/lib/nrser/rspex/example_group/describe_section.rb +4 -1
  82. data/lib/nrser/rspex/example_group/describe_sent_to.rb +1 -1
  83. data/lib/nrser/rspex/example_group/describe_setup.rb +1 -0
  84. data/lib/nrser/rspex/example_group/describe_source_file.rb +1 -1
  85. data/lib/nrser/rspex/example_group/describe_spec_file.rb +4 -2
  86. data/lib/nrser/rspex/example_group/describe_when.rb +2 -1
  87. data/lib/nrser/rspex/example_group/describe_x.rb +5 -5
  88. data/lib/nrser/rspex/format.rb +0 -15
  89. data/lib/nrser/sugar/method_missing_forwarder.rb +3 -3
  90. data/lib/nrser/sys/env/path.rb +2 -28
  91. data/lib/nrser/types.rb +63 -12
  92. data/lib/nrser/types/README.md +76 -0
  93. data/lib/nrser/types/arrays.rb +192 -137
  94. data/lib/nrser/types/attributes.rb +269 -0
  95. data/lib/nrser/types/booleans.rb +134 -83
  96. data/lib/nrser/types/bounded.rb +110 -47
  97. data/lib/nrser/types/collections.rb +119 -0
  98. data/lib/nrser/types/combinators.rb +283 -196
  99. data/lib/nrser/types/doc/display_table.md +66 -0
  100. data/lib/nrser/types/eqiuvalent.rb +91 -0
  101. data/lib/nrser/types/errors/check_error.rb +5 -11
  102. data/lib/nrser/types/errors/from_string_error.rb +3 -3
  103. data/lib/nrser/types/factory.rb +287 -20
  104. data/lib/nrser/types/hashes.rb +227 -179
  105. data/lib/nrser/types/in.rb +73 -36
  106. data/lib/nrser/types/is.rb +67 -60
  107. data/lib/nrser/types/is_a.rb +141 -84
  108. data/lib/nrser/types/labels.rb +45 -16
  109. data/lib/nrser/types/maybe.rb +6 -3
  110. data/lib/nrser/types/nil.rb +64 -27
  111. data/lib/nrser/types/not.rb +92 -34
  112. data/lib/nrser/types/numbers.rb +224 -169
  113. data/lib/nrser/types/pairs.rb +113 -89
  114. data/lib/nrser/types/paths.rb +250 -137
  115. data/lib/nrser/types/responds.rb +167 -89
  116. data/lib/nrser/types/selector.rb +234 -0
  117. data/lib/nrser/types/shape.rb +136 -65
  118. data/lib/nrser/types/strings.rb +189 -63
  119. data/lib/nrser/types/symbols.rb +83 -33
  120. data/lib/nrser/types/top.rb +89 -0
  121. data/lib/nrser/types/tuples.rb +134 -98
  122. data/lib/nrser/types/type.rb +617 -505
  123. data/lib/nrser/types/when.rb +123 -98
  124. data/lib/nrser/types/where.rb +182 -91
  125. data/lib/nrser/version.rb +1 -1
  126. data/spec/lib/nrser/core_ext/pathname/subpath_spec.rb +22 -0
  127. data/spec/lib/nrser/errors/attr_error_spec.rb +68 -0
  128. data/spec/lib/nrser/errors/count_error_spec.rb +69 -0
  129. data/spec/lib/nrser/functions/path/normalize_path_spec.rb +35 -0
  130. data/spec/lib/nrser/functions/tree/map_tree_spec.rb +74 -96
  131. data/spec/lib/nrser/functions/tree/transform_spec.rb +11 -11
  132. data/spec/lib/nrser/labs/config_spec.rb +22 -0
  133. data/spec/lib/nrser/labs/i8/struct_spec.rb +39 -0
  134. data/spec/lib/nrser/types/display_spec.rb +50 -0
  135. data/spec/lib/nrser/types/paths_spec.rb +16 -10
  136. data/spec/lib/nrser/types/selector_spec.rb +125 -0
  137. data/spec/spec_helper.rb +4 -5
  138. metadata +105 -22
  139. data/lib/nrser/types/any.rb +0 -41
  140. data/lib/nrser/types/attrs.rb +0 -213
  141. data/lib/nrser/types/trees.rb +0 -42
@@ -1,109 +1,133 @@
1
- # Requirements
2
- # =======================================================================
3
-
4
- # Stdlib
5
- # -----------------------------------------------------------------------
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
6
3
 
7
- # Deps
8
- # -----------------------------------------------------------------------
4
+ # Requirements
5
+ # ========================================================================
9
6
 
10
7
  # Project / Package
11
- # -----------------------------------------------------------------------
8
+ # ------------------------------------------------------------------------
9
+
12
10
  require 'nrser/core_ext/hash'
13
11
 
14
12
  require_relative './combinators'
13
+ require_relative './attributes'
15
14
  require_relative './tuples'
16
15
 
17
16
 
18
- # Refinements
19
- # =======================================================================
17
+ # Namespace
18
+ # ========================================================================
20
19
 
20
+ module NRSER
21
+ module Types
21
22
 
22
- # Declarations
23
+
24
+ # Definitions
23
25
  # =======================================================================
24
26
 
25
- module NRSER; end
27
+ # @!group Pairs Type Factories
28
+ # ----------------------------------------------------------------------------
26
29
 
27
30
 
28
- # Definitions
29
- # =======================================================================
31
+ #@!method self.ArrayPair key: self.Top, value: self.Top, **options
32
+ # Type for key/value pairs encoded as a {.Tuple} ({::Array}) of length 2.
33
+ #
34
+ # @param [TYPE] key
35
+ # Key type. Made into a type by {NRSER::Types.make} if it's not already.
36
+ #
37
+ # @param [TYPE] value
38
+ # Value type. Made into a type by {NRSER::Types.make} if it's not already.
39
+ #
40
+ # @param [Hash] options
41
+ # Passed to {Type#initialize}.
42
+ #
43
+ # @return [Type]
44
+ #
45
+ def_type :ArrayPair,
46
+ default_name: false,
47
+ parameterize: [ :key, :value ],
48
+ &->( key: self.Top, value: self.Top, **options ) do
49
+ tuple \
50
+ key,
51
+ value,
52
+ **options
53
+ end # .ArrayPair
30
54
 
31
- module NRSER::Types
32
-
33
- # Type for key/value pairs encoded as a {.tuple} (Array) of length 2.
34
- #
35
- def_factory(
36
- :array_pair,
37
- ) do |name: 'ArrayPair', key: any, value: any, **options|
38
- unless options.key? :name
39
- options[:name] = if key == any && value == any
40
- 'ArrayPair'
41
- else
42
- key = NRSER::Types.make key
43
- value = NRSER::Types.make value
44
-
45
- "ArrayPair<#{ key.name }, #{ value.name }>"
46
- end
47
- end
48
-
49
- tuple \
50
- key,
51
- value,
52
- # name: name,
53
- **options
54
- end # .array_pair
55
-
55
+
56
+ # @!method self.HashPair key: self.Top, value: self.Top, **options
57
+ #
58
+ # Type whose members are single a key/value pairs encoded as {::Hash} instances
59
+ # with a single entry (`::Hash#length==1`).
60
+ #
61
+ # @param [TYPE] key
62
+ # Key type. Made into a type by {NRSER::Types.make} if it's not already.
63
+ #
64
+ # @param [TYPE] value
65
+ # Value type. Made into a type by {NRSER::Types.make} if it's not already.
66
+ #
67
+ # @param [Hash] options
68
+ # Passed to {Type#initialize}.
69
+ #
70
+ # @return [Type]
71
+ #
72
+ def_type :HashPair,
73
+ default_name: false,
74
+ parameterize: [ :key, :value ],
75
+ &->( key: self.Top, value: self.Top, **options ) do
76
+ key = self.make key
77
+ value = self.make value
78
+
79
+ options[:name] ||= "Hash<(#{ key.name }, #{ value.name })>"
56
80
 
57
- # Type for key/value pairs encoded as {Hash} with a single entry.
58
- #
59
- # @param [String] name:
60
- # Name to give the new type.
61
- #
62
- # @param [Hash] **options
63
- # Other options to pass to
64
- #
65
- def_factory(
66
- :hash_pair,
67
- ) do |key: any, value: any, **options|
68
- unless options.key? :name
69
- options[:name] = if key == any && value == any
70
- 'HashPair'
71
- else
72
- key = NRSER::Types.make key
73
- value = NRSER::Types.make value
74
-
75
- "HashPair<#{ key.name }, #{ value.name }>"
76
- end
77
- end
78
-
79
- intersection \
80
- hash_type( keys: key, values: value ),
81
- length( 1 ),
82
- # name: name,
83
- **options
84
- end # .hash_pair
81
+ options[:symbolic] ||= "(#{ key.symbolic }=>#{ value.symbolic })"
85
82
 
83
+ intersection \
84
+ self.Hash( keys: key, values: value ),
85
+ self.Length( 1 ),
86
+ **options
87
+ end # .HashPair
88
+
89
+
90
+ #@!method self.Pair key: self.Top, value: self.Top, **options
91
+ # A key/value pair, which can be encoded as an Array of length 2 or a
92
+ # Hash of length 1.
93
+ #
94
+ # @param [TYPE] key
95
+ # Key type. Made into a type by {NRSER::Types.make} if it's not already.
96
+ #
97
+ # @param [TYPE] value
98
+ # Value type. Made into a type by {NRSER::Types.make} if it's not already.
99
+ #
100
+ # @param [Hash] options
101
+ # Passed to {Type#initialize}.
102
+ #
103
+ # @return [Type]
104
+ #
105
+ def_type :Pair,
106
+ default_name: false,
107
+ parameterize: [ :key, :value ],
108
+ &->( key: self.Top, value: self.Top, **options ) do
109
+ key = self.make key
110
+ value = self.make value
86
111
 
87
- # A key/value pair, which can be encoded as an Array of length 2 or a
88
- # Hash of length 1.
89
- #
90
- #
91
- def_factory :pair do |key: any, value: any, **options|
92
- unless options.key? :name
93
- options[:name] = if key == any && value == any
94
- 'Pair'
95
- else
96
- key = NRSER::Types.make key
97
- value = NRSER::Types.make value
98
-
99
- "Pair<#{ key.name }, #{ value.name }>"
100
- end
101
- end
102
-
103
- union \
104
- array_pair( key: key, value: value ),
105
- hash_pair( key: key, value: value ),
106
- **options
107
- end # #pair
112
+ options[:name] ||= if key == self.Top && value == self.Top
113
+ "Pair"
114
+ else
115
+ "Pair<#{ key.name }, #{ value.name }>"
116
+ end
117
+
118
+ options[:symbolic] ||= "(#{ key.symbolic }, #{ value.symbolic })"
108
119
 
109
- end # module NRSER::Types
120
+ union \
121
+ self.ArrayPair( key: key, value: value ),
122
+ self.HashPair( key: key, value: value ),
123
+ **options
124
+ end # .Pair
125
+
126
+ # @!endgroup Pairs Type Factories # ******************************************
127
+
128
+
129
+ # /Namespace
130
+ # ========================================================================
131
+
132
+ end # module NRSER
133
+ end #module Types
@@ -1,153 +1,266 @@
1
1
  # Requirements
2
2
  # =======================================================================
3
3
 
4
- # Stdlib
5
- # -----------------------------------------------------------------------
6
-
7
- # Deps
8
- # -----------------------------------------------------------------------
9
-
10
4
  # Project / Package
11
5
  # -----------------------------------------------------------------------
12
6
 
13
7
  require 'nrser/core_ext/pathname'
8
+ require 'nrser/functions/path/normalized'
14
9
 
15
10
  require_relative './is_a'
16
11
  require_relative './where'
17
12
  require_relative './combinators'
18
13
 
19
14
 
15
+ # Namespace
16
+ # ========================================================================
17
+
18
+ module NRSER
19
+ module Types
20
+
21
+
20
22
  # Definitions
21
23
  # =======================================================================
22
24
 
23
- module NRSER::Types
24
-
25
- # @!group Type Factory Functions
26
-
27
- def_factory :pathname do |to_data: :to_s, **options|
28
- is_a \
29
- Pathname,
30
- from_s: ->( string ) { Pathname.new string },
31
- to_data: to_data,
32
- **options
33
- end
34
-
35
-
36
- # A type satisfied by a {Pathname} instance that's not empty (meaning it's
37
- # string representation is not empty).
38
- def_factory :non_empty_pathname do |name: 'NonEmptyPathname', **options|
39
- all_of \
40
- pathname,
41
- attrs( to_s: non_empty_str ),
42
- name: name,
43
- **options
44
- end
45
-
46
-
47
- # @!method
48
- # A path is a non-empty {String} or {Pathname}.
49
- #
50
- # @param **options see NRSER::Types::Type#initialize
51
- #
52
- # @return [NRSER::Types::Type]
53
- #
54
- def_factory :path do |name: 'Path', **options|
55
- one_of \
56
- non_empty_str,
57
- non_empty_pathname,
58
- name: name,
59
- **options
60
- end # #path
61
-
62
-
63
- def_factory :posix_path_segment,
64
- aliases: [:path_segment, :path_seg] \
65
- do |name: 'POSIXPathSegment', **options|
66
- all_of \
67
- non_empty_str,
68
- respond( to: [:include?, '/'], with: false ),
69
- name: name,
70
- **options
71
- end
72
-
73
-
74
- # An absolute {#path}.
75
- #
76
- # @param **options see NRSER::Types::Type#initialize
77
- #
78
- def_factory :abs_path do |name: 'AbsPath', **options|
79
- intersection \
80
- path,
81
- # Weirdly, there is no {File.absolute?}..
82
- attrs( to_pn: attrs( absolute?: true ) ),
83
- name: name,
84
- from_s: ->( s ) { File.expand_path s },
85
- **options
86
- end
87
-
88
-
89
- # A relative path.
90
- #
91
- # @todo
92
- # Quick addition, not sure if it's totally right with regard to tilde
93
- # paths and such.
94
- #
95
- def_factory :rel_path do |name: 'RelPath', **options|
96
- intersection \
97
- path,
98
- ~abs_path,
99
- name: name,
100
- **options
101
- end
102
-
103
-
104
- # A {NRSER::Types.path} that is a directory.
105
- #
106
- # @param [Hash] **options
107
- # Construction options passed to {NRSER::Types::Type#initialize}.
108
- #
109
- # @return [NRSER::Types::Type]
110
- #
111
- def_factory :dir_path do |name: 'DirPath', **options|
112
- intersection \
113
- path,
114
- # TODO How to change this from {.where}?
115
- where { |path| File.directory? path },
116
- name: name,
117
- **options
118
- end # #dir_path
119
-
120
-
121
- # Absolute {.path} to a directory (both an {.abs_path} and an {.dir_path}).
122
- #
123
- # @param name: (see NRSER::Types::Type#initialize)
124
- #
125
- # @param **options
126
- # See {NRSER::Types::Type#initialize}
127
- #
128
- def_factory :abs_dir_path do |name: 'AbsDirPath', **options|
129
- intersection \
130
- abs_path,
131
- dir_path,
132
- name: name,
133
- **options
134
- end # .abs_dir_path
135
-
136
-
137
- # A {.path} that is a file (using {File.file?} to test).
138
- #
139
- # @param name: (see NRSER::Types::Type#initialize)
140
- #
141
- # @param **options
142
- # See {NRSER::Types::Type#initialize}
143
- #
144
- def_factory :file_path do |name: 'FilePath', **options|
145
- intersection \
146
- path,
147
- # TODO How to change this from {.where}?
148
- where { |path| File.file? path },
149
- name: name,
150
- **options
151
- end
152
-
153
- end # module NRSER::Types
25
+ # Constants
26
+ # ----------------------------------------------------------------------------
27
+
28
+ # Regular expression to match "tilde" user-home-relative paths.
29
+ #
30
+ # @return [Regexp]
31
+ #
32
+ TILDE_PATH_RE = /\A\~(?:\/|\z)/
33
+
34
+
35
+ # @!group Path Type Factories
36
+ # ----------------------------------------------------------------------------
37
+
38
+ #@!method self.Pathname **options
39
+ # Just a type for instances of {Pathname}.
40
+ #
41
+ # @param [Hash] options
42
+ # Passed to {Type#initialize}.
43
+ #
44
+ # @return [Type]
45
+ #
46
+ def_type :Pathname,
47
+ to_data: :to_s,
48
+ from_s: ->( string ) { Pathname.new string } \
49
+ do |**options|
50
+ is_a Pathname, **options
51
+ end
52
+
53
+
54
+ #@!method self.NonEmptyPathname **options
55
+ # A {.Pathname} that isn't empty. Because not emptiness is often important.
56
+ #
57
+ # @param [Hash] options
58
+ # Passed to {Type#initialize}.
59
+ #
60
+ # @return [Type]
61
+ #
62
+ def_type :NonEmptyPathname,
63
+ &->( **options ) do
64
+ self.Intersection \
65
+ self.Pathname,
66
+ self.Attributes( to_s: self.NonEmptyString ),
67
+ **options
68
+ end # .NonEmptyPathname
69
+
70
+
71
+ # @!method self.Path **options
72
+ # A path is a {.NonEmptyString} or {.NonEmptyPathname}.
73
+ #
74
+ # @param [Hash] options
75
+ # See {Type#initialize}.
76
+ #
77
+ # @return [Type]
78
+ #
79
+ def_type :Path,
80
+ &->( **options ) do
81
+ self.Union \
82
+ self.NonEmptyString,
83
+ self.NonEmptyPathname,
84
+ **options
85
+ end # #Path
86
+
87
+
88
+ #@!method self.POSIXPathSegment **options
89
+ # A POSIX path segment (directory, file name) - any {.NonEmptyString} that
90
+ # doesn't have `/` in it.
91
+ #
92
+ # @param [Hash] options
93
+ # Passed to {Type#initialize}.
94
+ #
95
+ # @return [Type]
96
+ #
97
+ def_type :POSIXPathSegment,
98
+ aliases: [ :path_segment, :path_seg ],
99
+ &->( **options ) do
100
+ self.Intersection \
101
+ self.NonEmptyString,
102
+ self.Respond( to: [:include?, '/'], with: false ),
103
+ **options
104
+ end # .POSIXPathSegment
105
+
106
+
107
+ # @!method self.AbsolutePath **options
108
+ # An absolute {.Path}.
109
+ #
110
+ # @param [Hash] options
111
+ # Passed to {Type#initialize}.
112
+ #
113
+ # @return [Type]
114
+ #
115
+ def_type :AbsolutePath,
116
+ aliases: [ :AbsPath, :abs_path ],
117
+ # TODO IDK how I feel about this...
118
+ # from_s: ->( s ) { File.expand_path s },
119
+ &->( **options ) do
120
+ self.Intersection \
121
+ self.Path,
122
+ # Weirdly, there is no {File.absolute?}..
123
+ self.Attributes( to_pn: attrs( absolute?: true ) ),
124
+ **options
125
+ end # .AbsolutePath
126
+
127
+
128
+ #@!method self.HomePath **options
129
+ # A path that starts with `~`, meaning it's relative to a user's home
130
+ # directory (to Ruby, see note below).
131
+ #
132
+ # > ### Note: How Bash and Ruby Think Differently About Home Paths ###
133
+ # >
134
+ # > #### Ruby Always Tries to Go Home ####
135
+ # >
136
+ # > From my understanding and fiddling around Ruby considers *any* path that
137
+ # > starts with `~` a "home path" for the purpose of expanding, such as in
138
+ # > {::File.expand_path} and {::Pathname#expand_path}.
139
+ # >
140
+ # > You can see this clearly in the [rb_file_expand_path_internal][] C
141
+ # > function, which is where those expand methods end up.
142
+ # >
143
+ # > [rb_file_expand_path_internal]: https://github.com/ruby/ruby/blob/61bef8612afae25b912627e69699ddbef81adf93/file.c#L3486
144
+ # >
145
+ # > #### Bash ####
146
+ # >
147
+ # > However
148
+ # >
149
+ # > However - Bash 4's `cd` - on MacOSX, at least - treats `~some_user` as
150
+ # > being a home directory *only if* `some_user` exists... and you may have
151
+ # > a file or directory in the working dir named `~some_user` that it will
152
+ # > correctly fall back on if `some_user` does not exist.
153
+ # >
154
+ # > Paths are complicated, man.
155
+ #
156
+ # @param [Hash] options
157
+ # Passed to {Type#initialize}.
158
+ #
159
+ # @return [Type]
160
+ #
161
+ def_type :HomePath,
162
+ &->( **options ) do
163
+ self.Intersection \
164
+ self.Path,
165
+ self.Respond( to: [ :start_with?, '~' ], with: self.True ),
166
+ **options
167
+ end # .HomePath
168
+
169
+
170
+ # @!method self.AbsPath **options
171
+ # A relative {.Path}, which is just a {.Path} that's not {.AbsPath} or
172
+ # {.TildePath}.
173
+ #
174
+ # @param [Hash] options
175
+ # Passed to {Type#initialize}.
176
+ #
177
+ # @return [Type]
178
+ #
179
+ def_type :RelPath,
180
+ &->( **options ) do
181
+ self.Intersection \
182
+ self.Path,
183
+ !self.AbsPath,
184
+ !self.TildePath,
185
+ **options
186
+ end
187
+
188
+
189
+ # @method self.DirPath **options
190
+ # A {.Path} that is a directory. Requires checking the file system.
191
+ #
192
+ # @param [Hash] options
193
+ # Passed to {Type#initialize}.
194
+ #
195
+ # @return [Type]
196
+ #
197
+ def_type :DirPath,
198
+ &->( **options ) do
199
+ self.Intersection \
200
+ self.Path,
201
+ self.Where( File.method :directory? ),
202
+ **options
203
+ end # .DirPath
204
+
205
+
206
+ # @!method self.AbsDirPath **options
207
+ # Absolute {.Path} to a directory (both an {.AbsPath} and an {.DirPath}).
208
+ #
209
+ # @param [Hash] options
210
+ # Passed to {Type#initialize}.
211
+ #
212
+ # @return [Type]
213
+ #
214
+ def_type :AbsDirPath,
215
+ &->( **options ) do
216
+ self.Intersection \
217
+ self.AbsPath,
218
+ self.DirPath,
219
+ **options
220
+ end # .AbsDirPath
221
+
222
+
223
+ # @!method self.FilePath **options
224
+ # A {.Path} that is a file (using {File.file?} to test).
225
+ #
226
+ # @param name: (see NRSER::Types::Type#initialize)
227
+ #
228
+ # @param [Hash] options
229
+ # See {NRSER::Types::Type#initialize}
230
+ #
231
+ def_type :FilePath,
232
+ &->( **options ) do
233
+ self.Intersection \
234
+ self.Path,
235
+ self.Where( File.method :file? ),
236
+ **options
237
+ end # .FilePath
238
+
239
+
240
+ #@!method self.NormalizedPath **options
241
+ # @todo Document NormalizedPath type factory.
242
+ #
243
+ # @param [Hash] options
244
+ # Passed to {Type#initialize}.
245
+ #
246
+ # @return [Type]
247
+ #
248
+ def_type :NormalizedPath,
249
+ aliases: [ :NormPath, :norm_path ],
250
+ &->( **options ) do
251
+ self.Intersection \
252
+ self.Path,
253
+ self.Where( NRSER.method :normalized_path? ),
254
+ **options
255
+ end # .NormalizedPath
256
+
257
+
258
+
259
+ # @!endgroup Path Type Factories # *******************************************
260
+
261
+
262
+ # /Namespace
263
+ # ========================================================================
264
+
265
+ end # module Types
266
+ end # module NRSER