fmt 0.3.2 → 0.3.3

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: c5cab8d0eef24b2446c187520bd8a8ac2b71cef4149ff6d0370ffd04d67120d1
4
- data.tar.gz: 3e5b6dca4adf86661850769bd7ca0191fe7f9b62b7c7c8612765bb5c5fb54c0b
3
+ metadata.gz: ed2f5a4d3984f777c398dfe2efeba95883d1474165b0831cea8b045c9d1bc3d3
4
+ data.tar.gz: 3ae71397daf558b9d32b5377d29f40a2b307a650fc53d08f4faa3cc69759eedb
5
5
  SHA512:
6
- metadata.gz: ceeb6ab3f6d47a8863a35b90addf52135d31905be200c402819a516fa2600bbc0672e03d813555031bee131c865d44a92f3ad431863a3a4efd72ebe7ed3b7cc3
7
- data.tar.gz: cfdbbdb355a735235b7417bc5b96a636c7e4392d8911178fbaa80e16a7127db41d388101cbdb8e14aa15c1562846d83a8546b8137c35cca3ade24aa695e39435
6
+ metadata.gz: e87abb12eb2ff4373ec7f13ecd1ac236b01914296a9d2b854f8bb60dd1aef5ee1e834ba45601a9997fe53168260c5ac33f70c78c694c45c1bc49f5c958cb8e61
7
+ data.tar.gz: d26316457a56992b65d8b9c2d2478b36fc9cdd378a454748a2016dfb2c388de91098f73a5cdce23d3d9dc6d8f0d4d47ac8774c66038c39fdcca10adfedec83bb
data/README.md CHANGED
@@ -1,6 +1,15 @@
1
1
  <p align="center">
2
2
  <a href="http://blog.codinghorror.com/the-best-code-is-no-code-at-all/">
3
- <img alt="Lines of Code" src="https://img.shields.io/badge/loc-1042-47d299.svg" />
3
+ <img alt="Lines of Code" src="https://img.shields.io/badge/loc-1050-47d299.svg" />
4
+ </a>
5
+ <a href="https://rubygems.org/gems/fmt">
6
+ <img alt="GEM Version" src="https://img.shields.io/gem/v/fmt">
7
+ </a>
8
+ <a href="https://rubygems.org/gems/fmt">
9
+ <img alt="GEM Downloads" src="https://img.shields.io/gem/dt/fmt">
10
+ </a>
11
+ <a href="https://github.com/hopsoft/fmt/actions">
12
+ <img alt="Tests" src="https://github.com/hopsoft/fmt/actions/workflows/tests.yml/badge.svg" />
4
13
  </a>
5
14
  <a href="https://github.com/testdouble/standard">
6
15
  <img alt="Ruby Style" src="https://img.shields.io/badge/style-standard-168AFE?logo=ruby&logoColor=FE1616" />
@@ -21,21 +30,21 @@
21
30
 
22
31
  ## Table of Contents
23
32
 
