nrser 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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