nrser 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/nrser/rspex.rb CHANGED
@@ -19,10 +19,20 @@
19
19
 
20
20
  # Deps
21
21
  # -----------------------------------------------------------------------
22
+ require 'rspec'
23
+ require 'commonmarker'
22
24
 
23
25
  # Project / Package
24
26
  # -----------------------------------------------------------------------
27
+ require 'nrser'
25
28
  require_relative './rspex/shared_examples'
29
+ require_relative './rspex/format'
30
+
31
+
32
+ # Refinements
33
+ # =======================================================================
34
+
35
+ using NRSER
26
36
 
27
37
 
28
38
  # Helpers
@@ -122,7 +132,6 @@ module NRSER::RSpex
122
132
  # Constants
123
133
  # =====================================================================
124
134
 
125
-
126
135
  # Symbols
127
136
  # ---------------------------------------------------------------------
128
137
  #
@@ -163,6 +172,10 @@ module NRSER::RSpex
163
172
 
164
173
  PREFIXES = PREFIXES_MATH_ITALIC
165
174
 
175
+ # PREFIXES = PREFIXES_MATH_ITALIC.map_values { |k, v|
176
+ # RSpec::Core::Formatters::ConsoleCodes.wrap( v, :cyan )
177
+ # }
178
+
166
179
 
167
180
  # Module (Class) Functions
168
181
  # =====================================================================
@@ -181,8 +194,7 @@ module NRSER::RSpex
181
194
  end # .short_s
182
195
 
183
196
 
184
-
185
- # @todo Document format_type method.
197
+ # @todo Document format method.
186
198
  #
187
199
  # @param [type] arg_name
188
200
  # @todo Add name param description.
@@ -190,39 +202,21 @@ module NRSER::RSpex
190
202
  # @return [return_type]
191
203
  # @todo Document return value.
192
204
  #
193
- def self.format_type type, description
194
- prefixes = RSpec.configuration.x_type_prefixes
195
-
196
- return description if type.nil? || !prefixes.key?( type )
197
-
198
- "#{ prefixes[type] } #{ description }"
199
- end # .format_type
200
-
205
+ def self.format *args
206
+ NRSER::RSpex::Format.description *args
207
+ end # .format
201
208
 
202
209
 
203
- # @todo Document format method.
210
+ # Get the relative path from the working directory with the `./` in front.
204
211
  #
205
- # @param [type] arg_name
206
- # @todo Add name param description.
212
+ # @param [String | Pathname] dest
213
+ # Destination file path.
207
214
  #
208
- # @return [return_type]
209
- # @todo Document return value.
215
+ # @return [String]
210
216
  #
211
- def self.format *parts, type: nil
212
- format_type \
213
- type,
214
- parts.
215
- map { |part|
216
- if part.respond_to? :to_desc
217
- part.to_desc
218
- elsif part.is_a? String
219
- part
220
- else
221
- short_s part
222
- end
223
- }.
224
- join( ' ' )
225
- end # .format
217
+ def self.dot_rel_path dest
218
+ File.join '.', dest.to_pn.relative_path_from( Pathname.getwd )
219
+ end # .dot_rel_path
226
220
 
227
221
 
228
222
  class List < Array
@@ -251,7 +245,7 @@ module NRSER::RSpex
251
245
  end
252
246
 
253
247
 
254
- class Args < Array
248
+ class Args < List
255
249
  def to_desc max = nil
256
250
  if last.is_a?( Hash )
