fmt 0.3.1 → 0.3.2

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
  SHA256:
3
- metadata.gz: 67c0fef310f41def1104325bdcf64e0e74c00be1c491bde56e8dd18f93121711
4
- data.tar.gz: fa7af34e9c94c03ebbd28d4843a0c268fe63304cd95bfde0c0b7cbca7d550916
3
+ metadata.gz: c5cab8d0eef24b2446c187520bd8a8ac2b71cef4149ff6d0370ffd04d67120d1
4
+ data.tar.gz: 3e5b6dca4adf86661850769bd7ca0191fe7f9b62b7c7c8612765bb5c5fb54c0b
5
5
  SHA512:
6
- metadata.gz: b04858bb8cab7de025a11ecf941e175a698559b231c1878bbdf9f5762dcb3eb05cd822ee50b11a0739aa21ee5077ea9a448ef75a0e790e0587c39403e33ca303
7
- data.tar.gz: eb55994dbd819d698b626ea170b56dec4177c02742f8b50da3e1d182704c7ff78043e31aece819ec47762cf6ab4297236d0698e2d80c6b5a974e19632817bccd
6
+ metadata.gz: ceeb6ab3f6d47a8863a35b90addf52135d31905be200c402819a516fa2600bbc0672e03d813555031bee131c865d44a92f3ad431863a3a4efd72ebe7ed3b7cc3
7
+ data.tar.gz: cfdbbdb355a735235b7417bc5b96a636c7e4392d8911178fbaa80e16a7127db41d388101cbdb8e14aa15c1562846d83a8546b8137c35cca3ade24aa695e39435
@@ -30,25 +30,18 @@ module Fmt
30
30
  # Extracts components for building the AST (Abstract Syntax Tree)
31
31
  # @rbs return: Hash[Symbol, Object] -- extracted components
32
32
  def extract
33
- {}
33
+ source = urtext.delete_prefix(Sigils::EMBED_PREFIX).delete_suffix(Sigils::EMBED_SUFFIX)
34
+ {source: source}
34
35
  end
35
36
 
36
37
  # Transforms extracted components into an AST (Abstract Syntax Tree)
37
38
  # @rbs return: Node -- AST (Abstract Syntax Tree)
38
- def transform(**)
39
+ def transform(source:)
39
40
  key = Node.new(:key, [self.key])
40
41
  placeholder = Node.new(:placeholder, [self.placeholder])
41
- template = TemplateParser.new(template_urtext).parse
42
+ template = TemplateParser.new(source).parse
42
43
  children = [key, placeholder, template].reject(&:empty?)
43
- Node.new(:embed, children, urtext: urtext, source: urtext)
44
- end
45
-
46
- private
47
-
48
- # Returns the template urtext
49
- # @rbs return: String
50
- def template_urtext
51
- urtext.delete_prefix(Sigils::EMBED_PREFIX).delete_suffix(Sigils::EMBED_SUFFIX)
44
+ Node.new(:embed, children, urtext: urtext, source: source)
52
45
  end
53
46
  end
54
47
  end
@@ -24,9 +24,7 @@ module Fmt
24
24
  # Extracts components for building the AST (Abstract Syntax Tree)
25
25
  # @rbs return: Hash[Symbol, Object] -- extracted components
26
26
  def extract
27
- code = urtext
28
- code = "#{Sigils::FORMAT_METHOD}('#{urtext}')" if native_format_string?(urtext)
29
-
27
+ code = urtext.delete_prefix(Sigils::FORMAT_PREFIX)
30
28
  tokens = tokenize(code)
31
29
  method = tokens.find(&:method_name?)&.value&.to_sym
32
30
 
@@ -46,7 +44,7 @@ module Fmt
46
44
  # @rbs arguments_tokens: Array[Token] -- arguments tokens
47
45
  # @rbs return: Node -- AST (Abstract Syntax Tree)
48
46
  def transform(method:, arguments_tokens:)
49
- method = Node.new(:name, [method], urtext: urtext, source: method)
47
+ method = Node.new(:name, [method], urtext: urtext, source: method.to_s)
50
48
  arguments = ArgumentsParser.new(arguments_tokens).parse
51
49
  source = "#{method.source}#{arguments.source}"
52
50
  children = [method, arguments].reject(&:empty?)
@@ -102,12 +100,5 @@ module Fmt
102
100
  return false if arguments_started?(tokens) && !arguments_finished?(tokens)
103
101
  true
104
102
  end
