sugar-high 0.4.0 → 0.4.3

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.
Files changed (34) hide show
  1. data/VERSION +1 -1
  2. data/lib/sugar-high/array.rb +58 -7
  3. data/lib/sugar-high/class_ext.rb +11 -0
  4. data/lib/sugar-high/enumerable.rb +67 -0
  5. data/lib/sugar-high/file.rb +24 -76
  6. data/lib/sugar-high/file_ext.rb +65 -0
  7. data/lib/sugar-high/file_mutate.rb +45 -192
  8. data/lib/sugar-high/file_mutate/append_content.rb +17 -0
  9. data/lib/sugar-high/file_mutate/delete.rb +29 -0
  10. data/lib/sugar-high/file_mutate/insert_content.rb +62 -0
  11. data/lib/sugar-high/file_mutate/mutate.rb +58 -0
  12. data/lib/sugar-high/file_mutate/overwrite_content.rb +17 -0
  13. data/lib/sugar-high/file_mutate/remove_content.rb +33 -0
  14. data/lib/sugar-high/file_mutate/replace_content.rb +45 -0
  15. data/lib/sugar-high/kind_of.rb +8 -43
  16. data/lib/sugar-high/string.rb +5 -0
  17. data/spec/fixtures/application_file.rb +1 -0
  18. data/spec/fixtures/class_file.rb +15 -0
  19. data/spec/fixtures/content_file.txt +1 -0
  20. data/spec/fixtures/file.txt +1 -0
  21. data/spec/fixtures/routes_file.rb +16 -0
  22. data/spec/sugar-high/array_spec.rb +44 -3
  23. data/spec/sugar-high/file/file_dsl_spec.rb +4 -0
  24. data/spec/sugar-high/file_mutate/append_content_spec.rb +60 -0
  25. data/spec/sugar-high/file_mutate/delete_spec.rb +47 -0
  26. data/spec/sugar-high/file_mutate/insert_before_last_spec.rb +56 -0
  27. data/spec/sugar-high/file_mutate/insert_content_spec.rb +111 -0
  28. data/spec/sugar-high/file_mutate/overwrite_content_spec.rb +80 -0
  29. data/spec/sugar-high/file_mutate/remove_content_spec.rb +109 -0
  30. data/spec/sugar-high/file_mutate/replace_content_spec.rb +33 -0
  31. data/spec/sugar-high/{file/file_spec.rb → file_spec.rb} +1 -0
  32. data/sugar-high.gemspec +26 -27
  33. metadata +27 -28
  34. data/spec/sugar-high/file/file_mutate_spec.rb +0 -325
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.0
1
+ 0.4.3
@@ -1,26 +1,56 @@
1
1
  require 'sugar-high/kind_of'
2
+ require 'sugar-high/enumerable'
2
3
  require 'sugar-high/path'
3
4
 
4
5
  class Array
5
- def to_symbols option=nil
6
- res = self.flatten
7
- res.map!{|a| a.kind_of?(Fixnum) ? "_#{a}" : a} if option == :num
8
- res.select_labels.map(&:to_s).map(&:to_sym)
6
+ def to_symbols
7
+ self.flatten.select_labels.map{|a| a.to_s.to_sym }
9
8
  end
10
9
 
10
+ def to_symbols!
11
+ self.flatten!.select_labels!.map!{|a| a.to_s.to_sym }
12
+ end
13
+
14
+ def to_symbols_num
15
+ self.flatten.map{|a| a.kind_of?(Fixnum) ? "_#{a}" : a}.map{|a| a.to_s.to_sym }
16
+ end
17
+
18
+ def to_symbols_num!
19
+ self.flatten!.map!{|a| a.kind_of?(Fixnum) ? "_#{a}" : a}..map!{|a| a.to_s.to_sym }
20
+ end
21
+
22
+ def to_symbols_uniq
23
+ to_symbols.uniq
24
+ end
25
+
26
+ def to_symbols_uniq!
27
+ to_symbols!.uniq!
28
+ end
29
+
11
30
  def to_strings
12
- self.flatten.select_labels.map(&:to_s)
31
+ self.flatten!.select_labels!.map!(&:to_s)
32
+ end
33
+
34
+ def to_strings!
35
+ self.flatten.select_labels!.map!(&:to_s)
13
36
  end
14
37
 
15
38
  def to_filenames
16
39
  self.to_strings.map(&:underscore)
17
40
  end
18
41
 
42
+ def to_filenames!
43
+ self.to_strings!.map!(&:underscore)
44
+ end
19
45
 
20
46
  def to_paths
21
47
  self.map(&:path)
22
48
  end
23
49
 
50
+ def to_paths!
51
+ self.map!(&:path)
52
+ end
53
+
24
54
  def file_join
25
55
  File.join(*self.flatten)
26
56
  end
@@ -29,14 +59,35 @@ class Array
29
59
  self.map{|fp| fp.path.to_file }
30
60
  self.extend FilesArray
31
61
  end
62
+
63
+ def to_files!
64
+ self.map!{|fp| fp.path.to_file }
65
+ self.extend FilesArray
66
+ end
32
67
 
33
68
  def none?
34
69
  self.flatten.compact.empty?
35
70
  end
36
71
 
37
- def flat_uniq
72
+ def flat_uniq
38
73
  self.flatten.compact.uniq
39
- end
74
+ end
75
+
76
+ def flat_uniq!
77
+ self.flatten!.compact!.uniq!
78
+ end
79
+
80
+ def extract(sym)
81
+ map { |e| e.send(sym) }
82
+ end
83
+
84
+ def sum
85
+ inject( 0 ) { |sum,x| sum + x }
86
+ end
87
+
88
+ def mean
89
+ (size > 0) ? sum.to_f / size : 0
90
+ end
40
91
  end
41
92
 
42
93
  module FilesArray
@@ -0,0 +1,11 @@
1
+ class Class
2
+ def include_and_extend(the_module, options={})
3
+ options[:instance_methods] ||= :InstanceMethods
4
+ options[:class_methods] ||= :ClassMethods
5
+ # Mainly include but be flexible
6
+ main_module = const_get(the_module)
7
+ include main_module # for an extend_and_include method, change this to extend main_module
8
+ include main_module.const_get(options[:instance_methods]) if main_module.const_defined?(options[:instance_methods])
9
+ extend main_module.const_get(options[:class_methods]) if main_module.const_defined?(options[:class_methods])
10
+ end
11
+ end
@@ -0,0 +1,67 @@
1
+ module Enumerable
2
+ def only_kinds_of? *kinds
3
+ all?{|a| a.any_kind_of? *kinds }
4
+ end
5
+
6
+ def only_labels?
7
+ all?{|a| a.kind_of_label? }
8
+ end
9
+
10
+ def select_kinds_of *kinds
11
+ select{|a| a.any_kind_of? *kinds }
12
+ end
13
+
14
+ def select_kinds_of! *kinds
15
+ select!{|a| a.any_kind_of? *kinds }
16
+ end
17
+
18
+ def select_labels
19
+ select{|a| a.kind_of_label? }
20
+ end
21
+
22
+ def select_labels!
23
+ select! {|a| a.kind_of_label? }
24
+ end
25
+
26
+
27
+ def select_symbols
28
+ select_only :symbol
29
+ end
30
+
31
+ def select_symbols!
32
+ select_only! :symbol
33
+ end
34
+
35
+ def select_uniq_symbols!
36
+ select_only!(:symbol).uniq!
37
+ end
38
+
39
+ def select_strings
40
+ select_only :string
41
+ end
42
+
43
+ def select_strings
44
+ select_only :string
45
+ end
46
+
47
+ def select_only type
48
+ const = type.kind_of_label? ? "#{type.to_s.camelize}".constantize : type
49
+ select{|a| a.kind_of? const}
50
+ end
51
+
52
+ def select_only! type
53
+ const = type.kind_of_label? ? "#{type.to_s.camelize}".constantize : type
54
+ select!{|a| a.kind_of? const}
55
+ end
56
+
57
+ def all_kinds
58
+ map do |a|
59
+ case a
60
+ when Kinds
61
+ a.kinds
62
+ else
63
+ a if a.kind_of?(Module)
64
+ end
65
+ end.compact.uniq.flatten
66
+ end
67
+ end
@@ -4,67 +4,36 @@ require 'sugar-high/path'
4
4
  require 'sugar-high/regexp'
5
5
  require 'sugar-high/string'
6
6
  require 'sugar-high/file_mutate'
7
+ require 'sugar-high/file_ext'
7
8
 
8
9
  class File
9
- def self.blank? file_name
10
- raise ArgumentError, "Filename argument must not be blank" if file_name.blank?
11
- raise ArgumentError, "There is no file at: #{file_name}" if !File.file?(file_name)
12
- File.zero?(file_name)
13
- end
14
-
15
- def blank?
16
- File.zero?(self.path)
17
- end
10
+ include SugarHigh::FileExt
11
+ extend SugarHigh::FileExt::ClassMethods
12
+ end
18
13
 
19
- def self.has_content? file_name, content_matcher, &block
20
- File.new(file_name).has_content? content_matcher, &block
14
+ class Symbol
15
+ def as_filename
16
+ self.to_s.underscore
21
17
  end
22
-
23
- def has_content? content_matcher = nil, &block
24
- content_matcher ||= yield
25
- begin
26
- content_matcher = content_matcher.to_regexp
27
- rescue
28
- raise ArgumentError, "Content match must be specified as either a String or Regexp"
29
- end
30
- !(self.read =~ content_matcher).nil?
18
+
19
+ def valid_file_command?
20
+ [:read, :remove, :delete].include? self
31
21
  end
22
+
23
+ def file
24
+ as_filename.file
25
+ end
26
+ end
32
27
 
33
- def read_content options = {}, &block
34
- File.read_from self.path, options, &block
28
+ class NilClass
29
+ def valid_file_command?
30
+ false
35
31
  end
36
- alias_method :with_content, :read_content
37
-
38
- class << self
39
-
40
- def read_from file_name, options = {}, &block
41
- raise ArgumentError, "File to read from not found or not a file: #{file_name}" if !File.file? file_name
42
- content = File.read file_name
43
-
44
- if options[:before]
45
- begin
46
- regexp = options[:before].to_regexp
47
- index = content.match(regexp).offset_before
48
- content = content[0..index]
49
- rescue
50
- raise ArgumentError, ":before option must be a string or regular expression, was : #{options[:before]}"
51
- end
52
- end
32
+ end
53
33
 
54
- if options[:after]
55
- begin
56
- regexp = options[:after].to_regexp
57
- index = content.match(regexp).offset_after
58
- content = content[index..-1]
59
- rescue
60
- raise ArgumentError, ":after option must be a string or regular expression, was : #{options[:after]}"
61
- end
62
- end
63
- yield content if block
64
- content
65
- end
66
- alias_method :read_content_from, :read_from
67
- alias_method :with_content_from, :read_from
34
+ class Array
35
+ def file_names ext = '*'
36
+ self.map{|a| a.gsub( /(.*)\//, '').gsub(/\.#{Regexp.escape(ext.to_s)}/, '')}
68
37
  end
69
38
  end
70
39
 
@@ -72,7 +41,7 @@ class String
72
41
  def as_filename
73
42
  self.underscore
74
43
  end
75
-
44
+
76
45
  def valid_file_command?
77
46
  self.to_sym.valid_file_command?
78
47
  end
@@ -86,7 +55,7 @@ class String
86
55
  return ::Dir.new(self) if ::File.directory?(self)
87
56
  raise "No file found at #{self}"
88
57
  end
89
-
58
+
90
59
  def new_file
91
60
  begin
92
61
  file
@@ -96,24 +65,3 @@ class String
96
65
  end
97
66
  end
98
67
 
99
- class Symbol
100
- def as_filename
101
- self.to_s.underscore
102
- end
103
-
104
- def valid_file_command?
105
- [:read, :remove, :delete].include? self
106
- end
107
- end
108
-
109
- class NilClass
110
- def valid_file_command?
111
- false
112
- end
113
- end
114
-
115
- class Array
116
- def file_names ext = '*'
117
- self.map{|a| a.gsub( /(.*)\//, '').gsub(/\.#{Regexp.escape(ext.to_s)}/, '')}
118
- end
119
- end
@@ -0,0 +1,65 @@
1
+ module SugarHigh
2
+ module FileExt
3
+ module ClassMethods
4
+ def blank? file_name
5
+ raise ArgumentError, "Filename argument must not be blank" if file_name.blank?
6
+ raise ArgumentError, "There is no file at: #{file_name}" if !File.file?(file_name)
7
+ File.zero?(file_name)
8
+ end
9
+
10
+ def has_content? file_name, content_matcher, &block
11
+ file = get_file file_name
12
+ file.has_content? content_matcher, &block
13
+ end
14
+
15
+ def read_from file_name, options = {}, &block
16
+ raise ArgumentError, "File to read from not found or not a file: #{file_name}" if !File.file? file_name
17
+ content = File.read file_name
18
+
19
+ if options[:before]
20
+ begin
21
+ regexp = options[:before].to_regexp
22
+ index = content.match(regexp).offset_before
23
+ content = content[0..index]
24
+ rescue
25
+ raise ArgumentError, ":before option must be a string or regular expression, was : #{options[:before]}"
26
+ end
27
+ end
28
+
29
+ if options[:after]
30
+ begin
31
+ regexp = options[:after].to_regexp
32
+ index = content.match(regexp).offset_after
33
+ content = content[index..-1]
34
+ rescue
35
+ raise ArgumentError, ":after option must be a string or regular expression, was : #{options[:after]}"
36
+ end
37
+ end
38
+ yield content if block
39
+ content
40
+ end
41
+ alias_method :read_content_from, :read_from
42
+ alias_method :with_content_from, :read_from
43
+ end
44
+
45
+ def blank?
46
+ File.zero?(self.path)
47
+ end
48
+
49
+ def has_content? content_matcher = nil, &block
50
+ content_matcher ||= yield
51
+ begin
52
+ content_matcher = content_matcher.to_regexp
53
+ rescue
54
+ raise ArgumentError, "Content match must be specified as either a String or Regexp"
55
+ end
56
+ matched = self.read_content =~ content_matcher
57
+ !(matched).nil?
58
+ end
59
+
60
+ def read_content options = {}, &block
61
+ File.read_from self.path, options, &block
62
+ end
63
+ alias_method :with_content, :read_content
64
+ end
65
+ end
@@ -4,203 +4,56 @@ require 'sugar-high/path'
4
4
  require 'sugar-high/regexp'
5
5
  require 'sugar-high/string'
6
6
  require 'sugar-high/file'
7
-
8
- class File
9
- class << self
10
- def delete! name
11
- return nil if !File.exist?(name)
12
- File.delete name
7
+ require 'sugar-high/array'
8
+
9
+ require 'sugar-high/file_mutate/delete'
10
+ require 'sugar-high/file_mutate/overwrite_content'
11
+ require 'sugar-high/file_mutate/append_content'
12
+ require 'sugar-high/file_mutate/remove_content'
13
+ require 'sugar-high/file_mutate/replace_content'
14
+ require 'sugar-high/file_mutate/insert_content'
15
+ require 'sugar-high/file_mutate/extras'
16
+
17
+ require 'sugar-high/class_ext'
18
+ require 'active_support/inflector'
19
+
20
+ module SugarHigh
21
+ module FileMutate
22
+ autoload :Mutate, 'sugar-high/file_mutate/mutate'
23
+ autoload :Delete, 'sugar-high/file_mutate/delete'
24
+ autoload :AppendContent, 'sugar-high/file_mutate/append_content'
25
+ autoload :InsertContent, 'sugar-high/file_mutate/insert_content'
26
+ autoload :OverwriteContent, 'sugar-high/file_mutate/overwrite_content'
27
+ autoload :RemoveContent, 'sugar-high/file_mutate/remove_content'
28
+ autoload :ReplaceContent, 'sugar-high/file_mutate/replace_content'
29
+ end
30
+ end
31
+
32
+
33
+ class File
34
+ def self.mutate_ext name
35
+ if name == :all
36
+ add_mutate_exts mutate_apis
37
+ return
13
38
  end
14
- alias_method :delete_file!, :delete!
15
- end
16
-
17
- def delete!
18
- File.delete(self.path)
39
+ raise ArgumentError, "Unknown FileMutate API: #{name}, must be one of: #{mutate_apis}" if !mutate_apis.include? name
40
+ add_mutate_exts [:mutate, name]
19
41
  end
20
- alias_method :delete_file!, :delete!
21
42
 
43
+ protected
22
44
 
23
- def overwrite content=nil, &block
24
- File.overwrite self.path, content, &block
25
- end
26
-
27
- def self.overwrite file, content=nil, &block
28
- filepath = case file
29
- when PathString, String
30
- file
31
- when File
32
- file.path
33
- else
34
- raise ArgumentError, "Expected first argument to be a File instance or a path indicating file to overwrite"
35
- end
36
- File.open(filepath, 'w') do |f|
37
- f.puts content ||= yield
38
- end
39
- end
40
-
41
- def append content=nil, &block
42
- File.append self.path, content, &block
43
- end
44
-
45
- def self.append path, content=nil, &block
46
- File.open(path, 'a') do |f|
47
- f.puts content ||= yield
48
- end
49
- end
50
-
51
- def remove_content options=nil, &block
52
- opt_str = case options
53
- when String
54
- options
55
- when Hash
56
- content = options[:content] || options[:where]
57
- raise ArgumentError, "Bad :content value in Hash" if !content || content.strip.empty?
58
- content.strip
59
- else
60
- raise ArgumentError, "non-block argument must be either String or Hash with a :content option" if !block
61
- end
62
- content = block ? yield : opt_str
63
- File.remove_content_from self.path, :content => content, :with => '', &block
64
- end
65
- alias_method :remove, :remove_content
66
-
67
- def self.remove_from file_name, content=nil, &block
68
- content ||= yield
69
- replace_content_from file_name, :content => content, :with => '', &block
70
- end
71
-
72
- def self.remove_content_from file_name, options = {}, &block
73
- replace_content_from file_name, options.merge(:with => ''), &block
74
- end
75
-
76
- def replace_content options = {}, &block
77
- File.replace_content_from self.path, options, &block
78
- end
79
-
80
- # replaces content found at replacement_expr with content resulting from yielding block
81
- # File.replace_content_from 'myfile.txt', where => /HelloWorld/, with => 'GoodBye'
82
- def self.replace_content_from file_name, options = {}, &block
83
- replacement_expr = options[:where] || options[:content]
84
- new_content = options[:with]
85
-
86
- begin
87
- replacement_expr = replacement_expr.to_regexp
88
- rescue
89
- raise ArgumentError, "Content to be replaced must be specified as either a String or Regexp in a :where or :content option"
90
- end
91
-
92
- # get existing file content
93
- content = File.read file_name
94
-
95
- # return nil if no mathing replacement found
96
- return nil if !(content =~ replacement_expr)
97
-
98
- new_content ||= yield if block
99
-
100
- raise ArgumentError, "Content to be replaced with must be specified as a :with option or as a block" if !new_content
101
-
102
- # remove content that matches expr, by replacing with empty
103
- mutated_content = content.gsub replacement_expr, new_content
104
-
105
- # write mutated content as new file
106
- File.overwrite file_name, mutated_content
107
-
108
- true # signal success!
109
- end
110
-
111
- def insert *args, &block
112
- File.insert_into self.path, *args, &block
113
- end
45
+ def self.mutate_apis
46
+ [:delete, :mutate, :append_content, :insert_content, :overwrite_content, :remove_content, :replace_content]
47
+ end
114
48
 
115
- # insert_into 'my_file.txt', :after => 'Blip', :content => 'Hello
116
- # insert_into 'my_file.txt', 'Hello', :after => 'Blip'
117
- # insert_into 'my_file.txt', :after => 'Blip' do
118
- # 'Hello'
119
- # end
120
- def self.insert_into file_name, *args, &block
121
- options = last_option args
122
- content = Insert.content options, *args, &block
123
-
124
- file = File.new(file_name)
125
- return nil if !File.exist?(file)
126
-
127
- # already inserted?
128
- return nil if content.blank?
129
- return nil if !options[:repeat] && (file.read =~ /#{Regexp.escape(content.to_s)}/)
130
-
131
- place, marker = if options[:before]
132
- [ :before, options[:before] ]
133
- elsif options[:before_last]
134
- [ :before_last, options[:before_last] ]
135
- else
136
- [ :after, options[:after] ]
137
- end
138
-
139
- marker = Insert.get_marker marker
140
- marker_found = (File.new(file.path).read =~ /#{marker}/)
141
- return nil if !marker_found
142
-
143
- res = Mutate.mutate_file file.path, marker, place do
144
- content
49
+ def self.add_mutate_exts *names
50
+ names.flat_uniq.each do |api|
51
+ ns = "SugarHigh::FileMutate::#{api.to_s.camelize}"
52
+ begin
53
+ self.send :include, ns.constantize
54
+ self.extend "#{ns}::ClassMethods".constantize
55
+ end
145
56
  end
146
- res
147
- end
148
-
149
- module EscapedString
150
- def escaped?
151
- true
152
- end
153
- end
154
-
155
- module Insert
156
- def self.get_marker marker
157
- return marker if marker.respond_to?(:escaped?) && marker.escaped?
158
- marker = case marker
159
- when Regexp
160
- marker
161
- when String
162
- Regexp.escape(marker).extend(EscapedString)
163
- end
164
- end
165
-
166
- def self.content options = {}, *args, &block
167
- case args.first
168
- when String
169
- args.first
170
- when Hash
171
- options[:content] || (yield if block)
172
- else
173
- return yield if block
174
- raise ArgumentError, "You must supply content to insert, either as a String before the options hash, a :content option or a block"
175
- end
176
- end
177
- end
178
-
179
- module Mutate
180
- def self.mutate_file file, marker, place, &block
181
- raise ArgumentError, "You must define a replacement marker for a :before, :before_last or :after key" if !marker
182
-
183
- if place == :before_last
184
- content = File.read(file)
185
- content = content.insert_before_last yield, marker
186
- File.open(file, 'wb') { |file| file.write(content) }
187
- return
188
- end
189
-
190
- marker = Insert.get_marker marker
191
-
192
- marker_found = (File.new(file.path).read =~ /#{marker}/)
193
- return nil if !marker_found
194
-
195
- replace_in_file file, /(#{marker})/mi do |match|
196
- place == :after ? "#{match}\n #{yield}" : "#{yield}\n #{match}"
197
- end
198
- true
199
- end
200
-
201
- def self.replace_in_file(path, regexp, *args, &block)
202
- content = File.read(path).gsub(regexp, *args, &block)
203
- File.open(path, 'wb') { |file| file.write(content) }
204
- end
205
57
  end
58
+
206
59
  end