trees 0.3.5 → 0.4.0

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.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/lib/flags.rb +25 -0
  3. data/lib/line.rb +17 -2
  4. data/lib/trees.rb +24 -15
  5. data/lib/version.rb +1 -1
  6. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ed26c969afc761461ea690075a2c838156cb3309fef5fbac31f219b716c71a8
4
- data.tar.gz: 47fed5e9edb8a0b5a930ef505beb53381c121dd84cb4d50c89d1b84f6c2875ce
3
+ metadata.gz: b8afa25fe3a28ca015098f7a3417d41ce8d4a02e80bda91889b9e656fa0df35a
4
+ data.tar.gz: b52883d15bcd9ebc738c269d4461b035d3bf3d527ec92267b1bbf5eabd0c4fcc
5
5
  SHA512:
6
- metadata.gz: 3142f22906faf7f82aed9b56586c4007bbcda629b7d0c98b4099223854e0469317d39f49b44bd55f8fbf378d167a27e5d850a5210bfb0a7177d0547d1e662fa4
7
- data.tar.gz: 425cf3ce7982b240e8527a34cb2928c071b588896112f2f02b23b428eb887fd017d26ade1f9502a130e9fcd6ea0ef5f6cca8cdd1493ef9c335ddef7aca98f55d
6
+ metadata.gz: 03dd4e5487d5d6d79ea979a80ac589240021bda0e71baed1a3789482b605bfbe748aef05cd1b168324e07896248bc86e24da0c956ab59edbd521cf18417819b6
7
+ data.tar.gz: e1cca79dfaf2810852075f1ce75f1f2bae7296cf154daaf1d85ecd791cc6dc8ddbc46e97bac122d101a655ffcbb443eb0b83442224cb2f15f26299eb71f0f2fe
data/lib/flags.rb ADDED
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Trees
4
+ module Flags
5
+ module_function
6
+
7
+ def split(tokens)
8
+ args = tokens.take_while { !flag?(it) }
9
+ flags = tokens.drop(args.length).slice_before { flag?(it) }.map { flag(*it) }
10
+ return if flags.include?(nil)
11
+
12
+ [args, flags.to_h]
13
+ end
14
+
15
+ # A dash alone, like for stdin, is an arg.
16
+ def flag?(token) = token.start_with?('-') && token != '-'
17
+
18
+ def flag(token, *values)
19
+ return if values.size > 1
20
+
21
+ name, given = token.sub(/\A--?/, '').split('=', 2)
22
+ [name.tr('-', '_').to_sym, given || values.first || true]
23
+ end
24
+ end
25
+ end
data/lib/line.rb CHANGED
@@ -2,16 +2,31 @@
2
2
 
3
3
  module Trees
4
4
  class Line
5
- attr_reader :path, :params
5
+ attr_reader :path, :params, :keywords
6
6
  attr_accessor :summary, :example, :execute
7
7
 
8
- def initialize(path:, params: [])
8
+ def initialize(path:, params: [], keywords: [])
9
9
  @path = path
10
10
  @params = params
11
+ @keywords = keywords
11
12
 
12
13
  @summary = nil
13
14
  @example = nil
14
15
  @execute = nil
16
+ @defaults = {}
17
+ end
18
+
19
+ # The keyword arguments' values once the line's defined, which are their defaults, kept so that a flag that isn't
20
+ # given on a run is its default again, rather than its value from the last run.
21
+ def keep_defaults
22
+ @defaults = keywords.to_h { [it, execute.binding.local_variable_get(it)] } if execute
23
+ end
24
+
25
+ # Sets the execute block's params to the values, or else the keyword arguments' defaults, then runs it.
26
+ def run(values)
27
+ values = @defaults.merge(values)
28
+ params.each { |param| execute.binding.local_variable_set(param, values[param]) if values.key?(param) }
29
+ execute.call
15
30
  end
16
31
  end
17
32
  end
data/lib/trees.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'flags'
3
4
  require_relative 'line'
4
5
  require_relative 'trie'
5
6
 
@@ -8,15 +9,11 @@ module Trees
8
9
 
9
10
  def line(path, &block)
10
11
  current_path << path
11
- current_path_joined = current_path.join(TOKEN_SEPARATOR)
12
-
13
- @current_line = Line.new(path: current_path_joined, params: block.parameters.map(&:last))
14
-
15
- lines[current_path_joined] = @current_line
16
- trie.merge(line: @current_line)
12
+ defined = define_line(block:)
17
13
 
18
14
  block.call(**stub_required_keywords(block:)) if block_given?
19
15
 
16
+ defined.keep_defaults
20
17
  current_path.pop
21
18
  end
22
19
 
@@ -35,31 +32,43 @@ module Trees
35
32
  end
36
33
  alias x execute
37
34
 
35
+ # The tokens match a line as they are, or else its args do, and its flags, in any order, are its keyword arguments.
38
36
  def run(tokens)
39
- results = trie.match(tokens:)
40
- execute_block(results:)
37
+ return true if execute_block(results: trie.match(tokens:))
38
+
39
+ args, flags = Flags.split(tokens)
40
+ return false if flags.nil? || flags.empty?
41
+
42
+ execute_block(results: trie.match(tokens: args), flags:)
41
43
  end
42
44
 
43
45
  private
44
46
 
45
- def execute_block(results:)
47
+ # The deepest line that runs, and has a keyword argument for each flag.
48
+ def execute_block(results:, flags: {})
46
49
  while results.count > 0
47
50
  result = results.pop
48
51
 
49
52
  next unless result.line.execute
53
+ next unless (flags.keys - result.line.keywords).empty?
50
54
 
51
- result.line.params.each do |param|
52
- result.line.execute.binding.local_variable_set(param, result.params[param]) if result.params.key?(param)
53
- end
54
-
55
- result.line.execute.call
56
-
55
+ result.line.run(result.params.merge(flags))
57
56
  return true
58
57
  end
59
58
 
60
59
  false
61
60
  end
62
61
 
62
+ def define_line(block:)
63
+ path = current_path.join(TOKEN_SEPARATOR)
64
+ keywords = block.parameters.filter_map { |type, name| name if %i[key keyreq].include?(type) }
65
+ @current_line = Line.new(path:, params: block.parameters.map(&:last), keywords:)
66
+
67
+ lines[path] = @current_line
68
+ trie.merge(line: @current_line)
69
+ @current_line
70
+ end
71
+
63
72
  # The "line" block defines the params that the "execute" child block will use later but doesn't itself execute user input.
64
73
  def stub_required_keywords(block:)
65
74
  block.parameters.filter_map { |type, name| [name, nil] if type == :keyreq }.to_h
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Trees
4
- VERSION = '0.3.5'
4
+ VERSION = '0.4.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trees
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - maedi
@@ -17,6 +17,7 @@ executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
+ - lib/flags.rb
20
21
  - lib/line.rb
21
22
  - lib/trees.rb
22
23
  - lib/trie.rb
@@ -41,7 +42,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
41
42
  - !ruby/object:Gem::Version
42
43
  version: '0'
43
44
  requirements: []
44
- rubygems_version: 3.7.2
45
+ rubygems_version: 4.0.6
45
46
  specification_version: 4
46
47
  summary: A CLI framework where you write the literal terminal commands.
47
48
  test_files: []