105
-
106
- # Indicates if a value is a Ruby native format string
107
- # @rbs value: String -- value to check
108
- # @rbs return: bool
109
- def native_format_string?(value)
110
- value.start_with? Sigils::FORMAT_PREFIX
111
- end
112
103
  end
113
104
  end
@@ -5,22 +5,18 @@
5
5
  module Fmt
6
6
  # Parses a template from a string and builds an AST (Abstract Syntax Tree)
7
7
  class TemplateParser < Parser
8
- PIPELINE_HEAD = %r{(?=(?!#{esc Sigils::PIPE_OPERATOR})#{Sigils::FORMAT_PREFIX})}o # : Regexp -- detects a native Ruby format string
9
- PIPELINE_TAIL = %r{(?=(\s+#{Sigils::FORMAT_PREFIX})|\z)}o # : Regexp -- detects a pipeline suffix
10
-
11
- EMBED_HEAD = %r{(?=#{esc Sigils::EMBED_PREFIX})}o # : Regexp -- detects an embed prefix
12
- EMBED_TAIL = %r{#{esc Sigils::EMBED_SUFFIX}}o # : Regexp -- detects an embed suffix
8
+ EMBED_PEEK = %r{(?=#{esc Sigils::EMBED_PREFIX})}o # : Regexp -- detects start of an embed prefix (look ahead)
9
+ PIPELINE_HEAD = %r{[#{Sigils::FORMAT_PREFIX}]}o # : Regexp -- detects start of a pipeline (i.e. Ruby format string)
10
+ PIPELINE_PEEK = %r{(?=[#{Sigils::FORMAT_PREFIX}][^#{Sigils::FORMAT_PREFIX}]|\z)}o # : Regexp -- detects start of a pipeline (look ahead)
11
+ PIPELINE_TAIL = %r{\s|\z}o # : Regexp -- detects end of a pipeline
13
12
 
14
13
  # Constructor
15
14
  # @rbs urtext: String -- original source code
16
- # @rbs scanner: StringScanner?
17
- def initialize(urtext = "", scanner: nil)
15
+ def initialize(urtext = "")
18
16
  @urtext = urtext.to_s
19
- @scanner = scanner || StringScanner.new(@urtext)
20
17
  end
21
18
 
22
19
  attr_reader :urtext # : String -- original source code
23
- attr_reader :scanner # : StringScanner?
24
20
 
25
21
  # Parses the urtext (original source code)
26
22
  # @rbs return: Node -- AST (Abstract Syntax Tree)
@@ -36,11 +32,13 @@ module Fmt
36
32
  def extract
37
33
  source = urtext
38
34
 
39
- embeds = extract_embeds
35
+ # 1) extract embeds first and update the source
36
+ embeds = extract_embeds(source)
40
37
  embeds.each do |embed|
41
- source = "#{source[0...embed[:index]]}#{embed[:placeholder]}#{source[embed[:rindex]..]}"
38
+ source = source.sub(embed[:urtext], embed[:placeholder])
42
39
  end
43
40
 
41
+ # 2) extract pipelines
44
42
  pipelines = extract_pipelines(source)
45
43
 
46
44
  {embeds: embeds, pipelines: pipelines, source: source}
@@ -65,61 +63,100 @@ module Fmt
65
63
 
66
64
  private
67
65
 
68
- # Extracts embed metadata from the urtext
69
- # @rbs return: Array[Hash] -- extracted embeds
70
- def extract_embeds
71
- embeds = []
66
+ # Extracts the next embed with the scanner
67
+ # @rbs scanner: StringScanner -- scanner to extract from
68
+ # @rbs return: String? -- extracted embed
69
+ # def extract_next_embed(scanner)
70
+ # return nil unless scanner.skip_until(EMBED_PEEK)
71
+
72
+ # index = scanner.pos
73
+ # rindex = index
74
+ # stack = 0
75
+ # string = scanner.string
76
+
77
+ # while rindex < string.length
78
+ # char = string.getbyte(rindex)
79
+
80
+ # case char
81
+ # when Sigils::EMBED_PREFIX.ord then stack += 1
82
+ # when Sigils::EMBED_SUFFIX.ord then stack -= 1
83
+ # end
84
+
85
+ # rindex += 1
86
+ # break if stack.zero?
87
+ # end
88
+
89
+ # stack.zero? ? string[index...rindex] : nil
90
+ # end
91
+ def extract_next_embed(scanner)
92
+ return nil unless scanner.skip_until(EMBED_PEEK)
93
+
94
+ string = scanner.string
95
+ index = scanner.pos
96
+ rindex = index
97
+ stack = 0
98
+
99
+ while rindex < string.length
100
+ case string[rindex]
101
+ in Sigils::EMBED_PREFIX[0] then break if (stack += 1).zero?
102
+ in Sigils::EMBED_SUFFIX[0] then break if (stack -= 1).zero?
103
+ else # noop
104
+ end
72
105
 
73
- index = nil
74
- embed = ""
106
+ rindex += 1
107
+ end
75
108
 
76
- scanner = StringScanner.new(urtext)
77
- scanner.skip_until(EMBED_HEAD)
109
+ scanner.pos = rindex
110
+ stack.zero? ? string[index...rindex] : nil
111
+ end
78
112
 
79
- while scanner.matched?
80
- index ||= scanner.charpos
81
- embed = "#{embed}#{scanner.scan_until(EMBED_TAIL)}"
113
+ # Extracts embed metadata from the source
114
+ # @rbs return: Array[Hash] -- extracted embeds
115
+ def extract_embeds(source)
116
+ scanner = StringScanner.new(source)
82
117
 
83
- if embed.scan(EMBED_HEAD).size == embed.scan(EMBED_TAIL).size
84
- rindex = scanner.charpos
85
- key = :"embed_#{index}_#{rindex}"
118
+ # will iterate until extract_next_embed returns nil... when run
119
+ generator = Enumerator.new do |yielder|
120
+ while (embed = extract_next_embed(scanner))
121
+ yielder << embed
122
+ end
123
+ end
86
124
 
87
- embeds << {
88
- index: index,
89
- rindex: rindex,
90
- key: key,
91
- placeholder: "#{Sigils::FORMAT_PREFIX}#{Sigils::KEY_PREFIXES[-1]}#{key}#{Sigils::KEY_SUFFIXES[-1]}",
92
- urtext: embed
93
- }
125
+ # runs the generator and returns the resulting array
126
+ embeds = generator.to_a
94
127
 
95
- index = nil
96
- embed = scanner.skip_until(EMBED_HEAD)
97
- end
128
+ embeds.map.with_index do |embed, index|
129
+ key = :"embed_#{index}"
130
+ placeholder = "#{Sigils::FORMAT_PREFIX}#{Sigils::KEY_PREFIXES[-1]}#{key}#{Sigils::KEY_SUFFIXES[-1]}"
131
+ {key: key, placeholder: placeholder, urtext: embed}
98
132
  end
133
+ end
99
134
 
100
- embeds
135
+ # Extracts the next pipeline with the scanner
136
+ # @rbs scanner: StringScanner -- scanner to extract from
137
+ # @rbs return: String? -- extracted pipeline
138
+ def extract_next_pipeline(scanner)
139
+ return nil unless scanner.skip_until(PIPELINE_HEAD)
140
+
141
+ index = scanner.pos
142
+ rindex = scanner.skip_until(PIPELINE_PEEK) ? scanner.pos : scanner.terminate.pos
143
+ pipeline = scanner.string[index - 1...rindex].strip
144
+ pipeline.rpartition(PIPELINE_TAIL).first
101
145
  end
102
146
 
103
147
  # Extracts pipelines from the source
104
148
  # @rbs source: String -- source code to extract pipelines from
105
149
  # @rbs return: Array[String] -- extracted pipelines
106
150
  def extract_pipelines(source)
107
- pipelines = []
108
- pipeline = ""
109
-
110
151
  scanner = StringScanner.new(source)
111
- scanner.skip_until(PIPELINE_HEAD)
112
-
113
- while scanner.matched?
114
- pipeline = scanner.scan_until(PIPELINE_TAIL)
115
152
 
116
- if scanner.matched?
117
- pipelines << pipeline
118
- scanner.skip_until(PIPELINE_HEAD)
153
+ generator = Enumerator.new do |yielder|
154
+ while (pipeline = extract_next_pipeline(scanner))
155
+ yielder << pipeline
119
156
  end
120
157
  end
121
158
 
122
- pipelines
159
+ generator.to_a
123
160
  end
124
161
  end
125
162
  end
data/lib/fmt/renderer.rb CHANGED
@@ -23,45 +23,37 @@ module Fmt
23
23
  def render(*args, **kwargs)
24
24
  raise Error, "positional and keyword arguments are mutually exclusive" if args.any? && kwargs.any?
25
25
 
26
- context = template.source
27
-
28
- render_embeds(context, *args, **kwargs) do |embed, result|
26
+ render_embeds(*args, **kwargs) do |embed, result|
29
27
  kwargs[embed.key] = result
30
28
  end
31
29
 
32
- render_pipelines(context, *args, **kwargs)
30
+ rendered = template.source
31
+ render_pipelines(*args, **kwargs) do |pipeline, result|
32
+ rendered = rendered.sub(pipeline.urtext, result.to_s)
33
+ end
34
+ rendered
33
35
  end
34
36
 
35
37
  private
36
38
 
37
- # Escapes a string for use in a regular expression
38
- # @rbs value: String -- string to escape
39
- # @rbs return: String -- escaped string
40
- def esc(value) = Regexp.escape(value.to_s)
41
-
42
39
  # Renders all template embeds
43
- # @rbs context: String -- starting context
44
40
  # @rbs args: Array[Object] -- positional arguments (user provided)
45
41
  # @rbs kwargs: Hash[Symbol, Object] -- keyword arguments (user provided)
46
- # @rbs &block: Proc -- block to execute after rendering embeds (signature: Proc(String, *args, **kwargs))
47
- def render_embeds(context, *args, **kwargs)
42
+ # @rbs &block: Proc -- block executed for each embed (signature: Proc(Embed, String))
43
+ def render_embeds(*args, **kwargs)
48
44
  template.embeds.each do |embed|
49
45
  yield embed, Renderer.new(embed.template).render(*args, **kwargs)
50
46
  end
51
47
  end
52
48
 
53
49
  # Renders all template pipelines
54
- # @rbs context: String -- starting context
55
50
  # @rbs args: Array[Object] -- positional arguments (user provided)
56
51
  # @rbs kwargs: Hash[Symbol, Object] -- keyword arguments (user provided)
57
- # @rbs return: String
58
- def render_pipelines(context, *args, **kwargs)
52
+ # @rbs block: Proc -- block executed for each pipeline (signature: Proc(Pipeline, String))
53
+ def render_pipelines(*args, **kwargs)
59
54
  template.pipelines.each_with_index do |pipeline, index|
60
- result = render_pipeline(pipeline, *args[index..], **kwargs)
61
- context = context.sub(pipeline.urtext, result)
55
+ yield pipeline, render_pipeline(pipeline, *args[index..], **kwargs)
62
56
  end
63
-
64
- context
65
57
  end
66
58
 
67
59
  # Renders a single pipeline
@@ -70,55 +62,53 @@ module Fmt
70
62
  # @rbs kwargs: Hash[Symbol, Object] -- keyword arguments (user provided)
71
63
  # @rbs return: String
72
64
  def render_pipeline(pipeline, *args, **kwargs)
73
- result = ""
65
+ result = nil
74
66
 
75
67
  pipeline.macros.each do |macro|
76
- result = case macro
77
- in name: Sigils::FORMAT_METHOD
78
- case [args, kwargs]
79
- in [], {} then invoke_formatter(macro)
80
- in [], {**} => kwargs then invoke_formatter(macro, **kwargs)
81
- in [*], {} then invoke_formatter(macro, *args)
82
- in [*], {**} => kwargs then invoke_formatter(macro, *args, **kwargs)
83
- end
84
- else invoke_macro(result, macro)
85
- end
68
+ result = invoke_macro(result, macro, *args, **kwargs)
86
69
  end
87
70
 
88
71
  result
89
72
  end
90
73
 
91
- # Invokes native Ruby string formatting
92
- # @rbs macro: Macro -- macro to use (source, arguments, etc.)
93
- # @rbs args: Array[Object] -- positional arguments (user provided)
94
- # @rbs kwargs: Hash[Symbol, Object] -- keyword arguments (user provided)
95
- # @rbs return: String
96
- def invoke_formatter(macro, *args, **kwargs)
97
- callable = Fmt.registry[[Kernel, macro.name]]
98
- context = macro.arguments.args[0]
99
- context.instance_exec(*args, **kwargs, &callable)
100
- rescue => error
101
- raise_format_error(macro, *args, cause: error, **kwargs)
102
- end
103
-
104
74
  # Invokes a macro
105
75
  # @rbs context: Object -- self in callable (Proc)
106
76
  # @rbs macro: Macro -- macro to use (source, arguments, etc.)
77
+ # @rbs args: Array[Object] -- positional arguments (user provided)
78
+ # @rbs kwargs: Hash[Symbol, Object] -- keyword arguments (user provided)
107
79
  # @rbs return: Object -- result
108
- def invoke_macro(context, macro)
80
+ def invoke_macro(context, macro, *args, **kwargs)
109
81
  callable = Fmt.registry[[context.class, macro.name]] || Fmt.registry[[Object, macro.name]]
110
- raise Error, "[#{context.class.name} | Object, #{macro.name}] is not a registered formatter!" unless callable
111
-
112
- args = macro.arguments.args
113
- kwargs = macro.arguments.kwargs
114
82
 
115
- context.instance_exec(*args, **kwargs, &callable)
83
+ case callable
84
+ in nil
85
+ if kwargs.key? macro.name
86
+ kwargs[macro.name]
87
+ else
88
+ quietly do
89
+ context.instance_exec { sprintf(macro.urtext, *args, **kwargs) }
90
+ end
91
+ end
92
+ else
93
+ context.instance_exec(*macro.arguments.args, **macro.arguments.kwargs, &callable)
94
+ end
116
95
  rescue => error
117
96
  args ||= []
118
97
  kwargs ||= {}
119
98
  raise_format_error(macro, *args, cause: error, **kwargs)
120
99
  end
121
100
 
101
+ # Suppresses verbose output for the duration of the block
102
+ # @rbs block: Proc -- block to execute
103
+ # @rbs return: void
104
+ def quietly
105
+ verbose = $VERBOSE
106
+ $VERBOSE = nil
107
+ yield
108
+ ensure
109
+ $VERBOSE = verbose
110
+ end
111
+
122
112
  # Raises an invocation error if/when Proc invocations fail
123
113
  # @rbs macro: Macro -- macro that failed
124
114
  # @rbs args: Array[Object] -- positional arguments (user provided)
data/lib/fmt/version.rb CHANGED
@@ -3,5 +3,5 @@
3
3
  # rbs_inline: enabled
4
4
 
5
5
  module Fmt
6
- VERSION = "0.3.1"
6
+ VERSION = "0.3.2"
7
7
  end
@@ -25,12 +25,6 @@ module Fmt
25
25
 
26
26
  # Transforms extracted components into an AST (Abstract Syntax Tree)
27
27
  # @rbs return: Node -- AST (Abstract Syntax Tree)
28
- def transform: (**untyped) -> Node
29
-
30
- private
31
-
32
- # Returns the template urtext
33
- # @rbs return: String
34
- def template_urtext: () -> String
28
+ def transform: (source: untyped) -> Node
35
29
  end
36
30
  end
@@ -51,10 +51,5 @@ module Fmt
51
51
  # @rbs tokens: Array[Token] -- tokens to check
52
52
  # @rbs return: bool
53
53
  def finished?: (Array[Token] tokens) -> bool
54
-
55
- # Indicates if a value is a Ruby native format string
56
- # @rbs value: String -- value to check
57
- # @rbs return: bool
58
- def native_format_string?: (String value) -> bool
59
54
  end
60
55
  end
@@ -3,23 +3,20 @@
3
3
  module Fmt
4
4
  # Parses a template from a string and builds an AST (Abstract Syntax Tree)
5
5
  class TemplateParser < Parser
6
- PIPELINE_HEAD: ::Regexp
6
+ EMBED_PEEK: ::Regexp
7
7
 
8
- PIPELINE_TAIL: ::Regexp
8
+ PIPELINE_HEAD: ::Regexp
9
9
 
10
- EMBED_HEAD: ::Regexp
10
+ PIPELINE_PEEK: ::Regexp
11
11
 
12
- EMBED_TAIL: ::Regexp
12
+ PIPELINE_TAIL: ::Regexp
13
13
 
14
14
  # Constructor
15
15
  # @rbs urtext: String -- original source code
16
- # @rbs scanner: StringScanner?
17
- def initialize: (?String urtext, ?scanner: StringScanner?) -> untyped
16
+ def initialize: (?String urtext) -> untyped
18
17
 
19
18
  attr_reader urtext: untyped
20
19
 
21
- attr_reader scanner: untyped
22
-
23
20
  # Parses the urtext (original source code)
24
21
  # @rbs return: Node -- AST (Abstract Syntax Tree)
25
22
  def parse: () -> Node
@@ -38,9 +35,18 @@ module Fmt
38
35
 
39
36
  private
40
37
 
41
- # Extracts embed metadata from the urtext
38
+ # stack.zero? ? string[index...rindex] : nil
39
+ # end
40
+ def extract_next_embed: (untyped scanner) -> untyped
41
+
42
+ # Extracts embed metadata from the source
42
43
  # @rbs return: Array[Hash] -- extracted embeds
43
- def extract_embeds: () -> Array[Hash]
44
+ def extract_embeds: (untyped source) -> Array[Hash]
45
+
46
+ # Extracts the next pipeline with the scanner
47
+ # @rbs scanner: StringScanner -- scanner to extract from
48
+ # @rbs return: String? -- extracted pipeline
49
+ def extract_next_pipeline: (StringScanner scanner) -> String?
44
50
 
45
51
  # Extracts pipelines from the source
46
52
  # @rbs source: String -- source code to extract pipelines from
@@ -20,24 +20,17 @@ module Fmt
20
20
 
21
21
  private
22
22
 
23
- # Escapes a string for use in a regular expression
24
- # @rbs value: String -- string to escape
25
- # @rbs return: String -- escaped string
26
- def esc: (String value) -> String
27
-
28
23
  # Renders all template embeds
29
- # @rbs context: String -- starting context
30
24
  # @rbs args: Array[Object] -- positional arguments (user provided)
31
25
  # @rbs kwargs: Hash[Symbol, Object] -- keyword arguments (user provided)
32
- # @rbs &block: Proc -- block to execute after rendering embeds (signature: Proc(String, *args, **kwargs))
33
- def render_embeds: (String context, *untyped args, **untyped kwargs) -> untyped
26
+ # @rbs &block: Proc -- block executed for each embed (signature: Proc(Embed, String))
27
+ def render_embeds: (*untyped args, **untyped kwargs) -> untyped
34
28
 
35
29
  # Renders all template pipelines
36
- # @rbs context: String -- starting context
37
30
  # @rbs args: Array[Object] -- positional arguments (user provided)
38
31
  # @rbs kwargs: Hash[Symbol, Object] -- keyword arguments (user provided)
39
- # @rbs return: String
40
- def render_pipelines: (String context, *untyped args, **untyped kwargs) -> String
32
+ # @rbs block: Proc -- block executed for each pipeline (signature: Proc(Pipeline, String))
33
+ def render_pipelines: (*untyped args, **untyped kwargs) -> untyped
41
34
 
42
35
  # Renders a single pipeline
43
36
  # @rbs pipeline: Pipeline -- pipeline to render
@@ -46,18 +39,18 @@ module Fmt
46
39
  # @rbs return: String
47
40
  def render_pipeline: (Pipeline pipeline, *untyped args, **untyped kwargs) -> String
48
41
 
49
- # Invokes native Ruby string formatting
50
- # @rbs macro: Macro -- macro to use (source, arguments, etc.)
51
- # @rbs args: Array[Object] -- positional arguments (user provided)
52
- # @rbs kwargs: Hash[Symbol, Object] -- keyword arguments (user provided)
53
- # @rbs return: String
54
- def invoke_formatter: (Macro macro, *untyped args, **untyped kwargs) -> String
55
-
56
42
  # Invokes a macro
57
43
  # @rbs context: Object -- self in callable (Proc)
58
44
  # @rbs macro: Macro -- macro to use (source, arguments, etc.)
45
+ # @rbs args: Array[Object] -- positional arguments (user provided)
46
+ # @rbs kwargs: Hash[Symbol, Object] -- keyword arguments (user provided)
59
47
  # @rbs return: Object -- result
60
- def invoke_macro: (Object context, Macro macro) -> Object
48
+ def invoke_macro: (Object context, Macro macro, *untyped args, **untyped kwargs) -> Object
49
+
50
+ # Suppresses verbose output for the duration of the block
51
+ # @rbs block: Proc -- block to execute
52
+ # @rbs return: void
53
+ def quietly: () -> void
61
54
 
62
55
  # Raises an invocation error if/when Proc invocations fail
63
56
  # @rbs macro: Macro -- macro that failed
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fmt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Hopkins (hopsoft)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-22 00:00:00.000000000 Z
11
+ date: 2024-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ast
@@ -301,7 +301,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
301
301
  - !ruby/object:Gem::Version
302
302
  version: '0'
303
303
  requirements: []
304
- rubygems_version: 3.5.16
304
+ rubygems_version: 3.5.21
305
305
  signing_key:
306
306
  specification_version: 4
307
307
  summary: CLI Templating System and String Formatter