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 +1 -0
- data/.travis.yml +10 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +5 -1
- data/README.md +122 -0
- data/fast.gemspec +2 -1
- data/lib/fast.rb +1 -0
- data/lib/fast/dir.rb +73 -35
- data/lib/fast/exceptions.rb +3 -0
- data/lib/fast/fast.rb +3 -0
- data/lib/fast/file.rb +16 -37
- data/lib/fast/filesystemobject.rb +69 -0
- data/lib/fast/version.rb +1 -1
- data/lib/patterns/adapter/fast/dir.rb +19 -0
- data/lib/sub-setter/fast/dir.rb +8 -0
- data/spec/fast/dir_spec.rb +152 -94
- data/spec/fast/file_spec.rb +72 -80
- data/spec/fast/filesystemobject_spec.rb +309 -0
- data/spec/patterns/adapter/fast/dir_spec.rb +16 -0
- data/spec/sub-setter/fast/dir_spec.rb +20 -0
- metadata +47 -10
- data/README.rdoc +0 -81
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fast (0.1.
|
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
|
data/README.md
ADDED
@@ -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
|
data/fast.gemspec
CHANGED
data/lib/fast.rb
CHANGED
data/lib/fast/dir.rb
CHANGED
@@ -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
|
-
|
59
|
-
|
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
|
-
|
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
|
350
|
-
|
386
|
+
|
387
|
+
def do_exist? path
|
388
|
+
::File.directory? path
|
351
389
|
end
|
352
390
|
end
|
353
391
|
end
|
data/lib/fast/fast.rb
CHANGED
data/lib/fast/file.rb
CHANGED
@@ -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
|
-
|
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
|
273
|
+
def do_exist? path
|
295
274
|
::File.exist?(path) && !::File.directory?(path)
|
296
275
|
end
|
297
276
|
|