format_engine 0.7.0 → 0.7.1

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: f114053c3cff51fcde5ac482b6e27463110adc68
4
- data.tar.gz: 0721a2c7c92b65dbcb1f6f410f0dbb759530df8a
3
+ metadata.gz: bbc14c2d44ed9942c2648f3e96f2599f2328e5fe
4
+ data.tar.gz: 962a267e81193093a7ba295784dc123154a0f361
5
5
  SHA512:
6
- metadata.gz: 4ae828117862ee0e38f5b670f4ddeb78b69f1868db1b18978db53dc8b2a97f851cb3ed6c5eca960f53a43ff442fb471e769b743cb7b5e040647883af68680f5d
7
- data.tar.gz: 6b613688092373d7eec2d7cf66336a23f9cc8dfe45008f88d0d98a74b4d63486327350700d52a4f742472c4bf465acee477d34c41bad85ff5b5ad8261b82a9f7
6
+ metadata.gz: 0d4c624e4d34c28a8c2e9bebcbb8960b1a173c5b2c6bc7e72bb7aa7b92ca6b6f40939e044bd16fd994b13198432fa7627992bfa7d8694992c01f86f35573fa56
7
+ data.tar.gz: 484a63a6acb302edc40f3f9c7240ec087c0f518989994249fad1b4776c20a5fe5994bd80dd69702f21ae490b06a323114a5d7b3186f95ef21bc745af9ccede3a
data/README.md CHANGED
@@ -21,13 +21,67 @@ Or install it yourself as:
21
21
 
22
22
  ## Usage
23
23
 
24
- In general formatters and parsers are defined using the attr_formatter
25
- and attr_parser methods. Both of these methods accept a symbol and a hash of
26
- strings (plus a few special symbols) that point to blocks (that take no arguments).
24
+ In general the format engine allows for the easy creation of formatters and
25
+ parsers. This is done using the attr_formatter and attr_parser methods that
26
+ work in a manner analogous to attr_reader etc for creating access to instance
27
+ data.
27
28
 
28
- The symbol is the name of a method that is created. The hash forms a library
29
- of supported formats. Special hash keys are the symbols :before (that is run
30
- before all other operations) and :after (that is run after all other operations)
29
+ #### attr_formatter
30
+
31
+ Creates a data formatting facility for the specified class.
32
+
33
+ _Prerequisites_
34
+ <br>The class must 'extend FormatEngine::AttrFormatter'
35
+
36
+ _Arguments_
37
+ * method_symbol - the name of the formatter instance method created by this
38
+ method
39
+ * library - a hash mapping specifications to actions (lambda blocks)
40
+
41
+ _Returns_
42
+ <br>The formatting engine created for the formatter.
43
+
44
+ _The created instance method_
45
+ <br>This method creates an instance method that provides formatted text from
46
+ an object. This takes the form:
47
+
48
+ an_object.method_name(format_string) -> a_formatted_string
49
+
50
+ #### attr_parse
51
+
52
+ Creates a data parsing facility for the specified class.
53
+
54
+ _Prerequisites_
55
+ <br>The class must 'extend FormatEngine::AttrParser'
56
+
57
+ _Arguments_
58
+ * method_symbol - the name of the parser class method created by this method.
59
+ * library - a hash mapping specifications to actions (lambda blocks)
60
+
61
+ _Returns_
62
+ <br>The formatting engine created for the parser.
63
+
64
+ _The created class method_
65
+ <br>This method creates an class method that parses formatted text into a new
66
+ instance of the class. This takes the form:
67
+
68
+ AClass.method_name(input_string, format_string) -> an_object
69
+
70
+ _Extras_
71
+ <br>After the parsing method is completed, the unparsed attribute of the parser
72
+ engine contains the un-processed portion of the input string. If no parsing
73
+ has been performed, this is an empty string.
74
+
75
+ #### Special entries
76
+ The library has two special entries keyed by symbols instead of strings.
77
+ These are
78
+
79
+ * :before - references a block that is executed before the formatting or
80
+ parsing process starts.
81
+ * :after - references a block that is executed after the formatting or
82
+ parsing process finishes.
83
+
84
+ By default, both of these entries take no action.
31
85
 
32
86
  ### Example
33
87
  The following example is found in the mocks folder:
@@ -92,16 +146,17 @@ The parsing of format specification strings is based on the following regular
92
146
  expression. This expression is applied repeatedly until all the specifications
93
147
  have been extracted from the input string.
94
148
 
