format_engine 0.5.1 → 0.5.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
  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: