fast 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  pkg/*
2
2
  *.gem
3
3
  .bundle
4
+ .rbx
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - jruby-18mode
7
+ - jruby-19mode
8
+ - rbx-18mode
9
+ - rbx-19mode
10
+ - ree
data/Gemfile CHANGED
@@ -2,3 +2,7 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in fast.gemspec
4
4
  gemspec
5
+
6
+ group :test do
7
+ gem "rake"
8
+ end
@@ -1,14 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fast (0.1.2)
4
+ fast (0.1.4)
5
5
  metafun (>= 0.2.0)
6
+ sub-setter (>= 0.0.2)
6
7
 
7
8
  GEM
8
9
  remote: http://rubygems.org/
9
10
  specs:
10
11
  diff-lcs (1.1.3)
11
12
  metafun (0.2.0)
13
+ rake (0.9.2.2)
12
14
  rspec (2.8.0)
13
15
  rspec-core (~> 2.8.0)
14
16
  rspec-expectations (~> 2.8.0)
@@ -17,6 +19,7 @@ GEM
17
19
  rspec-expectations (2.8.0)
18
20
  diff-lcs (~> 1.1.2)
19
21
  rspec-mocks (2.8.0)
22
+ sub-setter (0.0.2)
20
23
  zucker (12.1)
21
24
 
22
25
  PLATFORMS
@@ -24,5 +27,6 @@ PLATFORMS
24
27
 
25
28
  DEPENDENCIES
26
29
  fast!
30
+ rake
27
31
  rspec
28
32
  zucker
@@ -0,0 +1,122 @@
1
+ Fast
2
+ ====
3
+
4
+ [![Build Status](https://secure.travis-ci.org/xaviervia/fast.png)](http://travis-ci.org/xaviervia/fast)
5
+
6
+ Tired of having a hard time working with files? Take a look at Fast...
7
+
8
+ require "fast"
9
+
10
+ lib_dir = dir! :lib # Creates a new dir "lib"
11
+
12
+ lib_dir["demo.txt"] = "I love creating files from a Hash-like API"
13
+ # Creates lib/demo.txt containing the text
14
+
15
+ lib_dir.list # => ['demo.txt']
16
+
17
+ file! "lib/empty.txt" # New file lib/empty.txt
18
+
19
+ lib_dir.files do |path|
20
+ puts path
21
+ end # => demo.txt
22
+ # empty.txt
23
+
24
+ lib_dir.destroy
25
+
26
+ dir? :lib # => false
27
+
28
+ ...and finally is **quite stable** so you can use it if you wish so.
29
+
30
+ Fast is a DSL for file and dir handling focused in intuitivity and semantics. Fast is pure Ruby, don't relays on OS functions, so is a little slower but more portable.
31
+
32
+ Installation
33
+ ------------
34
+
35
+ gem install fast
36
+
37
+ Usage
38
+ -----
39
+
40
+ Fast declares two sets of methods in its DSL:
41
+
42
+ ### Dir methods
43
+
44
+ dir :lib # The same as => Fast::Dir.new "lib"
45
+ dir.delete! "demo" # The same as => Fast::Dir.new.delete! "demo"
46
+
47
+ dir! :new_dir # The same as => Fast::Dir.new.create! :new_dir
48
+ dir? :new_dir # The same as => Fast::Dir.new.exist? :new_dir
49
+
50
+ ### File methods
51
+
52
+ file "demo.txt" # The same as => Fast::File.new "demo.txt"
53
+ file.copy "demo.txt", "new.txt" # The same as =>
54
+ # Fast::File.new.copy "demo.txt", "new.txt"
55
+
56
+ file! "demo.txt" # The same as => Fast::File.new.create! "demo.txt"
57
+ file? "demo.txt" # The same as => Fast::File.new.exist? "demo.txt"
58
+
59
+ Philosophy
60
+ ----------
61
+
62
+ *Fast* embraces the more straightforward view of files as strings of data and directories as arrays of files/directories. Why?
63
+
64
+ * It is more realistic in everyday usage
65
+ * It makes them more object-like (and thus, more friendly to OOP)
66
+ * It is more semantic
67
+ * Files as IOs are still accessible through the harder-to-use native Ruby API
68
+
69
+ <tt>Fast::Dir</tt> is a subclass of <tt>Array</tt>, usable as a hash, and <tt>Fast::File</tt> if a subclass of String.
70
+
71
+ Conflicts
72
+ ---------
73
+
74
+ It is a known issue that the DSL of Fast conflicts with [Pry][pry-gem] and most notable with [Rake][rake-gem]; I am aware that is a bold move to reclaim `file` from the standard namespace for Fast to use.
75
+
76
+ In order to workaround that, you can require fast in a not-so-much DSL way:
77
+
78
+ require "fast/fast"
79
+
80
+ Fast.file "myfile.txt" # The same as `file "myfile.txt"`
81
+
82
+ Fast.dir! :lib # etc...
83
+
84
+ This is also the recommended form when using Fast in the context of a library.
85
+
86
+ > Also: try to avoid using Fast in a library, because Fast is mostly semantic sugar and you want to avoid adding loading time just for the sake of having a couple of convenience methods. Fast is more fun when used for code sketching and simple scripts.
87
+
88
+ [pry-gem]: https://github.com/pry/pry
89
+ [rake-gem]: http://rake.rubyforge.org/
90
+
91
+ Quick notes (to self)
92
+ ---------------------
93
+
94
+ * Rename FilesystemObject: Item, CommonMethods, AbstractFile, FastHelpers (think!)
95
+ * Deliberate whether is a good idea to make Fast::Dir and Fast::File Multitons. (May be only when an absolute path is used)
96
+ * The path can be setted indirectly by any method of Fast::File instances, and the same works for Dir. This is fine because allows for very quick calls, but once an instance gets a path setted it should be fixed and raise an exception in case some other method call is trying to change it.
97
+
98
+ ### Fast::File
99
+ * Read bytes as binary ASCII-8BIT always and then try to perform an heuristic conversion, if there is any reasonable way to do it. Otherwise, leave it to the user. Google: "ruby string encode utf-8 ascii" for some good readings.
100
+
101
+ ### Fast::Dir
102
+ * Calls to #dirs and #files should delegate to a SubSetter
103
+ * Change the behaviour in the calls to #dirs and #files: return a new instance, with no @path setted.
104
+ * Change the behaviour in the initialization: call #list always if there's a path an the path matches an existing directory
105
+ * Allow for easy recursive calls (#list_all, #files_all, #dirs_all for example, think of better synonyms)
106
+ * Deliberate whether "#<<" should be kept in Fast::Dir and if it should be used as alias for merge
107
+ * An instance of Fast::Dir should be possible to be created from a Array. (pity I didn't specified an usage case)
108
+ * Add documentation to Patterns::Adapter::Fast::Dir
109
+
110
+ Remote future
111
+ -------------
112
+
113
+ * Make Fast a REST client (well, use <tt>rest-client</tt>) in order to transparently use files and directories from a compliant REST server.
114
+ * Include REST methods: Dir#post, File#get, File#head, etc and equivalents for local files (prepare ground for Piano Rest)
115
+ * Allow Files to behave as Dirs with the right method calls
116
+
117
+ License
118
+ -------
119
+
120
+ GPL License. Why other?
121
+
122
+ @ Xavier Via
@@ -15,7 +15,8 @@ Gem::Specification.new do |s|
15
15
  s.rubyforge_project = "fast"
16
16
 
17
17
  s.add_dependency "metafun", ">= 0.2.0"
18
-
18
+ s.add_dependency "sub-setter", ">= 0.0.2"
19
+
19
20
  s.add_development_dependency "rspec"
20
21
  s.add_development_dependency "zucker"
21
22
 
@@ -1,4 +1,5 @@
1
1
  require "metafun/delegator"
2
+ require "sub-setter"
2
3
 
3
4
  require "fast/fast"
4
5
 
@@ -2,7 +2,13 @@ require "sub-setter/fast/dir" # This call should be automated in the sub-setter
2
2
 
3
3
  module Fast
4
4
  # Directory handling class
5
+ #
6
+ # Inherits from Array in order to be usable as a Array
7
+ # Includes the module Fast::FilesystemObject for common
8
+ # functionality with Fast::File
5
9
  class Dir < Array
10
+ include FilesystemObject
11
+
6
12
  def initialize path = nil
7
13
  super()
8
14
  @path = normalize path if path
@@ -55,8 +61,20 @@ module Fast
55
61
  if args.length > 0
56
62
  return_me = nil
57
63
  args.each do |path|
58
- raise ArgumentError, "Dir '#{path}' already exists" if Dir.new.exist? path
59
- return_me = do_create path
64
+ unless path.is_a? Hash
65
+ raise ArgumentError, "Dir '#{path}' already exists" if Dir.new.exist? path
66
+ return_me = do_create path
67
+ else
68
+ if @path
69
+ subdir = Dir.new.create! "#{@path}"
70
+ else
71
+ subdir = Dir.new "."
72
+ end
73
+ path.each do |item_name, item_content|
74
+ subdir[item_name] = item_content
75
+ end
76
+ return subdir
77
+ end
60
78
  end
61
79
  return return_me
62
80
  else
@@ -72,7 +90,19 @@ module Fast
72
90
  if args.length > 0
73
91
  return_me = nil
74
92
  args.each do |path|
75
- return_me = do_create path
93
+ unless path.is_a? Hash
94
+ return_me = do_create path
95
+ else
96
+ if @path
97
+ subdir = Dir.new.create! "#{@path}"
98
+ else
99
+ subdir = Dir.new "."
100
+ end
101
+ path.each do |item_name, item_content|
102
+ subdir[item_name] = item_content
103
+ end
104
+ return subdir
105
+ end
76
106
  end
77
107
  return return_me
78
108
  else
@@ -125,15 +155,7 @@ module Fast
125
155
  alias :destroy! :delete!
126
156
  alias :del! :delete!
127
157
  alias :unlink! :delete!
128
-
129
- # Checks for existence. True if the directory exists, false otherwise
130
- def exist? path = nil
131
- @path = normalize path if path
132
- ::File.directory? @path
133
- end
134
-
135
- alias :exists? :exist?
136
-
158
+
137
159
  # Returns true if all passed dirs exist, false otherwise
138
160
  def exist_all? *args
139
161
  unless args.empty?
@@ -172,32 +194,17 @@ module Fast
172
194
 
173
195
  return existing_ones
174
196
  end
197
+
198
+ # This will be ported to a pattern exactly like SubSetter
199
+ def to
200
+ Patterns::Adapter::Fast::Dir.new self
201
+ end
175
202
 
176
203
  # Returns a String brief of the dir
177
204
  def to_s
178
205
  return "#{@path}"
179
206
  end
180
-
181
- # Sends self to a SubSetter for Fast::Dir
182
- def filter
183
- SubSetter::Fast::Dir.new self
184
- end
185
-
186
- alias :by :filter
187
207
 
188
- # Expands the path to absolute is it is relative
189
- def expand path = nil
190
- @path = normalize path if path
191
- ::File.expand_path @path
192
- end
193
-
194
- alias :absolute :expand
195
-
196
- # Returns the path to the dir, if defined
197
- def path
198
- @path if @path
199
- end
200
-
201
208
  # Renames this dir into the target path, unless the target path
202
209
  # points to an existing dir.
203
210
  def rename *args
@@ -297,6 +304,37 @@ module Fast
297
304
  end
298
305
  end
299
306
  end
307
+
308
+ # Checks the given dirs should be merged if any conflict would arise.
309
+ #
310
+ # Returns true if any file in the target directory has the same
311
+ # path (ie: the same name and subdirectory structure) as other file
312
+ # in the source directory.
313
+ def conflicts_with? *args
314
+ if args.length > 1
315
+ current, target = *args
316
+ @path = normalize current
317
+ target = Dir.new target
318
+ else
319
+ target = Dir.new args.first
320
+ end
321
+
322
+ files do |file|
323
+ target.files do |target_file|
324
+ return true if file == target_file
325
+ end
326
+ end
327
+
328
+ dirs do |dir|
329
+ target.dirs do |target_dir|
330
+ if dir == target_dir
331
+ return true if Fast::Dir.new.conflicts_with? "#{@path}/#{dir}", "#{target.path}/#{target_dir}"
332
+ end
333
+ end
334
+ end
335
+
336
+ false
337
+ end
300
338
 
301
339
  private
302
340
  def do_delete path = nil
@@ -345,9 +383,9 @@ module Fast
345
383
 
346
384
  target_dir
347
385
  end
348
-
349
- def normalize path
350
- "#{path}"
386
+
387
+ def do_exist? path
388
+ ::File.directory? path
351
389
  end
352
390
  end
353
391
  end
@@ -0,0 +1,3 @@
1
+ module Fast
2
+ class PathNotSettedException < ArgumentError; end
3
+ end
@@ -1,5 +1,8 @@
1
+ require "fast/filesystemobject"
1
2
  require "fast/file"
2
3
  require "fast/dir"
4
+ require "fast/exceptions"
5
+ require "patterns/adapter/fast/dir"
3
6
 
4
7
  module Fast
5
8
  # Returns a Dir with the file list already called (if a path is provided)
@@ -2,7 +2,12 @@ require "sub-setter/fast/file" # This call should be automated in the sub-sette
2
2
 
3
3
  module Fast
4
4
  # File handling class.
5
+ #
6
+ # Inherits from String in order to be usable as a String
7
+ # Includes the module Fast::FilesystemObject for common
8
+ # functionality with Fast::Dir
5
9
  class File < String
10
+ include FilesystemObject
6
11
 
7
12
  # Initializes the file
8
13
  def initialize source = nil
@@ -112,19 +117,17 @@ module Fast
112
117
  alias :create! :touch
113
118
 
114
119
  # Returns the contents of the file, all at once
115
- def read path = nil
120
+ def read path = nil, &block
116
121
  @path = normalize path if path
117
- ::File.read @path
122
+ unless block
123
+ ::File.read @path
124
+ else
125
+ ::File.open @path, "r" do |the_file|
126
+ block.call the_file
127
+ end
128
+ end
118
129
  end
119
130
 
120
- # Returns true if file exists, false otherwise
121
- def exist? path = nil
122
- @path = normalize path if path
123
- do_check_existence @path
124
- end
125
-
126
- alias :exists? :exist?
127
-
128
131
  def exist_all? *args
129
132
  unless args.empty?
130
133
  return_me = true
@@ -157,21 +160,6 @@ module Fast
157
160
  end
158
161
  return_list
159
162
  end
160
-
161
- # Sends self to a SubSetter for Fast::File
162
- def filter
163
- SubSetter::Fast::File.new self
164
- end
165
-
166
- alias :by :filter
167
-
168
- # Expands the path if it's a relative path
169
- def expand path = nil
170
- @path = normalize path if path
171
- ::File.expand_path @path
172
- end
173
-
174
- alias :absolute :expand
175
163
 
176
164
  # Renames the file (by Fast::File own means, it does not call
177
165
  # the underlying OS). Fails if the new path is an existent file
@@ -206,12 +194,7 @@ module Fast
206
194
  end
207
195
 
208
196
  alias :move! :rename!
209
-
210
- # Returns the path to the current file
211
- def path
212
- @path if @path
213
- end
214
-
197
+
215
198
  # Appends the contents of the target file into self and erase the target
216
199
  def merge *args
217
200
  if args.length > 1
@@ -263,11 +246,7 @@ module Fast
263
246
  do_copy target
264
247
  end
265
248
 
266
- private
267
- def normalize path
268
- "#{path}"
269
- end
270
-
249
+ private
271
250
  def do_copy target
272
251
  target.write read
273
252
  target
@@ -291,7 +270,7 @@ module Fast
291
270
  self
292
271
  end
293
272
 
294
- def do_check_existence path
273
+ def do_exist? path
295
274
  ::File.exist?(path) && !::File.directory?(path)
296
275
  end
297
276