format_engine 0.5.1 → 0.5.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e6e8a31da2b7b4563578c47c0356f8079f83de97
4
- data.tar.gz: 50f0f2c2acb64b9174e4a1ba9a32c3b690688d3b
3
+ metadata.gz: 09f96049d5a1aec1f68f2c4f999c5c0138c0bd83
4
+ data.tar.gz: 26d8f175cb85f9307c2d0f93bebedc7dfe682bd6
5
5
  SHA512:
6
- metadata.gz: 121d8da85416bf95fc3de8f563648036de5e658be5253c5224b0e7a7963be6905ab90c3d57b1842f03d2742cc7c1dbe93da6c96de42141dc484e12b1f6d5f87b
7
- data.tar.gz: 7679f577c475743cd6bdd0958b29898f39f6d508da6b16ab88e18ff6e47e61807f61ca742f57ab44b3675b2917e56736342b02f5bd0837eb06d4eae87f116c9a
6
+ metadata.gz: d9f42b5c1a1e0ba22a89b3fb9531e9b4ed874d3f618b0b8cdbe47d393e4a8a978860a07efcf7cdb805bb32199bb2b4e597464aae413252da2795c7691c04dfca
7
+ data.tar.gz: c0d18a3b94da1251e12e1d66166f42359adb08553005e5bd0bad7c6d722f64946758a1706e9bc309ea9bb8f1a7802b8b0efe1520ab63770c1b9776710dd544f2
data/README.md CHANGED
@@ -86,17 +86,19 @@ puts cust.strfmt('%f %l is %a years old.')
86
86
  ```
87
87
  ## Format Specification
88
88
 
89
- Format String Specification Syntax (BNF):
90
-
91
- * spec ::= (text | item | set)+
92
- * item ::= "%" flag* sign? (parm ("." parm)? )? command
93
- * set ::= "%" flag* parm? "[" chrs "]"
94
- * flag ::= "~" | "@" | "#" | "&" | "^" | "&" | "*" | "=" | "?" | "_"
95
- | "<" | ">" | "\\" | "/" | "." | "," | "|" | "!"
96
- * sign ::= sign = ("+" | "-")
97
- * parm ::= ("0" .. "9")+
98
- * chrs ::= (not_any("]") | "\\" "]")+
99
- * command ::= ("a" .. "z" | "A" .. "Z")
89
+ Format String Specification Syntax (Regex):
90
+
91
+ REGEX = %r{(?<lead> (^|(?<=[^\\]))%){0}
92
+ (?<flags> [~@#$^&*\=?_<>|!]*){0}
93
+ (?<parms> [-+]?(\d+(\.\d+)?)?){0}
94
+ (?<var> \g<lead>\g<flags>\g<parms>[a-zA-Z]){0}
95
+ (?<set> \g<lead>\g<flags>\d*\[([^\]\\]|\\.)+\]){0}
96
+ (?<per> \g<lead>%){0}
97
+ \g<var> | \g<set> | \g<per>
98
+ }x
99
+
100
+ Where _var_ describes a format specification, _set_ describes a regex
101
+ set (or unset) specification, and _per_ describes a %% literal.
100
102
 
101
103
  ###Samples:
102
104
 
@@ -115,9 +117,15 @@ creates the following format specification array:
115
117
  Variable("%S", ["-5", "2"]),
116
118
  Literal("!")]
117
119
  ```
118
- Where literals are processed as themselves. If that literal ends with a space,
119
- that space will match zero or more spaces. Variables are executed by looking
120
- up the format string in the library and executing the corresponding block.
120
+ Where literals are processed as themselves, except:
121
+ * If that literal ends with a space, that space will parse zero or more spaces.
122
+ When formatting, the trailing space is just another space.
123
+ * A %% will be treated as a single % sign.
124
+ * A backslash character will take the character that follows as a literal
125
+ character. Thus \\% is equivalent to %%.
126
+
127
+ Variables are executed by looking up the format string (without the width or
128
+ precision fields) in the library and executing the corresponding block.
121
129
 
122
130
  **Note:** If a format string does not correspond to an entry in the library,
123
131
  an exception occurs.
@@ -59,7 +59,7 @@ module FormatEngine
59
59
  #* spec_str - The format specification string.
60
60
  #* block - A code block performed for each format specification.
61
61
  def due_process(spec_info, spec_str)
62
- format_spec = FormatSpec.get_spec(spec_str).validate(self)
62
+ format_spec = FormatSpec.get_spec(spec_str)
63
63
 