257
251
  [
@@ -264,366 +258,6 @@ module NRSER::RSpex
264
258
  end
265
259
  end
266
260
 
267
-
268
- # Instance methods to extend example groups with.
269
- #
270
- module ExampleGroup
271
-
272
-
273
- # @todo Document describe_x method.
274
- #
275
- # @param [type] arg_name
276
- # @todo Add name param description.
277
- #
278
- # @return [return_type]
279
- # @todo Document return value.
280
- #
281
- def describe_x_type *description_parts,
282
- type:,
283
- metadata: {},
284
- subject_block: nil,
285
- &body
286
-
287
- description = NRSER::RSpex.format *description_parts, type: type
288
-
289
- describe description, **metadata, type: type do
290
- subject( &subject_block ) if subject_block
291
- module_exec &body
292
- end # description,
293
-
294
- end # #describe_x_type
295
-
296
-
297
- # **EXPERIMENTAL**
298
- #
299
- # Example group helper for use at the top level of each spec file to
300
- # set a bunch of stuff up and build a helpful description.
301
- #
302
- # @todo
303
- # This is totally just a one-off right now... would need to be
304
- # generalized quite a bit...
305
- #
306
- # 1. Extraction of module, class, etc from metadata should be flexible
307
- #
308
- # 2. Built description would need to be conditional on what metadata
309
- # was found.
310
- #
311
- # @param [String] description:
312
- # A description of the spec file to add to the RSpec description.
313
- #
314
- # @param [String] spec_path:
315
- # The path to the spec file (just feed it `__FILE__`).
316
- #
317
- # Probably possible to extract this somehow without having to provide it?
318
- #
319
- # @return [nil]
320
- #
321
- def describe_spec_file description: nil,
322
- spec_path:,
323
- bind_subject: true,
324
- **metadata,
325
- &body
326
-
327
- meth = metadata[:module].method metadata[:method]
328
- file, line = meth.source_location
329
- path = Pathname.new file
330
- loc = "./#{ path.relative_path_from Pathname.getwd }:#{ line }"
331
-
332
- spec_rel_path = "./#{ Pathname.new( spec_path ).relative_path_from Pathname.getwd }"
333
-
334
- desc = [
335
- "#{ metadata[:module].name }.#{ metadata[:method] }",
336
- "(#{ loc })",
337
- description,
338
- "Spec (#{ spec_rel_path})"
339
- ].compact.join " "
340
-
341
- describe desc, **metadata do
342
- if bind_subject
343
- subject { meth }
344
- end
345
-
346
- module_exec &body
347
- end
348
-
349
- nil
350
- end # #describe_spec_file
351
-
352
-
353
- # @todo Document describe_instance method.
354
- #
355
- # @param [type] arg_name
356
- # @todo Add name param description.
357
- #
358
- # @return [return_type]
359
- # @todo Document return value.
360
- #
361
- def describe_instance *constructor_args, &body
362
- describe_x_type ".new(", Args(*constructor_args), ")",
363
- type: :instance,
364
- metadata: {
365
- constructor_args: constructor_args,
366
- },
367
- # subject_block: -> { super().new *described_args },
368
- subject_block: -> { super().new *described_constructor_args },
369
- &body
370
- end # #describe_instance
371
-
372
-
373
- # Create a new {RSpec.describe} section where the subject is set by
374
- # calling the parent subject with `args` and evaluate `block` in it.
375
- #
376
- # @example
377
- # describe "hi sayer" do
378
- # subject{ ->( name ) { "Hi #{ name }!" } }
379
- #
380
- # describe_called_with 'Mom' do
381
- # it { is_expected.to eq 'Hi Mom!' }
382
- # end
383
- # end
384
- #
385
- # @param [Array] *args
386
- # Arguments to call `subject` with to produce the new subject.
387
- #
388
- # @param [#call] &block
389
- # Block to execute in the context of the example group after refining
390
- # the subject.
391
- #
392
- def describe_called_with *args, &body
393
- describe_x_type "called with", List(*args),
394
- type: :invocation,
395
- subject_block: -> { super().call *args },
396
- &body
397
- end # #describe_called_with
398
-
399
- # Aliases to other names I was using at first... not preferring their use
400
- # at the moment.
401
- #
402
- # The `when_` one sucks because Atom de-dents the line, and `describe_`
403
- # is just clearer what the block is doing for people reading it.
404
- alias_method :called_with, :describe_called_with
405
- alias_method :when_called_with, :describe_called_with
406
-
407
-
408
- def describe_message symbol, *args, &body
409
- description = \
410
- "message #{ [symbol, *args].map( &NRSER::RSpex.method( :short_s ) ).join( ', ' ) }"
411
-
412
- describe description, type: :message do
413
- subject { NRSER::Message.new symbol, *args }
414
- module_exec &body
415
- end
416
- end
417
-
418
-
419
- # For use when `subject` is a {NRSER::Message}. Create a new context for
420
- # the `receiver` where the subject is the result of sending that message
421
- # to the receiver.
422
- #
423
- # @param [Object] receiver
424
- # Object that will receive the message to create the new subject.
425
- #
426
- # @param [Boolean] publicly:
427
- # Send message publicly via {Object#public_send} (default) or privately
428
- # via {Object.send}.
429
- #
430
- # @return
431
- # Whatever the `context` call returns.
432
- #
433
- def describe_sent_to receiver, publicly: true, &block
434
- mode = if publicly
435
- "publicly"
436
- else
437
- "privately"
438
- end
439
-
440
- describe "sent to #{ receiver } (#{ mode })" do
441
- subject { super().send_to unwrap( receiver, context: self ) }
442
- module_exec &block
443
- end
444
- end # #describe_sent_to
445
-
446
- # Aliases to other names I was using at first... not preferring their use
447
- # at the moment.
448
- #
449
- # The `when_` one sucks because Atom de-dents the line, and `describe_`
450
- # is just clearer what the block is doing for people reading it.
451
- alias_method :sent_to, :describe_sent_to
452
- alias_method :when_sent_to, :describe_sent_to
453
-
454
-
455
- def describe_return_value *args, &body
456
- msg = NRSER::Message.from *args
457
-
458
- describe "return value from #{ msg }" do
459
- subject { msg.send_to super() }
460
- module_exec &body
461
- end # "return value from #{ msg }"
462
- end
463
-
464
-
465
- # Describe a "section". Just like {RSpec.describe} except it:
466
- #
467
- # 1. Expects a string title.
468
- #
469
- # 2. Prepends a little section squiggle `§` to the title so sections are
470
- # easier to pick out visually.
471
- #
472
- # 3. Adds `type: :section` metadata.
473
- #
474
- # @param [String] title
475
- # String title for the section.
476
- #
477
- # @param [Hash<Symbol, Object>] **metadata
478
- # Additional [RSpec metadata][] for the example group.
479
- #
480
- # [RSpec metadata]: https://relishapp.com/rspec/rspec-core/docs/metadata/user-defined-metadata
481
- #
482
- # @return
483
- # Whatever {RSpec.describe} returns.
484
- #
485
- def describe_section title, **metadata, &block
486
- describe(
487
- "#{ NRSER::RSpex::PREFIXES[:section] } #{ title }",
488
- type: :section,
489
- **metadata
490
- ) do
491
- module_exec &block
492
- end
493
- end # #describe_section
494
-
495
- # Old name
496
- alias_method :describe_topic, :describe_section
497
-
498
-
499
- def describe_file path, **metadata, &body
500
- title = path
501
-
502
- describe(
503
- "#{ NRSER::RSpex::PREFIXES[:file] } #{ title }",
504
- type: :file,
505
- file: path,
506
- **metadata
507
- ) do
508
- module_exec &body
509
- end
510
- end
511
-
512
-
513
- def describe_module mod, bind_subject: true, **metadata, &block
514
- describe(
515
- "#{ NRSER::RSpex::PREFIXES[:module] } #{ mod.name }",
516
- type: :module,
517
- module: mod,
518
- **metadata
519
- ) do
520
- if bind_subject
521
- subject { mod }
522
- end
523
-
524
- module_exec &block
525
- end
526
- end # #describe_module
527
-
528
-
529
- def describe_class klass, bind_subject: true, **metadata, &block
530
- description = "#{ NRSER::RSpex::PREFIXES[:class] } #{ klass.name }"
531
-
532
- describe(
533
- description,
534
- type: :class,
535
- class: klass,
536
- **metadata
537
- ) do
538
- if bind_subject
539
- subject { klass }
540
- end
541
-
542
- module_exec &block
543
- end
544
- end # #describe_class
545
-
546
-
547
- def described_class
548
- metadata[:class] || super()
549
- end
550
-
551
-
552
- def describe_group title, **metadata, &block
553
- describe(
554
- "#{ NRSER::RSpex::PREFIXES[:group] } #{ title }",
555
- type: :group,
556
- **metadata
557
- ) do
558
- module_exec &block
559
- end
560
- end # #describe_class
561
-
562
-
563
- def describe_method name, **metadata, &block
564
- describe(
565
- "#{ NRSER::RSpex::PREFIXES[:method] } #{ name }",
566
- type: :method,
567
- method_name: name,
568
- **metadata
569
- ) do
570
- if name.is_a? Symbol
571
- subject { super().method name }
572
- end
573
-
574
- module_exec &block
575
- end
576
- end # #describe_method
577
-
578
-
579
- def describe_attribute symbol, **metadata, &block
580
- describe(
581
- "#{ NRSER::RSpex::PREFIXES[:attribute] } ##{ symbol }",
582
- type: :attribute,
583
- **metadata
584
- ) do
585
- subject { super().public_send symbol }
586
- module_exec &block
587
- end
588
- end # #describe_attribute
589
-
590
- # Shorter name
591
- alias_method :describe_attr, :describe_attribute
592
-
593
-
594
- # Define a `context` block with `let` bindings and evaluate the `body`
595
- # block in it.
596
- #
597
- # @param [Hash<Symbol, Object>] **bindings
598
- # Map of symbol names to value to bind using `let`.
599
- #
600
- # @param [#call] &body
601
- # Body block to evaluate in the context.
602
- #
603
- # @return
604
- # Whatever `context` returns.
605
- #
606
- def context_where description = nil, **bindings, &body
607
-
608
- if description.nil?
609
- description = bindings.map { |name, value|
610
- "#{ name }: #{ NRSER::RSpex.short_s value }"
611
- }.join( ", " )
612
- end
613
-
614
- context "△ #{ description }", type: :where do
615
- bindings.each { |name, value|
616
- let( name ) { unwrap value, context: self }
617
- }
618
-
619
- module_exec &body
620
- end
621
- end
622
-
623
-
624
- end # module ExampleGroup
625
-
626
-
627
261
  # Extensions available in examples themselves via RSpec's `config.include`.
628
262
  #
629
263
  module Example
@@ -639,6 +273,8 @@ module NRSER::RSpex
639
273
 
640
274
  end # module NRSER:RSpex
641
275
 
276
+ require_relative './rspex/example_group'
277
+
642
278
 
643
279
  RSpec.configure do |config|
644
280
  config.extend NRSER::RSpex::ExampleGroup
@@ -646,9 +282,9 @@ RSpec.configure do |config|
646
282
 
647
283
  config.add_setting :x_type_prefixes
648
284
  config.x_type_prefixes = \
649
- NRSER::RSpex::PREFIXES_BASE.merge( NRSER::RSpex::PREFIXES_MATH_ITALIC )
650
-
651
- config.add_setting :x_type_prefixes
285
+ NRSER::RSpex::PREFIXES
286
+
287
+ config.add_setting :x_style, default: :unicode
652
288
  end
653
289
 
654
290
  # Make available at the top-level
@@ -30,7 +30,7 @@ module NRSER; end
30
30
 
31
31
  module NRSER::Types
32
32
 
33
- # A {Pathname} type that provides a `from_s`
33
+ # A {Pathname} type that provides a `from_s`
34
34
  PATHNAME = is_a \
35
35
  Pathname,
36
36
  name: 'PathnameType',
@@ -102,7 +102,7 @@ module NRSER::Types
102
102
  def abs_path name: 'AbsPath', **options
103
103
  intersection \
104
104
  path,
105
- where { |path| File.absolute? path },
105
+ where { |path| path.to_pn.absolute? },
106
106
  name: name,
107
107
  **options
108
108
  end
@@ -155,4 +155,3 @@ module NRSER::Types
155
155
  POSIX_PATH_SEGMENT = path_segment name: 'POSIXPathSegment'
156
156
 
157
157
  end # module NRSER::Types
158
-
data/lib/nrser/types.rb CHANGED
@@ -104,7 +104,11 @@ module NRSER::Types
104
104
  # OK, we matched! Is the corresponding expression callable?
105
105
  if expression.respond_to? :call
106
106
  # It is; invoke and return result.
107
- return expression.call value
107
+ if expression.arity == 0
108
+ return expression.call
109
+ else
110
+ return expression.call value
111
+ end
108
112
  else
109
113
  # It's not; assume it's a value and return it.
110
114
  return expression
data/lib/nrser/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module NRSER
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
 
4
4
  module Version
5
5
 
data/lib/nrser.rb CHANGED
@@ -20,7 +20,7 @@ require 'singleton'
20
20
 
21
21
  # Deps
22
22
  # -----------------------------------------------------------------------
23
-
23
+ require 'hamster'
24
24
 
25
25
  # Hi there!
26
26
  #
@@ -61,8 +61,10 @@ require_relative './nrser/errors'
61
61
  require_relative './nrser/version'
62
62
  require_relative './nrser/no_arg'
63
63
  require_relative './nrser/message'
64
+ require_relative './nrser/env'
64
65
  require_relative './nrser/collection'
65
66
  require_relative './nrser/functions'
66
67
  require_relative './nrser/types'
67
68
  require_relative './nrser/refinements'
68
69
  require_relative './nrser/meta'
70
+ require_relative './nrser/mean_streak'
@@ -0,0 +1,65 @@
1
+ describe_spec_file(
2
+ spec_path: __FILE__,
3
+ class: NRSER::Env::Path,
4
+ instance_method: :insert,
5
+ ) do
6
+
7
+ describe_setup %{
8
+ Create a new instance from `source`, call `#insert` on `args` and compare
9
+ to the string result from `#to_s`
10
+ } do
11
+
12
+ let( :path ) { NRSER::Env::Path.new source }
13
+ subject { path.insert( *args ).to_s }
14
+
15
+ describe_use_case(
16
+ "insert `./test/bin` into PATH before any workdir paths",
17
+ where: {
18
+ args: ['./test/bin', before: %r{^./}],
19
+ }
20
+ ) do
21
+
22
+ describe_when(
23
+ "`./bin` is the first path in source",
24
+ source: './bin:/Users/nrser/bin:/usr/local/bin',
25
+ ) do
26
+ it "should insert at the start" do
27
+ is_expected.
28
+ to eq "./test/bin:#{ source }"
29
+ end
30
+ end
31
+
32
+ describe_when(
33
+ "`./bin` is in the middle of the source",
34
+ source: '/some/path:./bin:/Users/nrser/bin:/usr/local/bin',
35
+ ) do
36
+ it "should insert before `./bin`" do
37
+ is_expected.
38
+ to eq '/some/path:./test/bin:./bin:/Users/nrser/bin:/usr/local/bin'
39
+ end
40
+ end
41
+
42
+ describe_when(
43
+ "`./bin` is at the end of the source",
44
+ source: '/some/path:/Users/nrser/bin:/usr/local/bin:./bin',
45
+ ) do
46
+ it "should insert before `./bin`" do
47
+ is_expected.
48
+ to eq '/some/path:/Users/nrser/bin:/usr/local/bin:./test/bin:./bin'
49
+ end
50
+ end
51
+
52
+ describe_when(
53
+ "no `./` paths in source",
54
+ source: '/some/path:/Users/nrser/bin:/usr/local/bin',
55
+ ) do
56
+ it "should insert at the end" do
57
+ is_expected.
58
+ to eq '/some/path:/Users/nrser/bin:/usr/local/bin:./test/bin'
59
+ end
60
+ end
61
+ end # insert `./test/bin` into PATH before any workdir paths
62
+
63
+ end # setup
64
+
65
+ end # spec
@@ -0,0 +1,12 @@
1
+ describe_spec_file(
2
+ spec_path: __FILE__,
3
+ class: NRSER::Env::Path,
4
+ ) do
5
+
6
+ describe_method :from_ENV do
7
+ it "loads from ENV['PATH']" do
8
+ expect( subject.call :PATH ).to be_a( described_class )
9
+ end
10
+ end # Method :from_ENV Description
11
+
12
+ end # spec