24
- - [Getting Started](#getting-started)
25
- - [Usage](#usage)
26
- - [Macros](#macros)
27
- - [Pipelines](#pipelines)
28
- - [Supported Methods](#supported-methods)
29
- - [Rainbow GEM](#rainbow-gem)
30
- - [Composition](#composition)
31
- - [Embedded Templates](#embedded-templates)
32
- - [Customizing Fmt](#customizing-fmt)
33
- - [Kernel Refinement](#kernel-refinement)
34
- - [`fmt(object, *pipeline)`](#fmtobject-pipeline)
35
- - [`fmt_print(object, *pipeline)`](#fmt_printobject-pipeline)
36
- - [`fmt_puts(object, *pipeline)`](#fmt_putsobject-pipeline)
37
- - [Performance](#performance)
38
- - [Sponsors](#sponsors)
33
+ - [Getting Started](#getting-started)
34
+ - [Usage](#usage)
35
+ - [Macros](#macros)
36
+ - [Pipelines](#pipelines)
37
+ - [Supported Methods](#supported-methods)
38
+ - [Rainbow GEM](#rainbow-gem)
39
+ - [Composition](#composition)
40
+ - [Embedded Templates](#embedded-templates)
41
+ - [Customizing Fmt](#customizing-fmt)
42
+ - [Kernel Refinement](#kernel-refinement)
43
+ - [`fmt(object, *pipeline)`](#fmtobject-pipeline)
44
+ - [`fmt_print(object, *pipeline)`](#fmt_printobject-pipeline)
45
+ - [`fmt_puts(object, *pipeline)`](#fmt_putsobject-pipeline)
46
+ - [Performance](#performance)
47
+ - [Sponsors](#sponsors)
39
48
 
40
49
  <!-- Tocer[finish]: Auto-generated, don't remove. -->
41
50
 
@@ -133,7 +142,7 @@ Templates can include multiple format strings with distinct pipelines:
133
142
  ```ruby
134
143
  template = "Date: %<date>.10s|>magenta -- %{msg}|>titleize|>bold"
135
144
  Fmt(template, date: Time.now, msg: "this is cool")
136
- #=> "Date: \e[35m2024-09-20\e[0m \e[1mThis Is Cool\e[0m"
145
+ #=> "Date: \e[35m2024-09-21\e[0m -- \e[1mThis Is Cool\e[0m"
137
146
  ```
138
147
 
139
148
  #### Embedded Templates
@@ -178,11 +187,11 @@ template = <<~T
178
187
  %{one}|>red {{
179
188
  %{two}|>blue {{
180
189
  %{three}|>green
181
- }}
182
- }}|>bold
190
+ }}|>bold
191
+ }}
183
192
  T
184
193
  Fmt(template, one: "Red", two: "Blue", three: "Green")
185
- #=> "Multiline:\n\e[31mRed\e[0m \e[1m\n \e[34mBlue\e[0m \n \e[32mGreen\e[0m"
194
+ #=> "Multiline:\n\e[31mRed\e[0m \n \e[34mBlue\e[0m \e[1m\n \e[32mGreen\e[0m\n \e[0m\n\n"
186
195
  ```
187
196
 
188
197
  ### Customizing Fmt
@@ -6,9 +6,9 @@ module Fmt
6
6
  # Parses a template from a string and builds an AST (Abstract Syntax Tree)
7
7
  class TemplateParser < Parser
8
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
9
+ PIPELINE_PEEK = %r{(?=[#{Sigils::FORMAT_PREFIX}][^#{Sigils::FORMAT_PREFIX}])}o # : Regexp -- detects start of a pipeline (look ahead)
10
+ PERCENT_LITERAL = %r{[#{Sigils::FORMAT_PREFIX}]{2}}o # : Regexp -- detects a percent literal
11
+ WHITESPACE = %r{\s}o # : Regexp -- detects whitespace
12
12
 
13
13
  # Constructor
14
14
  # @rbs urtext: String -- original source code
@@ -66,48 +66,28 @@ module Fmt
66
66
  # Extracts the next embed with the scanner
67
67
  # @rbs scanner: StringScanner -- scanner to extract from
68
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
69
  def extract_next_embed(scanner)
92
70
  return nil unless scanner.skip_until(EMBED_PEEK)
93
71
 
94
- string = scanner.string
72
+ head = Sigils::EMBED_PREFIX[0]
73
+ tail = Sigils::EMBED_SUFFIX[0]
95
74
  index = scanner.pos
96
- rindex = index
97
75
  stack = 0
98
76
 
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?
77
+ until scanner.eos?
78
+ case scanner.getch
79
+ in ^head then stack += 1
80
+ in ^tail then stack -= 1
81
+ in nil then break
103
82
  else # noop
104
83
  end
105
84
 
106
- rindex += 1
85
+ break if stack.zero?
107
86
  end
108
87
 
109
- scanner.pos = rindex
110
- stack.zero? ? string[index...rindex] : nil
88
+ return nil unless stack.zero?
89
+
90
+ scanner.string[index...scanner.pos]
111
91
  end
112
92
 
113
93
  # Extracts embed metadata from the source
@@ -136,12 +116,25 @@ module Fmt
136
116
  # @rbs scanner: StringScanner -- scanner to extract from
137
117
  # @rbs return: String? -- extracted pipeline
138
118
  def extract_next_pipeline(scanner)
139
- return nil unless scanner.skip_until(PIPELINE_HEAD)
119
+ return nil unless scanner.skip_until(PIPELINE_PEEK)
140
120
 
141
121
  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
122
+
123
+ until scanner.eos?
124
+ if scanner.peek(2).match?(PERCENT_LITERAL)
125
+ scanner.pos += 2
126
+ next
127
+ end
128
+
129
+ case [index, scanner.pos, scanner.peek(1)]
130
+ in [i, pos, Sigils::FORMAT_PREFIX] if i == pos then scanner.pos += 1
131
+ in [i, pos, Sigils::FORMAT_PREFIX] if i != pos then break
132
+ in [i, pos, WHITESPACE] if arguments_balanced?(scanner.string[i...pos]) then break
133
+ else scanner.pos += 1
134
+ end
135
+ end
136
+
137
+ scanner.string[index...scanner.pos]
145
138
  end
146
139
 
147
140
  # Extracts pipelines from the source
@@ -158,5 +151,13 @@ module Fmt
158
151
 
159
152
  generator.to_a
160
153
  end
154
+
155
+ # Indicates if arguments are balances in the given list of chars
156
+ # @rbs value: String -- value to check
157
+ # @rbs return: bool
158
+ def arguments_balanced?(value)
159
+ return true if value.nil? || value.empty?
160
+ value.count(Sigils::ARGS_PREFIX) == value.count(Sigils::ARGS_SUFFIX)
161
+ end
161
162
  end
162
163
  end
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.2"
6
+ VERSION = "0.3.3"
7
7
  end
@@ -5,11 +5,11 @@ module Fmt
5
5
  class TemplateParser < Parser
6
6
  EMBED_PEEK: ::Regexp
7
7
 
8
- PIPELINE_HEAD: ::Regexp
9
-
10
8
  PIPELINE_PEEK: ::Regexp
11
9
 
12
- PIPELINE_TAIL: ::Regexp
10
+ PERCENT_LITERAL: ::Regexp
11
+
12
+ WHITESPACE: ::Regexp
13
13
 
14
14
  # Constructor
15
15
  # @rbs urtext: String -- original source code
@@ -35,9 +35,10 @@ module Fmt
35
35
 
36
36
  private
37
37
 
38
- # stack.zero? ? string[index...rindex] : nil
39
- # end
40
- def extract_next_embed: (untyped scanner) -> untyped
38
+ # Extracts the next embed with the scanner
39
+ # @rbs scanner: StringScanner -- scanner to extract from
40
+ # @rbs return: String? -- extracted embed
41
+ def extract_next_embed: (StringScanner scanner) -> String?
41
42
 
42
43
  # Extracts embed metadata from the source
43
44
  # @rbs return: Array[Hash] -- extracted embeds
@@ -52,5 +53,10 @@ module Fmt
52
53
  # @rbs source: String -- source code to extract pipelines from
53
54
  # @rbs return: Array[String] -- extracted pipelines
54
55
  def extract_pipelines: (String source) -> Array[String]
56
+
57
+ # Indicates if arguments are balances in the given list of chars
58
+ # @rbs value: String -- value to check
59
+ # @rbs return: bool
60
+ def arguments_balanced?: (String value) -> bool
55
61
  end
56
62
  end
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.2
4
+ version: 0.3.3
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-10-10 00:00:00.000000000 Z
11
+ date: 2024-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ast