64
64
  spec_info.instance_exec(&self[:before])
65
65
 
@@ -8,8 +8,8 @@ module FormatEngine
8
8
 
9
9
  # Set up a literal format specification.
10
10
  def initialize(literal)
11
- @literal = literal
12
- @head = literal.rstrip
11
+ @literal = literal.gsub(/\\./) {|seq| seq[-1]}
12
+ @head = @literal.rstrip
13
13
  @has_tail = @head != @literal
14
14
  end
15
15
 
@@ -18,11 +18,6 @@ module FormatEngine
18
18
  0
19
19
  end
20
20
 
21
- # Is this literal supported by the engine? YES!
22
- def validate(_engine)
23
- self
24
- end
25
-
26
21
  # Format onto the output string
27
22
  def do_format(spec_info)
28
23
  spec_info.dst << @literal
@@ -33,12 +33,6 @@ module FormatEngine
33
33
  @regex = Regexp.new("#{set}#{qualifier}")
34
34
  end
35
35
 
36
- #Is this variable supported by the engine?
37
- def validate(engine)
38
- fail "Unsupported tag = #{format.inspect}" unless engine[format]
39
- self
40
- end
41
-
42
36
  #Format onto the output string
43
37
  def do_format(spec_info)
44
38
  fail "The tag %{@raw} may not be used in formatting."
@@ -46,7 +40,11 @@ module FormatEngine
46
40
 
47
41
  #Parse from the input string
48
42
  def do_parse(spec_info)
49
- spec_info.instance_exec(&spec_info.engine[self.format])
43
+ unless (block = spec_info.engine[format])
44
+ fail "Unsupported tag = #{format.inspect}"
45
+ end
46
+
47
+ spec_info.instance_exec(&block)
50
48
  end
51
49
 
52
50
  #Inspect for debugging.
@@ -31,12 +31,6 @@ module FormatEngine
31
31
  end
32
32
  end
33
33
 
34
- #Is this variable supported by the engine?
35
- def validate(engine)
36
- fail "Unsupported tag = #{format.inspect}" unless engine[format]
37
- self
38
- end
39
-
40
34
  #Has a width been specified?
41
35
  def has_width?
42
36
  parms
@@ -69,12 +63,12 @@ module FormatEngine
69
63
 
70
64
  #Format onto the output string
71
65
  def do_format(spec_info)
72
- spec_info.instance_exec(&spec_info.engine[self.format])
66
+ spec_info.instance_exec(&get_block(spec_info.engine))
73
67
  end
74
68
 
75
69
  #Parse from the input string
76
70
  def do_parse(spec_info)
77
- spec_info.instance_exec(&spec_info.engine[self.format])
71
+ spec_info.instance_exec(&get_block(spec_info.engine))
78
72
  end
79
73
 
80
74
  #Inspect for debugging.
@@ -82,6 +76,14 @@ module FormatEngine
82
76
  "Variable(#{format.inspect}, #{parms.inspect})"
83
77
  end
84
78
 
79
+ private
80
+
81
+ #Get the execution block from the engine.
82
+ def get_block(engine)
83
+ block = engine[format]
84
+ fail "Unsupported tag = #{format.inspect}" unless block
85
+ block
86
+ end
85
87
  end
86
88
 
87
89
  end
@@ -9,11 +9,12 @@ module FormatEngine
9
9
  #The format string parser.
10
10
  class FormatSpec
11
11
  #The regex used to parse variable specifications.
12
- REGEX = %r{(?<flags> [~@#$^&*\=?_<>\\\/\.,\|!]*){0}
12
+ REGEX = %r{(?<lead> (^|(?<=[^\\]))%){0}
13
+ (?<flags> [~@#$^&*\=?_<>|!]*){0}
13
14
  (?<parms> [-+]?(\d+(\.\d+)?)?){0}
14
- (?<var> %\g<flags>\g<parms>[a-zA-Z]){0}
15
- (?<set> %\g<flags>\d*\[([^\]\\]|\\.)+\]){0}
16
- (?<per> %%){0}
15
+ (?<var> \g<lead>\g<flags>\g<parms>[a-zA-Z]){0}
16
+ (?<set> \g<lead>\g<flags>\d*\[([^\]\\]|\\.)+\]){0}
17
+ (?<per> \g<lead>%){0}
17
18
  \g<var> | \g<set> | \g<per>
18
19
  }x
19
20
 
@@ -1,5 +1,5 @@
1
1
 
2
2
  module FormatEngine
3
3
  # The version of the format_engine gem.
4
- VERSION = "0.5.1"
4
+ VERSION = "0.5.2"
5
5
  end
@@ -16,6 +16,14 @@ class FormatSpecTester < Minitest::Test
16
16
  assert_equal("ABCDEFG!", test.specs[0].literal)
17
17
  end
18
18
 
19
+ def test_that_backslash_quotes
20
+ test = FormatEngine::FormatSpec.get_spec "ABC\\%DEFG!"
21
+ assert_equal(Array, test.specs.class)
22
+ assert_equal(1, test.specs.length)
23
+ assert_equal(FormatEngine::FormatLiteral, test.specs[0].class)
24
+ assert_equal("ABC%DEFG!", test.specs[0].literal)
25
+ end
26
+
19
27
  def test_that_it_scans_simple_variable_formats
20
28
  test = FormatEngine::FormatSpec.get_spec "%A"
21
29
  assert_equal(Array, test.specs.class)
@@ -80,7 +88,7 @@ class FormatSpecTester < Minitest::Test
80
88
  end
81
89
 
82
90
  def test_that_it_scans_option_variable_formats
83
- "~@#&^&*-+=?_<>\\/.,|".each_char do |char|
91
+ "~@#&^&*-+=?_<>|".each_char do |char|
84
92
  test = FormatEngine::FormatSpec.get_spec "%#{char}A"
85
93
  assert_equal(Array, test.specs.class)
86
94
  assert_equal(1, test.specs.length)
@@ -182,16 +190,6 @@ class FormatSpecTester < Minitest::Test
182
190
  assert_equal(")", test.specs[6].literal)
183
191
  end
184
192
 
185
- def test_that_it_validates
186
- engine = { "%A" => true, "%B" => true }
187
-
188
- test = FormatEngine::FormatSpec.get_spec "%A and %B"
189
- assert_equal(test, test.validate(engine))
190
-
191
- test = FormatEngine::FormatSpec.get_spec "%A and %C"
192
- assert_raises(RuntimeError) { test.validate(engine) }
193
- end
194
-
195
193
  def test_that_it_caches
196
194
  t1 = FormatEngine::FormatSpec.get_spec "%123.456A"
197
195
  t2 = FormatEngine::FormatSpec.get_spec "%123.456A"
@@ -62,13 +62,4 @@ class FormatterTester < Minitest::Test
62
62
  assert_raises(RuntimeError) { engine.do_format(obj, spec) }
63
63
  end
64
64
 
65
- def test_that_it_validates_before_before
66
- engine, obj, spec = make_all("Name = %f %j")
67
- test = 1
68
- engine[:before] = lambda { test = 2 }
69
-
70
- assert_raises(RuntimeError) { engine.do_format(obj, spec) }
71
- assert_equal(1, test)
72
- end
73
-
74
65
  end
@@ -8,11 +8,6 @@ class LiteralSpecTester < Minitest::Test
8
8
  #Track mini-test progress.
9
9
  MinitestVisible.track self, __FILE__
10
10
 
11
- def test_that_it_validates_always
12
- test = FormatEngine::FormatLiteral.new("Test 1 2 3")
13
- assert_equal(test, test.validate(nil))
14
- end
15
-
16
11
  def test_that_it_formats
17
12
  spec_info = FormatEngine::SpecInfo.new(nil, "", nil)
18
13
  test = FormatEngine::FormatLiteral.new("Test 1 2 3")
@@ -8,16 +8,6 @@ class VariableSpecTester < Minitest::Test
8
8
  #Track mini-test progress.
9
9
  MinitestVisible.track self, __FILE__
10
10
 
11
- def test_that_it_validates
12
- engine = { "%A" => true }
13
-
14
- test = FormatEngine::FormatVariable.new("%A")
15
- assert_equal(test, test.validate(engine))
16
-
17
- test = FormatEngine::FormatVariable.new("%B")
18
- assert_raises(RuntimeError) { test.validate(engine) }
19
- end
20
-
21
11
  def test_the_parms
22
12
  test = FormatEngine::FormatVariable.new("%B")
23
13
  refute(test.has_width?)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: format_engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Camilleri
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-06 00:00:00.000000000 Z
11
+ date: 2016-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -145,3 +145,4 @@ signing_key:
145
145
  specification_version: 4
146
146
  summary: An engine for string formatting and parsing.
147
147
  test_files: []
148
+ has_rdoc: