bocadillo 1.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 511ca3c5532cc2753317809342c469d5a9a427d7
4
+ data.tar.gz: eba82f473f1cae5d3dca6d8dcf10a7cd7fe2da88
5
+ SHA512:
6
+ metadata.gz: dae9ca582edf5025b3d216b380d7a35fe365eefc2e614cc9d3014b2a36ad7e705b9ecdfd2a482b1a5cf4c0e46e571bafc0a63e5bfec0e34ead50b4a3fe60cd3b
7
+ data.tar.gz: b5aa4a0408e9bd7a90eb147cc40a766c4c120fd841d2cd70a4a5080dfc8b062f7984969e9d35436e54f62f16c42ccf0228f7750f84e2e4b1ff639d48aed9a625
@@ -0,0 +1,18 @@
1
+ Copyright (c) 2017, Claudio Procida
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,41 @@
1
+ [![Build Status](https://travis-ci.org/emeraldion/bocadillo.svg?branch=master)](https://travis-ci.org/emeraldion/bocadillo)
2
+
3
+ # bocadillo
4
+
5
+ Converts a list of strings into a compact, readable representation with delimiters of choice
6
+
7
+ ```
8
+ bocadillo 'alba,albero,albergo,alberto'
9
+ # => alb(a|er(go|o|to))
10
+
11
+ bocadillo 'aria:arianna' ':' '[' '+' ']'
12
+ # => aria[+nna]
13
+ ```
14
+
15
+ ## What?
16
+
17
+ In Spanish, [bocadillo](https://es.wiktionary.org/wiki/bocadillo) means sandwich. The name hints at the strings being sliced and interleaved with bread, the delimiters. Bocadillo is the Ruby port of the PHP package [Tramezzino](https://packagist.org/packages/emeraldion/tramezzino).
18
+
19
+ ## Why?
20
+
21
+ Useful when you need to pass long lists of URL params
22
+
23
+ ## Ruby Gem
24
+
25
+ Add it to your Ruby project as a [Ruby Gem](https://rubygems.org):
26
+
27
+ ```sh
28
+ gem install bocadillo
29
+ ```
30
+
31
+ Then have it your way:
32
+
33
+ ```ruby
34
+
35
+ ```
36
+
37
+ ## License
38
+
39
+ Copyright (c) 2017, Claudio Procida
40
+
41
+ [MIT](https://opensource.org/licenses/MIT)
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bocadillo'
4
+
5
+ if (ARGV.length < 1)
6
+ Bocadillo::Usage.print
7
+ exit 1
8
+ end
9
+
10
+ args = Bocadillo::Args.get
11
+ arr = args[:string].split(args[:separator])
12
+ puts Bocadillo.encode(arr, args[:preamble], args[:delimiter], args[:terminator])
@@ -0,0 +1,19 @@
1
+ class Bocadillo
2
+ def self.encode(arr, preamble = '(', divider = '|', terminator = ')')
3
+ arr.sort!
4
+ Serializer.serialize({
5
+ 'l' => '',
6
+ 'c' => Cover.cover(arr)
7
+ }, preamble, divider, terminator)
8
+ end
9
+
10
+ def self.decode(str, preamble = '(', divider = '|', terminator = ')')
11
+ Parser.parse(str, preamble, divider, terminator)
12
+ end
13
+ end
14
+
15
+ require 'bocadillo/args'
16
+ require 'bocadillo/cover'
17
+ require 'bocadillo/parser'
18
+ require 'bocadillo/serializer'
19
+ require 'bocadillo/usage'
@@ -0,0 +1,18 @@
1
+ class Bocadillo::Args
2
+ def self.get
3
+ i = -1
4
+ str = ARGV[i+=1]
5
+ separator = ARGV[i+=1] || ','
6
+ preamble = ARGV[i+=1] || '('
7
+ delimiter = ARGV[i+=1] || '|'
8
+ terminator = ARGV[i+=1] || ')'
9
+
10
+ {
11
+ :string => str,
12
+ :separator => separator,
13
+ :preamble => preamble,
14
+ :delimiter => delimiter,
15
+ :terminator => terminator
16
+ }
17
+ end
18
+ end
@@ -0,0 +1,52 @@
1
+ class Bocadillo::Cover
2
+ def self.cover(arr = [], x0 = 0, y = 0, l = nil)
3
+ l = arr.length if l.nil?
4
+ # Check bad input
5
+ if x0 >= l
6
+ # Error: past assigned slice
7
+ return false
8
+ end
9
+ if x0 > arr.length - 1
10
+ # Error: past array length
11
+ return false;
12
+ end
13
+
14
+ if y > arr[x0].length - 1
15
+ if x0 === l - 1
16
+ # Termination of rightmost string
17
+ return [nil]
18
+ end
19
+ # The string at x0 was only as long as y0, so call on the next item
20
+ return [nil].concat(self.cover(arr, x0 + 1, y, l))
21
+ end
22
+
23
+ # Initialize non-trivial return structure
24
+ u = {
25
+ 'l' => arr[x0][y],
26
+ 'c' => []
27
+ }
28
+ r = [u]
29
+
30
+ # Spread in width until we find either the end, or a different char
31
+ x = x0
32
+ loop do
33
+ m = false
34
+ if x < l && arr[x0][y] === arr[x][y]
35
+ m = true
36
+ x += 1
37
+ end
38
+ break unless m
39
+ end
40
+
41
+ # If we haven't covered the full length of the assigned slice, launch
42
+ # on the pair (x + 1, y0) with the original length l.
43
+ if x < l
44
+ r.concat(self.cover(arr, x, y, l))
45
+ end
46
+
47
+ # Launch on the tail of the string at s[x0] from the position y
48
+ u['c'].concat(self.cover(arr, x0, y + 1, x))
49
+
50
+ r
51
+ end
52
+ end
@@ -0,0 +1,31 @@
1
+ class Bocadillo::Parser
2
+ def self.parse(str, preamble, divider, terminator)
3
+ arr = []
4
+ i = 0
5
+ j = 0
6
+ k = 0
7
+
8
+ while i < str.length do
9
+ if str[i, str.length].index(preamble) === 0 # (
10
+ t = arr[j + k]
11
+ arr.insert(j + k + 1, t)
12
+ i += preamble.length
13
+ elsif str[i, str.length].index(divider) === 0 # |
14
+ k += 1
15
+ t = arr[j + k]
16
+ arr.insert(j + k, t)
17
+ i += divider.length
18
+ elsif str[i, str.length].index(terminator) === 0 # )
19
+ arr.slice!(j + k + 1, 1)
20
+ j += k
21
+ k = 0
22
+ i += terminator.length
23
+ else
24
+ # trivial case, just keep appending to i+j-th string
25
+ arr[j + k] = (arr[j + k]||'') + str[i]
26
+ i += 1
27
+ end
28
+ end
29
+ arr
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ class Bocadillo::Serializer
2
+ def self.serialize(tree, preamble, divider, terminator, nested = false)
3
+ return '' if tree.nil?
4
+
5
+ head = [tree['l']]
6
+ if tree['c'].length === 0
7
+ return head
8
+ end
9
+
10
+ if tree['c'].length === 1
11
+ tail = [self.serialize(tree['c'][0], preamble, divider, terminator, true)]
12
+ else
13
+ suffixes = tree['c'].map do |suffix|
14
+ Bocadillo::Serializer.serialize(suffix, preamble, divider, terminator, true)
15
+ end
16
+ tail = [suffixes.join(divider)]
17
+ if nested
18
+ tail = [preamble].concat(tail).concat([terminator]);
19
+ end
20
+ end
21
+ return head.concat(tail).join('')
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ class Bocadillo::Usage
2
+ def self.print
3
+ puts <<END
4
+ Usage:
5
+ bocadillo <string> [<separator> [<child preamble> [<child separator> [<child terminator>]]]]
6
+
7
+ Examples:
8
+ bocadillo 'alba,albero,albino'
9
+ # => alb(a|ero|ino)
10
+
11
+ bocadillo 'alba:albero:albino' ':' '[' ',' ']'
12
+ # => alb[a,ero,ino]
13
+
14
+ END
15
+ end
16
+ end
@@ -0,0 +1,103 @@
1
+ require 'test/unit'
2
+ require 'bocadillo'
3
+ require 'yaml'
4
+
5
+ class BocadilloTest < Test::Unit::TestCase
6
+ def setup
7
+ @fixture_file = 'test/fixtures/arrays.yml'
8
+ @fixtures = YAML.load_file(@fixture_file)
9
+ end
10
+
11
+ def test_encode
12
+ # It should return the string unaltered if the array has a single element
13
+ assert_equal 'albero',
14
+ Bocadillo.encode(['albero'], '(', '|', ')')
15
+ end
16
+
17
+ def test_encode_no_common_radix
18
+ # Strings without a common radix
19
+ assert_equal 'a|b|c',
20
+ Bocadillo.encode(['a', 'b', 'c'], '(', '|', ')')
21
+ assert_equal 'albero|fiore',
22
+ Bocadillo.encode(@fixtures['ALBERO_FIORE'], '(', '|', ')')
23
+ end
24
+
25
+ def test_encode_common_radix
26
+ # Strings with a common radix
27
+ assert_equal 'alb(a|er(go|o|to))',
28
+ Bocadillo.encode(@fixtures['ALB_A_ER_GO_O_TO'], '(', '|', ')')
29
+ assert_equal 'pesc(a(|tore)|h(eria|iera))',
30
+ Bocadillo.encode(@fixtures['PESCA_TORE_H_ERIA_IERA'], '(', '|', ')')
31
+ assert_equal 'mar(e|i(a|na(|io)|o))',
32
+ Bocadillo.encode(@fixtures['MARE_INA_IO_IA'], '(', '|', ')')
33
+ end
34
+
35
+ def test_encode_mixed_strings
36
+ # Mixed strings
37
+ assert_equal 'alb(a|er(go|o|to))|pesc(a(|tore)|h(eria|iera))',
38
+ Bocadillo.encode(@fixtures['ALB_A_ER_GO_O_TO'].clone.concat(@fixtures['PESCA_TORE_H_ERIA_IERA']), '(', '|', ')')
39
+ end
40
+
41
+ def test_encode_scrambled_order
42
+ # Order of input doesn't matter
43
+ assert_equal Bocadillo.encode(@fixtures['ALBERO_FIORE'].reverse, '(', '|', ')'),
44
+ Bocadillo.encode(@fixtures['ALBERO_FIORE'], '(', '|', ')')
45
+ assert_equal Bocadillo.encode(@fixtures['ALB_A_ER_GO_O_TO'].reverse, '(', '|', ')'),
46
+ Bocadillo.encode(@fixtures['ALB_A_ER_GO_O_TO'], '(', '|', ')')
47
+ end
48
+
49
+ def test_encode_isin
50
+ @fixture_file = 'test/fixtures/parser.yml'
51
+ @fixtures = YAML.load_file(@fixture_file)
52
+
53
+ # A real life example
54
+ assert_equal @fixtures['ISIN']['string'], Bocadillo.encode(@fixtures['ISIN']['array'], '(', '|', ')')
55
+ end
56
+
57
+ def test_decode
58
+ # It should return the string unaltered if the array has a single element
59
+ assert_equal ['albero'],
60
+ Bocadillo.decode('albero', '(', '|', ')')
61
+ end
62
+
63
+ def test_decode_no_common_radix
64
+ # Strings without a common radix
65
+ assert_equal ['a', 'b', 'c'],
66
+ Bocadillo.decode('a|b|c', '(', '|', ')')
67
+ assert_equal @fixtures['ALBERO_FIORE'],
68
+ Bocadillo.decode('albero|fiore', '(', '|', ')')
69
+ end
70
+
71
+ def test_decode_common_radix
72
+ # Strings with a common radix
73
+ assert_equal @fixtures['ALB_A_ER_GO_O_TO'].sort,
74
+ Bocadillo.decode('alb(a|er(go|o|to))', '(', '|', ')')
75
+ assert_equal @fixtures['PESCA_TORE_H_ERIA_IERA'].sort,
76
+ Bocadillo.decode('pesc(a(|tore)|h(eria|iera))', '(', '|', ')')
77
+ assert_equal @fixtures['MARE_INA_IO_IA'].sort,
78
+ Bocadillo.decode('mar(e|i(a|na(|io)|o))', '(', '|', ')')
79
+ end
80
+
81
+ def test_decode_mixed_strings
82
+ # Mixed strings
83
+ assert_equal @fixtures['ALB_A_ER_GO_O_TO'].clone.concat(@fixtures['PESCA_TORE_H_ERIA_IERA']).sort,
84
+ Bocadillo.decode('alb(a|er(go|o|to))|pesc(a(|tore)|h(eria|iera))', '(', '|', ')')
85
+ end
86
+
87
+ def test_decode_scrambled_order
88
+ # Order of input does matter
89
+ assert_not_equal Bocadillo.decode('albero|fiore', '(', '|', ')'),
90
+ Bocadillo.decode('fiore|albero', '(', '|', ')')
91
+ assert_not_equal Bocadillo.decode('alb(er(o|to|go)|a)', '(', '|', ')'),
92
+ Bocadillo.decode('alb(a|er(go|o|to))', '(', '|', ')')
93
+ end
94
+
95
+ def test_decode_isin
96
+ @fixture_file = 'test/fixtures/parser.yml'
97
+ @fixtures = YAML.load_file(@fixture_file)
98
+
99
+ # A real life example
100
+ assert_equal @fixtures['ISIN']['array'],
101
+ Bocadillo.decode(@fixtures['ISIN']['string'], '(', '|', ')')
102
+ end
103
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bocadillo
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Claudio Procida
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-01-18 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Converts a list of strings into a compact, readable representation with
14
+ delimiters of choice
15
+ email: claudio.procida@gmail.com
16
+ executables:
17
+ - bocadillo
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - LICENSE.md
22
+ - README.md
23
+ - Rakefile
24
+ - bin/bocadillo
25
+ - lib/bocadillo.rb
26
+ - lib/bocadillo/args.rb
27
+ - lib/bocadillo/cover.rb
28
+ - lib/bocadillo/parser.rb
29
+ - lib/bocadillo/serializer.rb
30
+ - lib/bocadillo/usage.rb
31
+ - test/test_bocadillo.rb
32
+ homepage: http://rubygems.org/gems/bocadillo
33
+ licenses:
34
+ - MIT
35
+ metadata: {}
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubyforge_project:
52
+ rubygems_version: 2.6.8
53
+ signing_key:
54
+ specification_version: 3
55
+ summary: Compacts a list of strings
56
+ test_files:
57
+ - test/test_bocadillo.rb