fugu 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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