stringray 1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ lib/spec/rake/verify_ratio.rb
2
+ lib/stringray.rb
3
+ Rakefile
4
+ README.mkdn
5
+ spec/stringray_spec.rb
6
+ .manifest
@@ -0,0 +1,41 @@
1
+ StringRay
2
+ =========
3
+
4
+ **StringRay** exposes a powerful method to split a `String` into an `Array` of words,
5
+ and further allows you to include `Enumerable`, thus exposing many of the
6
+ most useful `Array` methods on your `String`s.
7
+
8
+ Usage
9
+ -----
10
+
11
+ class String; include StringRay; end
12
+
13
+ "Oi! I'm a string, do something fun with me!".each do |word|
14
+ p word
15
+ end
16
+
17
+ Getting
18
+ -------
19
+
20
+ The authoritative source for this project is available at
21
+ <http://github.com/elliottcable/stringray>. You can clone your own copy with the
22
+ following command:
23
+
24
+ git clone git://github.com/elliottcable/stringray.git
25
+
26
+ If you want to make changes to the codebase, you need to fork your own GitHub
27
+ repository for said changes. Send a pullrequest to [elliottcable](http://github.com/elliottcable "elliottcable on GitHub")
28
+ when you've got something ready for the master branch that you think should be
29
+ merged.
30
+
31
+ Requirements
32
+ ------------
33
+
34
+ To run git-blog, you need... nothing!
35
+
36
+ To develop and contribute to git-blog, you also need:
37
+
38
+ * `gem install rake`
39
+ * `gem install rspec`
40
+ * `gem install rcov`
41
+ * `gem install echoe`
@@ -0,0 +1,98 @@
1
+ ($:.unshift File.expand_path(File.join( File.dirname(__FILE__), 'lib' ))).uniq!
2
+ require 'stringray'
3
+ require 'merb-extlib/string' # String#/, because I'm a lazy fuck.
4
+ require 'rake'
5
+ require 'rake/rdoctask'
6
+ require 'spec/rake/spectask'
7
+ require 'spec/rake/verify_rcov'
8
+ require 'spec/rake/verify_ratio'
9
+
10
+ begin
11
+ require 'echoe'
12
+
13
+ namespace :echoe do
14
+ Echoe.new('StringRay', StringRay::VERSION) do |g|
15
+ g.name = 'stringray'
16
+ g.author = ['elliottcable']
17
+ g.email = ['StringRay@elliottcable.com']
18
+ g.summary = 'Combining many of the benefits of Arrays and Strings, StringRay allows you to treat a String as an Array of words in many cases.'
19
+ g.url = 'http://github.com/elliottcable/stringray'
20
+ g.dependencies = []
21
+ g.manifest_name = '.manifest'
22
+ g.ignore_pattern = ['.git', 'meta', 'stringray.gemspec']
23
+ end
24
+
25
+ desc 'tests packaged files to ensure they are all present'
26
+ task :verify => :package do
27
+ # An error message will be displayed if files are missing
28
+ if system %(ruby -e "require 'rubygems'; require 'merb-core'; require 'pkg/merb_strokedb-#{Merb::Orms::StrokeDB::VERSION}/lib/merb_strokedb'")
29
+ puts "\nThe library files are present"
30
+ end
31
+ end
32
+
33
+ task :copy_gemspec => [:package] do
34
+ pkg = Dir['pkg/*'].select {|dir| File.directory? dir}.last
35
+ mv File.join(pkg, pkg.gsub(/^pkg\//,'').gsub(/\-\d+$/,'.gemspec')), './'
36
+ end
37
+
38
+ desc 'builds a gemspec as GitHub wants it'
39
+ task :gemspec => [:package, :copy_gemspec, :clobber_package]
40
+
41
+ # desc 'Run specs, clean tree, update manifest, run coverage, and install gem!'
42
+ desc 'Clean tree, update manifest, and install gem!'
43
+ task :magic => [:clean, :manifest, :install]
44
+ end
45
+
46
+ task :manifest => [:'echoe:manifest']
47
+
48
+ rescue LoadError => boom
49
+ puts "You are missing a dependency required for meta-operations on this gem."
50
+ puts "#{boom.to_s.capitalize}."
51
+ ensure
52
+ task :default # No effect # Invisible
53
+
54
+ # Runs specs, generates rcov, and opens rcov in your browser.
55
+ namespace :rcov do
56
+ Spec::Rake::SpecTask.new(:run) do |t|
57
+ t.spec_opts = ["--format", "specdoc", "--colour"]
58
+ t.spec_files = Dir['spec/**/*_spec.rb'].sort
59
+ t.libs = ['lib']
60
+ t.rcov = true
61
+ t.rcov_dir = 'meta' / 'coverage'
62
+ end
63
+
64
+ Spec::Rake::SpecTask.new(:plain) do |t|
65
+ t.spec_opts = ["--format", "specdoc"]
66
+ t.spec_files = Dir['spec/**/*_spec.rb'].sort
67
+ t.libs = ['lib']
68
+ t.rcov = true
69
+ t.rcov_opts = ['--exclude-only', '".*"', '--include-file', '^lib']
70
+ t.rcov_dir = 'meta' / 'coverage'
71
+ end
72
+
73
+ RCov::VerifyTask.new(:verify) do |t|
74
+ t.threshold = 100
75
+ t.index_html = 'meta' / 'coverage' / 'index.html'
76
+ end
77
+
78
+ Spec::Rake::VerifySpecRatioTask.new(:ratio) do |t|
79
+ t.ratio = 1.00
80
+ end
81
+
82
+ task :open do
83
+ system 'open ' + 'meta' / 'coverage' / 'index.html' if PLATFORM['darwin']
84
+ end
85
+ end
86
+
87
+ namespace :git do
88
+ task :status do
89
+ `git status`
90
+ end
91
+ end
92
+
93
+ desc 'Check everything over before commiting'
94
+ task :aok => [:'echoe:manifest', :'rcov:run', :'rcov:verify', :'rcov:ratio', :'rcov:open', :'git:status']
95
+
96
+ # desc 'Task run during continuous integration' # Invisible
97
+ task :cruise => [:'rcov:plain', :'rcov:verify', :'rcov:ratio']
98
+ end
@@ -0,0 +1,77 @@
1
+
2
+ # Gem::Specification for Stringray-1
3
+ # Originally generated by Echoe
4
+
5
+ --- !ruby/object:Gem::Specification
6
+ name: stringray
7
+ version: !ruby/object:Gem::Version
8
+ version: "1"
9
+ platform: ruby
10
+ authors:
11
+ - elliottcable
12
+ autorequire:
13
+ bindir: bin
14
+
15
+ date: 2008-08-11 00:00:00 -08:00
16
+ default_executable:
17
+ dependencies:
18
+ - !ruby/object:Gem::Dependency
19
+ name: echoe
20
+ type: :development
21
+ version_requirement:
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: "0"
27
+ version:
28
+ description: Combining many of the benefits of Arrays and Strings, StringRay allows you to treat a String as an Array of words in many cases.
29
+ email:
30
+ - StringRay@elliottcable.com
31
+ executables: []
32
+
33
+ extensions: []
34
+
35
+ extra_rdoc_files:
36
+ - lib/spec/rake/verify_ratio.rb
37
+ - lib/stringray.rb
38
+ - README.mkdn
39
+ files:
40
+ - lib/spec/rake/verify_ratio.rb
41
+ - lib/stringray.rb
42
+ - Rakefile
43
+ - README.mkdn
44
+ - spec/stringray_spec.rb
45
+ - .manifest
46
+ - StringRay.gemspec
47
+ has_rdoc: true
48
+ homepage: http://github.com/elliottcable/stringray
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --line-numbers
52
+ - --inline-source
53
+ - --title
54
+ - StringRay
55
+ - --main
56
+ - README.mkdn
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "="
68
+ - !ruby/object:Gem::Version
69
+ version: "1.2"
70
+ version:
71
+ requirements: []
72
+
73
+ rubyforge_project: stringray
74
+ rubygems_version: 1.2.0
75
+ specification_version: 2
76
+ summary: Combining many of the benefits of Arrays and Strings, StringRay allows you to treat a String as an Array of words in many cases.
77
+ test_files: []
@@ -0,0 +1,78 @@
1
+ module Spec
2
+ module Rake
3
+
4
+ # A task that can verify that the ratio of (lines of spec)
5
+ # over (lines of code) doesn't drop below a certain threshold.
6
+ # It should be run after running Spec::Rake::SpecTask.
7
+ class VerifySpecRatioTask < ::Rake::TaskLib
8
+ # Name of the task. Defaults to :verify_spec_ratio
9
+ attr_accessor :name
10
+
11
+ # Glob pattern to match code files. (default is '**/*.rb')
12
+ # Automatically excludes everything matching +spec_pattern+
13
+ attr_accessor :pattern
14
+
15
+ # Glob pattern to match spec files. (default is 'spec/**/*_spec.rb')
16
+ attr_accessor :spec_pattern
17
+
18
+ # Whether or not to output details. Defaults to true.
19
+ attr_accessor :verbose
20
+
21
+ # The threshold value (in decimal value) for ratio. If the
22
+ # actual ratio is not above this value, the task will raise an
23
+ # exception. The ratio is devised as LoS/LoC, so values above 1
24
+ # mean expressive specs, while values below one mean weak specs.
25
+ attr_accessor :ratio
26
+
27
+ def initialize(name=:verify_spec_ratio)
28
+ @name = name
29
+ @pattern = '**/*.rb'
30
+ @spec_pattern = 'spec/**/*_spec.rb'
31
+ @verbose = true
32
+ yield self if block_given?
33
+ raise "Ratio must be set" if @ratio.nil?
34
+ define_task
35
+ end
36
+
37
+ def define_task
38
+ desc "Verify that spec-ratio is at least #{@ratio}%"
39
+ task @name do
40
+ loc = 0
41
+ los = 0
42
+
43
+ code_files = Dir[@pattern]
44
+ spec_files = Dir[@spec_pattern]
45
+
46
+ code_files.each do |code_file|
47
+ next if spec_files.include? code_file
48
+ code = File.open(code_file)
49
+
50
+ code.each_line do |line|
51
+ line.gsub! /#(.*)/, '' # Get rid of all comments
52
+ line.gsub! /\s/, '' # Get rid of all whitespace
53
+ loc += 1 unless line.empty?
54
+ end
55
+ end
56
+
57
+ spec_files.each do |spec_file|
58
+ spec = File.open(spec_file)
59
+
60
+ spec.each_line do |line|
61
+ line.gsub! /#(.*)/, '' # Get rid of all comments
62
+ line.gsub! /\s/, '' # Get rid of all whitespace
63
+ los += 1 unless line.empty?
64
+ end
65
+ end
66
+
67
+ ratio = (los.to_f / loc.to_f)
68
+
69
+ puts "Spec-ratio: #{los}/#{loc} (#{ratio.to_s[0..3]}, expected >=: #{@ratio})" if @verbose
70
+ raise "Spec-ratio must be above #{@ratio} but was #{ratio.to_s[0..3]}" if ratio < @ratio
71
+ raise "Your spec-ratio file pattern matched no files" if loc == 0
72
+ raise "Your spec-ratio specfile pattern matched no files" if los == 0
73
+ end
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,128 @@
1
+ module StringRay
2
+ VERSION = 1
3
+
4
+ # Splits a string into words. Not using the obvious names (+#split+, +#words+)
5
+ # because I want compatibility for inclusion into +String+.
6
+ def enumerate
7
+ ray = []
8
+
9
+ self.each_byte do |byte|
10
+ char = byte.chr
11
+
12
+ if Delimiter::Characters.include? char
13
+ ray << Delimiter.new(char)
14
+
15
+ elsif Whitespace::Characters.include? char
16
+ if ray.last.is_a? Whitespace
17
+ ray.last << char
18
+ else
19
+ ray << Whitespace.new(char)
20
+ end
21
+
22
+ else
23
+ if ray.last.is_a? Word
24
+ ray.last << char
25
+ else
26
+ ray << Word.new(char)
27
+ end
28
+
29
+ end
30
+ end
31
+
32
+ ray
33
+ end
34
+
35
+ # More sensible than +String#each+, this uses +#enumerate+ to enumerate on
36
+ # words. Accepts options as a hash, determining whether :whitespace and
37
+ # :delemiters will :attach_before, :standalone, or :attach_after. Default is
38
+ # for both to :attach_before.
39
+ def each_word opts = {}, &block
40
+ {:whitespace => :attach_before, :delemiters => :attach_before}.merge! opts
41
+
42
+ # First, we create a two-dimensional array of words with any whitespace or
43
+ # delemiters that should attach to them.
44
+ words = self.enumerate
45
+ mapped = []
46
+ attach_before_next = []
47
+
48
+ words.each do |item|
49
+ case item
50
+ when Delimiter
51
+ case opts[:delemiters]
52
+ when :standalone
53
+ mapped << [item]
54
+ when :attach_after
55
+ attach_before_next << item
56
+ else
57
+ if attach_before_next.empty?
58
+ mapped.last << item
59
+ else
60
+ attach_before_next << item
61
+ end
62
+ end
63
+
64
+ when Whitespace
65
+ case opts[:whitespace]
66
+ when :standalone
67
+ mapped << [item]
68
+ when :attach_after
69
+ attach_before_next << item
70
+ else
71
+ if attach_before_next.empty?
72
+ mapped.last << item
73
+ else
74
+ attach_before_next << item
75
+ end
76
+ end
77
+
78
+ when Word
79
+ if not attach_before_next.empty?
80
+ mapped << [attach_before_next, item].flatten
81
+ attach_before_next = []
82
+ else
83
+ mapped << [item]
84
+ end
85
+
86
+ end
87
+ end
88
+ (mapped.last << attach_before_next).flatten! if not attach_before_next.empty?
89
+
90
+ # Next, we yield each group of (word plus delimiters and whitespace) as a
91
+ # normal string to the block
92
+ mapped.each do |arr|
93
+ yield arr.map{|w|w.to_s}.join
94
+ end
95
+ end
96
+
97
+ class Word < String
98
+ def inspect
99
+ "(#{self})"
100
+ end
101
+ end
102
+
103
+ class Whitespace < String
104
+ Characters = [" ", "\t", "\n"]
105
+ def inspect
106
+ "#{self}"
107
+ end
108
+ end
109
+
110
+ class Delimiter < String
111
+ Characters = ['-', ',', '.', '?', '!']
112
+
113
+ def inspect
114
+ "<#{self}>"
115
+ end
116
+ end
117
+
118
+ # This overrides +String#each+ with +StringRay#each_word+, thus allowing us
119
+ # to include +Enumerable+.
120
+ def self.included klass
121
+ klass.class_eval do
122
+ alias_method :each_at, :each
123
+ alias_method :each, :each_word
124
+
125
+ include Enumerable
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,75 @@
1
+ require 'stringray'
2
+
3
+ describe 'a String including StringRay' do
4
+ before :all do
5
+ String.send :include, StringRay
6
+ end
7
+
8
+ describe '#enumerate' do
9
+ it 'should split a string into an array' do
10
+ string = 'The time has come to talk of many things - of sailing ' +
11
+ 'ships and sealing wax, of cabbages and kings!'
12
+ array = []
13
+ string.each {|i| array << i }
14
+ array.should == ['The ','time ','has ','come ','to ','talk ','of ',
15
+ 'many ','things - ','of ','sailing ','ships ','and ','sealing ',
16
+ 'wax, ','of ','cabbages ','and ','kings!']
17
+ end
18
+ end
19
+
20
+ describe '#each_word' do
21
+ it 'should be able to attach delimeters to the beginning of the next word' do
22
+ string = 'The time has come to talk of many things - of sailing ' +
23
+ 'ships and sealing wax, of cabbages and kings!'
24
+ array = []
25
+ string.each(:delemiters => :attach_after) {|i| array << i }
26
+ array.should == ['The ','time ','has ','come ','to ','talk ','of ',
27
+ 'many ','things ','- of ','sailing ','ships ','and ','sealing ',
28
+ 'wax',', of ','cabbages ','and ','kings!']
29
+ end
30
+
31
+ it 'should be able to let delimeters stand alone' do
32
+ string = 'The time has come to talk of many things - of sailing ' +
33
+ 'ships and sealing wax, of cabbages and kings!'
34
+ array = []
35
+ string.each(:delemiters => :standalone) {|i| array << i }
36
+ array.should == ['The ','time ','has ','come ','to ','talk ','of ',
37
+ 'many ','things ','- ', 'of ','sailing ','ships ','and ','sealing ',
38
+ 'wax',', ','of ','cabbages ','and ','kings','!']
39
+ end
40
+
41
+ it 'should be able to attach whitespace to the beginning of the next word' do
42
+ string = 'The time has come to talk of many things - of sailing ' +
43
+ 'ships and sealing wax, of cabbages and kings!'
44
+ array = []
45
+ string.each(:whitespace => :attach_after) {|i| array << i }
46
+ array.should == ['The',' time',' has',' come',' to',' talk',' of',
47
+ ' many',' things',' - of',' sailing',' ships',' and',' sealing',
48
+ ' wax,',' of',' cabbages',' and',' kings!']
49
+ end
50
+
51
+ it 'should be able to let whitespace stand alone' do
52
+ string = 'The time has come to talk of many things - of sailing ' +
53
+ 'ships and sealing wax, of cabbages and kings!'
54
+ array = []
55
+ string.each(:whitespace => :standalone) {|i| array << i }
56
+ array.should == ['The',' ','time',' ','has',' ','come',' ','to',' ','talk',' ','of',
57
+ ' ','many',' ','things',' -',' ','of',' ','sailing',' ','ships',' ','and',' ','sealing',
58
+ ' ','wax,',' ','of',' ','cabbages',' ','and',' ','kings!']
59
+ end
60
+
61
+ it 'should be able to not split a delimated word' do
62
+ pending "Figure out a way to allow delemiters to _not_ split words " +
63
+ "- i.e. 'K-I-S-S-I-N-G' should be passed as a single word."
64
+
65
+ string = "String and Array, sitting in a tree - K-I-S-S-I-N-G!"
66
+ array = string.map
67
+ array.should == ['String ','and ','Array, ','sitting ','in ','a ','tree - ','K-','I-','S-','S-','I-','N-','G!']
68
+ end
69
+ end
70
+
71
+ # TODO: Figure out a better way to say 'should be_include(Enumerable)'
72
+ it 'should also include enumerable' do
73
+ String.ancestors.should be_include(Enumerable)
74
+ end
75
+ end
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stringray
3
+ version: !ruby/object:Gem::Version
4
+ version: "1"
5
+ platform: ruby
6
+ authors:
7
+ - elliottcable
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-08-11 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: echoe
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
+ description: Combining many of the benefits of Arrays and Strings, StringRay allows you to treat a String as an Array of words in many cases.
26
+ email:
27
+ - StringRay@elliottcable.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - lib/spec/rake/verify_ratio.rb
34
+ - lib/stringray.rb
35
+ - README.mkdn
36
+ files:
37
+ - lib/spec/rake/verify_ratio.rb
38
+ - lib/stringray.rb
39
+ - Rakefile
40
+ - README.mkdn
41
+ - spec/stringray_spec.rb
42
+ - .manifest
43
+ - StringRay.gemspec
44
+ has_rdoc: true
45
+ homepage: http://github.com/elliottcable/stringray
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --line-numbers
49
+ - --inline-source
50
+ - --title
51
+ - StringRay
52
+ - --main
53
+ - README.mkdn
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "="
65
+ - !ruby/object:Gem::Version
66
+ version: "1.2"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project: stringray
71
+ rubygems_version: 1.2.0
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: Combining many of the benefits of Arrays and Strings, StringRay allows you to treat a String as an Array of words in many cases.
75
+ test_files: []
76
+