fmt 0.3.2 → 0.3.4
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.
- checksums.yaml +4 -4
- data/README.md +29 -20
- data/lib/fmt/parsers/embed_parser.rb +1 -1
- data/lib/fmt/parsers/macro_parser.rb +1 -1
- data/lib/fmt/parsers/pipeline_parser.rb +1 -1
- data/lib/fmt/parsers/template_parser.rb +47 -40
- data/lib/fmt/version.rb +1 -1
- data/sig/generated/fmt/parsers/template_parser.rbs +12 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 674b8314e97d214271069e488dfdb736551f431953d260d1766001fdc797fd55
|
4
|
+
data.tar.gz: 8b9c601567e80419c9b2bb7414bcb42b22431832c9c1db7039a53b6d1f1cdd34
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01317ca04d3745516ec6fc842650bf0cce4fc47702f12b025b5d3d203f328f2c92053b3805a72eb9ac134686d3b1d0dfe52aee15f82ab13d8fab4f4b1f7240c9
|
7
|
+
data.tar.gz: e08ed93970be78e2fe713d22a2861111d931f63bc6d8f6e402ba1ee25405febd82b343758f201a255f3ae5f9b0d0f8faae2ea2a0d40a2d6a7b33473f6f545e32
|
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-
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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-
|
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
|
-
}}
|
190
|
+
}}|>bold
|
191
|
+
}}
|
183
192
|
T
|
184
193
|
Fmt(template, one: "Red", two: "Blue", three: "Green")
|
185
|
-
#=> "Multiline:\n\e[31mRed\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
|
@@ -10,7 +10,7 @@ module Fmt
|
|
10
10
|
# @rbs key: Symbol -- key for embed
|
11
11
|
# @rbs placeholder: String -- placeholder for embed
|
12
12
|
def initialize(urtext = "", key:, placeholder:)
|
13
|
-
@urtext = urtext.to_s
|
13
|
+
@urtext = urtext.to_s.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "?")
|
14
14
|
@key = key
|
15
15
|
@placeholder = placeholder
|
16
16
|
end
|
@@ -8,7 +8,7 @@ module Fmt
|
|
8
8
|
# Constructor
|
9
9
|
# @rbs urtext: String -- original source code
|
10
10
|
def initialize(urtext = "")
|
11
|
-
@urtext = urtext.to_s
|
11
|
+
@urtext = urtext.to_s.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "?")
|
12
12
|
end
|
13
13
|
|
14
14
|
attr_reader :urtext # : String -- original source code
|
@@ -8,7 +8,7 @@ module Fmt
|
|
8
8
|
# Constructor
|
9
9
|
# @rbs urtext: String -- original source code
|
10
10
|
def initialize(urtext = "")
|
11
|
-
@urtext = urtext.to_s
|
11
|
+
@urtext = urtext.to_s.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "?")
|
12
12
|
end
|
13
13
|
|
14
14
|
attr_reader :urtext # : String -- original source code
|
@@ -5,15 +5,15 @@
|
|
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
|
-
EMBED_PEEK = %r{(?=#{esc Sigils::EMBED_PREFIX})}
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
EMBED_PEEK = %r{(?=#{esc Sigils::EMBED_PREFIX})}ou # : Regexp -- detects start of an embed prefix (look ahead)
|
9
|
+
PIPELINE_PEEK = %r{(?=[#{Sigils::FORMAT_PREFIX}][^#{Sigils::FORMAT_PREFIX}])}ou # : Regexp -- detects start of a pipeline (look ahead)
|
10
|
+
PERCENT_LITERAL = %r{[#{Sigils::FORMAT_PREFIX}]{2}}ou # : Regexp -- detects a percent literal
|
11
|
+
WHITESPACE = %r{\s}ou # : Regexp -- detects whitespace
|
12
12
|
|
13
13
|
# Constructor
|
14
14
|
# @rbs urtext: String -- original source code
|
15
15
|
def initialize(urtext = "")
|
16
|
-
@urtext = urtext.to_s
|
16
|
+
@urtext = urtext.to_s.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "?")
|
17
17
|
end
|
18
18
|
|
19
19
|
attr_reader :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
|
-
|
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
|
-
|
100
|
-
case
|
101
|
-
in
|
102
|
-
in
|
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
|
-
|
85
|
+
break if stack.zero?
|
107
86
|
end
|
108
87
|
|
109
|
-
|
110
|
-
|
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,31 @@ 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(
|
119
|
+
return nil unless scanner.skip_until(PIPELINE_PEEK)
|
140
120
|
|
141
121
|
index = scanner.pos
|
142
|
-
|
143
|
-
|
144
|
-
|
122
|
+
|
123
|
+
until scanner.eos?
|
124
|
+
len = 1
|
125
|
+
val = nil
|
126
|
+
val = scanner.peek(len += 1) until val&.valid_encoding?
|
127
|
+
if val&.match? PERCENT_LITERAL
|
128
|
+
scanner.pos += len
|
129
|
+
next
|
130
|
+
end
|
131
|
+
|
132
|
+
len = 0
|
133
|
+
val = nil
|
134
|
+
val = scanner.peek(len += 1) until val&.valid_encoding?
|
135
|
+
case [index, scanner.pos, val]
|
136
|
+
in [i, pos, Sigils::FORMAT_PREFIX] if i == pos then scanner.pos += len
|
137
|
+
in [i, pos, Sigils::FORMAT_PREFIX] if i != pos then break
|
138
|
+
in [i, pos, WHITESPACE] if arguments_balanced?(scanner.string[i...pos]) then break
|
139
|
+
else scanner.pos += len
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
scanner.string[index...scanner.pos]
|
145
144
|
end
|
146
145
|
|
147
146
|
# Extracts pipelines from the source
|
@@ -158,5 +157,13 @@ module Fmt
|
|
158
157
|
|
159
158
|
generator.to_a
|
160
159
|
end
|
160
|
+
|
161
|
+
# Indicates if arguments are balances in the given list of chars
|
162
|
+
# @rbs value: String -- value to check
|
163
|
+
# @rbs return: bool
|
164
|
+
def arguments_balanced?(value)
|
165
|
+
return true if value.nil? || value.empty?
|
166
|
+
value.count(Sigils::ARGS_PREFIX) == value.count(Sigils::ARGS_SUFFIX)
|
167
|
+
end
|
161
168
|
end
|
162
169
|
end
|
data/lib/fmt/version.rb
CHANGED
@@ -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
|
-
|
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
|
-
#
|
39
|
-
#
|
40
|
-
|
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.
|
4
|
+
version: 0.3.4
|
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-
|
11
|
+
date: 2024-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ast
|