fugu 0.8.0

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,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,7 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ fugu.gemspec
7
+ .rake_tasks*
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Erik Kastner, Ian Meyer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,18 @@
1
+ = fugu
2
+
3
+ A magical string puffer and shrinker.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (if you want to have your own version, that is fine but
13
+ bump version in a commit by itself I can ignore when I pull)
14
+ * Send me a pull request. Bonus points for topic branches.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2009 Erik Kastner and Ian Meyer. See LICENSE for details.
@@ -0,0 +1,70 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "fugu"
8
+ gem.summary = %Q{Magically puff or shrink strings}
9
+ gem.description = %Q{Puff: host0{9-10} to host09 host10}
10
+ gem.email = "kastner@gmail.com"
11
+ gem.homepage = "http://github.com/kastner/fugu"
12
+ gem.authors = ["Erik Kastner"]
13
+ gem.add_development_dependency "shoulda"
14
+ gem.add_development_dependency "cucumber"
15
+ gem.executables = ['fugu']
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
21
+ end
22
+
23
+ require 'rake/testtask'
24
+ Rake::TestTask.new(:test) do |test|
25
+ test.libs << 'lib' << 'test'
26
+ test.pattern = 'test/**/*_test.rb'
27
+ test.verbose = true
28
+ end
29
+
30
+ begin
31
+ require 'rcov/rcovtask'
32
+ Rcov::RcovTask.new do |test|
33
+ test.libs << 'test'
34
+ test.pattern = 'test/**/*_test.rb'
35
+ test.verbose = true
36
+ end
37
+ rescue LoadError
38
+ task :rcov do
39
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
40
+ end
41
+ end
42
+
43
+ task :test => :check_dependencies
44
+
45
+ begin
46
+ require 'cucumber/rake/task'
47
+ Cucumber::Rake::Task.new(:features)
48
+
49
+ task :features => :check_dependencies
50
+ rescue LoadError
51
+ task :features do
52
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
53
+ end
54
+ end
55
+
56
+ task :default => :test
57
+
58
+ require 'rake/rdoctask'
59
+ Rake::RDocTask.new do |rdoc|
60
+ if File.exist?('VERSION')
61
+ version = File.read('VERSION')
62
+ else
63
+ version = ""
64
+ end
65
+
66
+ rdoc.rdoc_dir = 'rdoc'
67
+ rdoc.title = "fugu #{version}"
68
+ rdoc.rdoc_files.include('README*')
69
+ rdoc.rdoc_files.include('lib/**/*.rb')
70
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.8.0
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby -wKU
2
+
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), "..", "lib")
4
+
5
+ %w{rubygems fugu optparse}.each { |m| require m }
6
+
7
+ options = {}
8
+ OptionParser.new() do |opts|
9
+ opts.banner = "Usage: #{$0} RANGE"
10
+
11
+ options[:action] = "puff"
12
+ opts.on('-s', '--shrink', 'Shrink expression') do
13
+ options[:action] = "shrink"
14
+ end
15
+
16
+ options[:delimiter] = "\n"
17
+ opts.on('-d', '--delimiter DELIMITER', String, 'Delimiter') do |delimiter|
18
+ options[:delimiter] = delimiter
19
+ end
20
+
21
+ opts.parse!
22
+ end
23
+
24
+ string = ARGV[0] || ARGF.read
25
+
26
+ puts case options[:action]
27
+ when "puff" then Fugu.puff(string).join(options[:delimiter])
28
+ when "shrink" then Fugu.shrink(string, options[:delimiter])
29
+ end
@@ -0,0 +1,70 @@
1
+ Feature: Puffing up
2
+ In order to puff some text
3
+ A user passes input to fugu
4
+ And gets something useful out
5
+
6
+ Scenario: Unexpandable text should come back as it went in
7
+ Given the string "web0001" and delimiter ","
8
+ When I puff it
9
+ Then I should get back "web0001"
10
+ And @text should be "web0001"
11
+
12
+ Scenario: Unexpandable Fugu expression comes back as it went in
13
+ Given the string "web{0001}" and delimiter ","
14
+ When I puff it
15
+ Then I should get back "web0001"
16
+ And @text should be "web{0001}"
17
+
18
+ Scenario: Simple expansion
19
+ Given the string "web000{1,2}" and delimiter ","
20
+ When I puff it
21
+ Then I should get back "web0001,web0002"
22
+
23
+ Scenario: Range expanstion
24
+ Given the string "web000{1-3}" and delimiter ","
25
+ When I puff it
26
+ Then I should get back "web0001,web0002,web0003"
27
+
28
+ Scenario: Simple Range expanstion
29
+ Given the string "web{1-2}" and delimiter ","
30
+ When I puff it
31
+ Then I should get back "web1,web2"
32
+
33
+ Scenario: Mix of simple and complex ranges
34
+ Given the string "web000{1,2-4,6}" and delimiter ","
35
+ When I puff it
36
+ Then I should get back "web0001,web0002,web0003,web0004,web0006"
37
+
38
+ Scenario: Simple two range expansion
39
+ Given the string "web0001|api01" and delimiter ","
40
+ When I puff it
41
+ Then I should get back "web0001,api01"
42
+
43
+ Scenario: Complex two range expansion
44
+ Given the string "web000{1-3}|api0{1-2}" and delimiter ","
45
+ When I puff it
46
+ Then I should get back "web0001,web0002,web0003,api01,api02"
47
+
48
+ Scenario: Doing a permanent expansion
49
+ Given the string "web000{1-3}" and delimiter ","
50
+ When I really puff it
51
+ Then @text should be "web0001,web0002,web0003"
52
+
53
+ Scenario: Expansion with zeros
54
+ Given the string "web{09-12}" and delimiter ","
55
+ When I puff it
56
+ Then I should get back "web09,web10,web11,web12"
57
+
58
+ Scenario: Class method puff
59
+ When I call puff on Fugu with "web000{1-3}"
60
+ Then I should have "web0001,web0002,web0003"
61
+
62
+ Scenario: Puffing unpadded string always returns correct pad amount
63
+ Given the string "web00{9-10}" and delimiter ","
64
+ When I puff it
65
+ Then I should get back "web0009,web0010"
66
+
67
+ #Scenario: Removing entry from puffed string
68
+ # Given the string "web00{9-11} - web0010" and delimiter ","
69
+ # When I puff it
70
+ # Then I should get back "web0009,web0011"
@@ -0,0 +1,38 @@
1
+ Feature: Shrinking down
2
+ In order to shrink some text
3
+ A user passes input to fugu
4
+ And gets a shorter version (if possible)
5
+
6
+ Scenario: Simplest shrink
7
+ Given the string "web1,web2" and delimiter ","
8
+ When I shrink it
9
+ Then I should get the string "web{1-2}"
10
+
11
+ Scenario: Longer range shrink
12
+ Given the string "web1,web2,web3" and delimiter ","
13
+ When I shrink it
14
+ Then I should get the string "web{1-3}"
15
+
16
+ Scenario: Range with gap shrink
17
+ Given the string "web1,web2,web4" and delimiter ","
18
+ When I shrink it
19
+ Then I should get the string "web{1-2,4}"
20
+
21
+ Scenario: Range, gap, range, gap...
22
+ Given the string "web1,web2,web9,web6,web7,web4" and delimiter ","
23
+ When I shrink it
24
+ Then I should get the string "web{1-2,4,6-7,9}"
25
+
26
+ Scenario: zeros...
27
+ Given the string "web01,web02,web12,web13,web14,web15" and delimiter ","
28
+ When I shrink it
29
+ Then I should get the string "web{01-02,12-15}"
30
+
31
+ Scenario: Class method of shrink
32
+ When I call shrink on Fugu with "web001,web002,web003" and delimiter ","
33
+ Then I should have shrunk "web00{1-3}"
34
+
35
+ #Scenario: Multiple shrinks
36
+ # Given the string "web1,web2,api3,api4" and delimiter ","
37
+ # When I shrink it
38
+ # Then I should get the string "web{1-2}|api{3-4}"
@@ -0,0 +1,46 @@
1
+ Given /^the string "([^\"]*)" and delimiter "([^\"]*)"$/ do |arg1, arg2|
2
+ @f = Fugu.new
3
+ @f.text = arg1
4
+ @f.delimiter = arg2
5
+ end
6
+
7
+ When /^I puff it$/ do
8
+ @message = "puff"
9
+ end
10
+
11
+ When /^I shrink it$/ do
12
+ @message = "shrink"
13
+ end
14
+
15
+ Then /^I should get back "([^\"]*)"$/ do |arg1|
16
+ assert_equal arg1, @f.send(@message).join(",")
17
+ end
18
+
19
+ Then /^I should get the string "([^\"]*)"$/ do |arg1|
20
+ assert_equal arg1, @f.send(@message)
21
+ end
22
+
23
+ When /^I really puff it$/ do
24
+ @f.puff!
25
+ end
26
+
27
+ Then /^@text should be "([^\"]*)"$/ do |arg1|
28
+ # assert_equal arg1, @f.send().join(',')
29
+ end
30
+
31
+ When /^I call puff on Fugu with "([^\"]*)"$/ do |arg1|
32
+ @string = arg1
33
+ end
34
+
35
+ Then /^I should have "([^\"]*)"$/ do |arg1|
36
+ assert_equal arg1, Fugu.puff(@string).join(',')
37
+ end
38
+
39
+ When /^I call shrink on Fugu with "([^\"]*)" and delimiter "([^\"]*)"$/ do |arg1, arg2|
40
+ @string = arg1
41
+ @delimiter = arg2
42
+ end
43
+
44
+ Then /^I should have shrunk "([^\"]*)"$/ do |arg1|
45
+ assert_equal arg1, Fugu.shrink(@string, @delimiter)
46
+ end
@@ -0,0 +1,7 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'fugu'
3
+
4
+ require 'test/unit/assertions'
5
+ require 'matchy'
6
+
7
+ World(Test::Unit::Assertions)
@@ -0,0 +1,21 @@
1
+ class Array
2
+ def to_ranges
3
+ array = self.compact.uniq.sort
4
+ ranges = []
5
+ if !array.empty?
6
+ # Initialize the left and right endpoints of the range
7
+ left, right = self.first, nil
8
+ array.each do |obj|
9
+ # If the right endpoint is set and obj is not equal to right's successor
10
+ # then we need to create a range.
11
+ if right && obj != right.succ
12
+ ranges << Range.new(left,right)
13
+ left = obj
14
+ end
15
+ right = obj
16
+ end
17
+ ranges << Range.new(left,right)
18
+ end
19
+ ranges
20
+ end
21
+ end
@@ -0,0 +1,70 @@
1
+ require 'array'
2
+
3
+ class Fugu
4
+ attr_accessor :text, :delimiter
5
+
6
+ def self.puff(string)
7
+ f = self.new
8
+ f.text = string
9
+ f.puff
10
+ end
11
+
12
+ def puff
13
+ @text.split('|').collect do |range|
14
+ if range.match(/\{/)
15
+ before, expand_string, after = range.scan(/(.*)\{(.*)\}(.*)/)[0]
16
+ expanded_string = puff_expression(expand_string)
17
+ range = expanded_string.map { |piece| before + piece + after }
18
+ end
19
+ range
20
+ end.flatten
21
+ end
22
+
23
+ def puff!
24
+ @text = puff
25
+ end
26
+
27
+ def puff_expression(string)
28
+ string.split(",").collect do |v|
29
+ (v[/-/]) ? Range.new(*pad_expression(v).split('-')).to_a : v
30
+ end.flatten
31
+ end
32
+
33
+ def self.shrink(string, delimiter)
34
+ f = self.new
35
+ f.text = string
36
+ f.delimiter = delimiter
37
+ f.shrink
38
+ end
39
+
40
+ def shrink
41
+ pieces = @text.split("#{@delimiter}")
42
+ first, base = pieces.first, pieces.first
43
+ first.size.times do |len|
44
+ base = first[0, first.size-len]
45
+ break if pieces.all? {|p| p.match(base)}
46
+ end
47
+ diffs = pieces.map {|p| (p.scan(/./) - base.scan(/./)).join}
48
+ base + "{#{shrink_array(diffs)}}"
49
+ end
50
+
51
+ def shrink!
52
+ @text = shrink
53
+ end
54
+
55
+ def shrink_array(array)
56
+ array.flatten.to_ranges.map do |r|
57
+ if r.first == r.last
58
+ r.first
59
+ else
60
+ "#{r.first}-#{r.last}"
61
+ end
62
+ end.join(",")
63
+ end
64
+
65
+ def pad_expression(string)
66
+ fat = string.split('-')
67
+ "%0#{fat.last.length}d-#{fat.last}" % fat.first.to_i
68
+ end
69
+ end
70
+
@@ -0,0 +1,19 @@
1
+ require 'test_helper'
2
+
3
+ class FuguTest < Test::Unit::TestCase
4
+ def setup
5
+ @fugu = Fugu.new
6
+ end
7
+
8
+ should "puff a string like {1-3}" do
9
+ assert_equal %w[1 2 3], @fugu.puff_expression("1-3")
10
+ end
11
+
12
+ should "shrink a string like 1,2,3" do
13
+ assert_equal "1-3", @fugu.shrink_array(%w[1 2 3])
14
+ end
15
+
16
+ should "pad expression with appropriate number of zeros" do
17
+ assert_equal "01-10", @fugu.pad_expression("1-10")
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'fugu'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fugu
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.0
5
+ platform: ruby
6
+ authors:
7
+ - Erik Kastner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-07 00:00:00 -05:00
13
+ default_executable: fugu
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: cucumber
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: "Puff: host0{9-10} to host09 host10"
36
+ email: kastner@gmail.com
37
+ executables:
38
+ - fugu
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - LICENSE
43
+ - README.rdoc
44
+ files:
45
+ - .document
46
+ - .gitignore
47
+ - LICENSE
48
+ - README.rdoc
49
+ - Rakefile
50
+ - VERSION
51
+ - bin/fugu
52
+ - features/puff.feature
53
+ - features/shrink.feature
54
+ - features/step_definitions/fugu_steps.rb
55
+ - features/support/env.rb
56
+ - lib/array.rb
57
+ - lib/fugu.rb
58
+ - test/fugu_test.rb
59
+ - test/test_helper.rb
60
+ has_rdoc: true
61
+ homepage: http://github.com/kastner/fugu
62
+ licenses: []
63
+
64
+ post_install_message:
65
+ rdoc_options:
66
+ - --charset=UTF-8
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ version:
81
+ requirements: []
82
+
83
+ rubyforge_project:
84
+ rubygems_version: 1.3.5
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: Magically puff or shrink strings
88
+ test_files:
89
+ - test/fugu_test.rb
90
+ - test/test_helper.rb