95
- REGEX = %r{(?<lead> (^|(?<=[^\\]))%){0}
96
- (?<flags> [~@#$^&*=?_<>|!]*){0}
149
+ PARSE_REGEX =
150
+ %r{(?<lead> (^|(?<=[^\\]))%){0}
151
+ (?<flags> [~@#$^&*=?_<>|!]*){0}
97
152
 
98
- (?<var> \g<lead>\g<flags>[-+]?(\d+(\.\d+)?)?[a-zA-Z]){0}
99
- (?<set> \g<lead>\g<flags>(\d+(,\d+)?)?\[([^\]\\]|\\.)+\]){0}
100
- (?<rgx> \g<lead>\g<flags>\/([^\\ \/]|\\.)*\/([imx]*)){0}
101
- (?<per> \g<lead>%){0}
153
+ (?<var> \g<lead>\g<flags>[-+]?(\d+(\.\d+)?)?[a-zA-Z]){0}
154
+ (?<set> \g<lead>\g<flags>(\d+(,\d+)?)?\[([^\]\\]|\\.)+\]){0}
155
+ (?<rgx> \g<lead>\g<flags>\/([^\\ \/]|\\.)*\/([imx]*)){0}
156
+ (?<per> \g<lead>%){0}
102
157
 
103
- \g<var> | \g<set> | \g<rgx> | \g<per>
104
- }x
158
+ \g<var> | \g<set> | \g<rgx> | \g<per>
159
+ }x
105
160
 
106
161
  ### Var
107
162
  A format specification of the classical form:
@@ -1,4 +1,3 @@
1
-
2
1
  module FormatEngine
3
2
 
4
3
  # This module adds the \attr_formatter extension to a class.
@@ -16,6 +15,8 @@ module FormatEngine
16
15
  #* spec_str - A format specification string with %x etc qualifiers.
17
16
  #<br>Meta-method Returns
18
17
  #* A formatted string
18
+ #<br>Returns
19
+ #* The format engine used by this method.
19
20
  def attr_formatter(method, library)
20
21
  engine = Engine.new(library)
21
22
 
@@ -24,6 +25,7 @@ module FormatEngine
24
25
  engine.do_format(self, spec_str)
25
26
  end
26
27
 
28
+ engine
27
29
  end
28
30
 
29
31
  end
@@ -17,6 +17,8 @@ module FormatEngine
17
17
  #* spec_str - A format specification string with %x etc qualifiers.
18
18
  #<br>Meta-method Returns
19
19
  #* An instance of the host class.
20
+ #<br>Returns
21
+ #* The format engine used by this method.
20
22
  def attr_parser(method, library)
21
23
  engine = Engine.new(library)
22
24
 
@@ -25,6 +27,7 @@ module FormatEngine
25
27
  engine.do_parse(src, self, spec_str)
26
28
  end
27
29
 
30
+ engine
28
31
  end
29
32
 
30
33
  end
@@ -6,10 +6,14 @@ module FormatEngine
6
6
  #The parse library
7
7
  attr_reader :library
8
8
 
9
+ #Any un-parsed string data.
10
+ attr_reader :unparsed
11
+
9
12
  #Set up base data structures.
10
13
  def initialize(library)
11
14
  @library = library
12
15
  @spec_pool = {}
16
+ @unparsed = ""
13
17
 
14
18
  #Set up defaults for pre and post amble blocks.
15
19
  nop = lambda { }
@@ -50,6 +54,9 @@ module FormatEngine
50
54
  due_process(spec_info, parse_spec_str) do |format|
51
55
  spec_info.do_parse(format)
52
56
  end
57
+
58
+ ensure
59
+ @unparsed = spec_info.src
53
60
  end
54
61
 
55
62
  private
@@ -29,7 +29,7 @@ module FormatEngine
29
29
  #Scan the format string extracting literals and variables.
30
30
  def scan_spec(fmt_string)
31
31
  until fmt_string.empty?
32
- if (match_data = REGEX.match(fmt_string))
32
+ if (match_data = PARSE_REGEX.match(fmt_string))
33
33
  mid = match_data.to_s
34
34
  pre = match_data.pre_match
35
35
 
@@ -2,15 +2,16 @@ module FormatEngine
2
2
 
3
3
  #The format string parser.
4
4
  class FormatSpec
5
- #The regex used to parse variable specifications.
6
- REGEX = %r{(?<lead> (^|(?<=[^\\]))%){0}
7
- (?<flags> [~@#$^&*=?_<>|!]*){0}
8
- (?<var> \g<lead>\g<flags>[-+]?(\d+(\.\d+)?)?[a-zA-Z]){0}
9
- (?<set> \g<lead>\g<flags>(\d+(,\d+)?)?\[([^\]\\]|\\.)+\]){0}
10
- (?<rgx> \g<lead>\g<flags>\/([^\\ \/]|\\.)*\/([imx]*)){0}
11
- (?<per> \g<lead>%){0}
12
- \g<var> | \g<set> | \g<rgx> | \g<per>
13
- }x
5
+ #The regular expression used to parse variable specifications.
6
+ PARSE_REGEX =
7
+ %r{(?<lead> (^|(?<=[^\\]))%){0}
8
+ (?<flags> [~@#$^&*=?_<>|!]*){0}
9
+ (?<var> \g<lead>\g<flags>[-+]?(\d+(\.\d+)?)?[a-zA-Z]){0}
10
+ (?<set> \g<lead>\g<flags>(\d+(,\d+)?)?\[([^\]\\]|\\.)+\]){0}
11
+ (?<rgx> \g<lead>\g<flags>\/([^\\ \/]|\\.)*\/([imx]*)){0}
12
+ (?<per> \g<lead>%){0}
13
+ \g<var> | \g<set> | \g<rgx> | \g<per>
14
+ }x
14
15
  end
15
16
 
16
17
  end
@@ -1,5 +1,5 @@
1
1
 
2
2
  module FormatEngine
3
3
  # The version of the format_engine gem.
4
- VERSION = "0.7.0"
4
+ VERSION = "0.7.1"
5
5
  end
@@ -6,10 +6,13 @@ class Customer
6
6
  ##
7
7
  #The specification of the formatter method of the demo \Customer class.
8
8
 
9
- attr_formatter :strfmt,
9
+ @formatter_engine = attr_formatter :strfmt,
10
10
  {"%a" => lambda {cat "%#{fmt.width_str}d" % src.age },
11
11
  "%f" => lambda {cat "%#{fmt.width_str}s" % src.first_name },
12
12
  "%l" => lambda {cat "%#{fmt.width_str}s" % src.last_name }
13
13
  }
14
14
 
15
+ class << self
16
+ attr_reader :formatter_engine
17
+ end
15
18
  end
@@ -6,11 +6,19 @@ class Customer
6
6
  ##
7
7
  #The specification of the parser method of the demo \Customer class.
8
8
 
9
- attr_parser :strprs,
10
- {"%a" => lambda { tmp[:age] = found.to_i if parse(/(\d)+/) },
11
- "%f" => lambda { tmp[:fn] = found if parse(/(\w)+/) },
12
- "%l" => lambda { tmp[:ln] = found if parse(/(\w)+/) },
13
- :after => lambda { set dst.new(tmp[:fn], tmp[:ln], tmp[:age]) }
9
+ @parser_engine = attr_parser :strprs,
10
+ {"%a" => lambda { tmp[:age] = found.to_i if parse(/\d+/) },
11
+ "%f" => lambda { tmp[:fn] = found.gsub(/_/, ' ') if parse(/\w+/) },
12
+ "%l" => lambda { tmp[:ln] = found.gsub(/_/, ' ') if parse(/\w+/) },
13
+ :after => lambda do
14
+ fail "Customer strprs error, missing field: first name" unless tmp[:fn]
15
+ fail "Customer strprs error, missing field: last name" unless tmp[:ln]
16
+ fail "Customer strprs error, missing field: age" unless tmp[:age]
17
+ set dst.new(tmp[:fn], tmp[:ln], tmp[:age])
18
+ end
14
19
  }
15
20
 
21
+ class << self
22
+ attr_reader :parser_engine
23
+ end
16
24
  end
@@ -11,6 +11,11 @@ class FormatEngineTester < Minitest::Test
11
11
  #Track mini-test progress.
12
12
  include MinitestVisible
13
13
 
14
+ def test_that_engines_are_returned
15
+ assert_equal(FormatEngine::Engine, Customer.formatter_engine.class)
16
+ assert_equal(FormatEngine::Engine, Customer.parser_engine.class)
17
+ end
18
+
14
19
  def test_basic_formatting
15
20
  cust = Customer.new("Jane", "Doe", 21)
16
21
 
@@ -26,4 +31,19 @@ class FormatEngineTester < Minitest::Test
26
31
  assert_equal(21, cust.age)
27
32
  end
28
33
 
34
+ def test_some_fancy_footwork
35
+ cust = Customer.strprs("Wernher, von_Braun 104", "%f, %l %a")
36
+
37
+ assert_equal(Customer, cust.class)
38
+ assert_equal("Wernher", cust.first_name)
39
+ assert_equal("von Braun", cust.last_name)
40
+ assert_equal(104, cust.age)
41
+ end
42
+
43
+ def test_for_missing_data_detection
44
+ assert_raises { Customer.strprs("Jane, Doe twenty", "%f, %l %a") }
45
+ assert_raises { Customer.strprs("Jane", "%f, %l %a") }
46
+ assert_raises { Customer.strprs("Jane, 34", "%f, %a") }
47
+ end
48
+
29
49
  end
@@ -167,4 +167,18 @@ class ParserTester < Minitest::Test
167
167
 
168
168
  end
169
169
 
170
+ def test_for_the_unparsed
171
+ engine = make_parser
172
+ assert_equal("", engine.unparsed)
173
+
174
+ spec = "%f, %l %a"
175
+ result = engine.do_parse("Squidly, Jones 55 And much more!", TestPerson, spec)
176
+
177
+ assert_equal(TestPerson, result.class)
178
+ assert_equal("Squidly", result.first_name)
179
+ assert_equal("Jones", result.last_name)
180
+ assert_equal(" And much more!", engine.unparsed)
181
+
182
+ end
183
+
170
184
  end
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.7.0
4
+ version: 0.7.1
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-22 00:00:00.000000000 Z
11
+ date: 2016-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler