fast 0.1.3 → 0.1.4

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.
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