ptools 1.1.9-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES ADDED
@@ -0,0 +1,105 @@
1
+ == 1.1.9 - 25-Mar-2010
2
+ * Refactored File.which and File.whereis and added additional tests for each.
3
+ * Removed the block form of File.whereis.
4
+ * Reorganized the Rakefile a bit and put the test tasks under the 'test'
5
+ namespace, and the gem tasks under the 'gem' namespace.
6
+ * Updated the test-unit development dependency.
7
+ * Updates the README.
8
+
9
+ == 1.1.8 - 6-Oct-2009
10
+ * Fixed some bad variable names that crept into the File.nl_convert method.
11
+ * Added the File.null_device alias for File.null.
12
+ * Added cygwin and mingw to Windows detection code.
13
+ * One of the nlconvert tests is now skipped on Windows.
14
+ * Two text files that were previously bundled as part of this library for
15
+ testing purposes have been removed. Those are now dynamically generated
16
+ within the tests themselves.
17
+ * Gemspec updates.
18
+ * Documentation updates.
19
+ * Added the :gem rake task.
20
+
21
+ == 1.1.7 - 28-Jul-2009
22
+ * Now compatible with Ruby 1.9.x.
23
+ * Replaced RUBY_PLATFORM with rbconfig check for the sake of other
24
+ implementations, such as JRuby.
25
+ * Updated the tests to be more friendly to JRuby.
26
+ * Added Test::Unit 2.x as a development dependency.
27
+ * Renamed the test files.
28
+
29
+ == 1.1.6 - 31-Aug-2007
30
+ * Fixed the File.touch method so that it doesn't whack existing files. Thanks
31
+ go to Thomas Preymesser for the spot.
32
+ * Added corresponding tests to the tc_touch.rb file.
33
+
34
+ == 1.1.5 - 19-Jul-2007
35
+ * Added the File.image? method. Inspired by ruby-talk: 260487.
36
+
37
+ == 1.1.4 - 21-May-2007
38
+ * Removed the install.rb file. Installation is now handled exclusively by the
39
+ rake install task.
40
+ * Updated the MANIFEST file, and made it rdoc friendly.
41
+ * Manual installation corrections in the README file.
42
+
43
+ == 1.1.3 - 29-Apr-2007
44
+ * I changed the way that the constants IS_WINDOWS and WIN32EXTS are defined.
45
+ * The IS_WINDOWS and WIN32EXTS are no long documented publically. They were
46
+ never meant for public use.
47
+ * The tc_constants.rb file was modified to only run certain tests on Windows.
48
+
49
+ == 1.1.2 - 28-Apr-2007
50
+ * Fixed a require line that could cause problems on MS Windows.
51
+ * Added a Rakefile which includes tasks for installation and testing.
52
+ * Some cleanup and improvement in the various test files.
53
+
54
+ == 1.1.1 - 24-Aug-2006
55
+ * Added the File.binary? method, based on code from Ryan Davis.
56
+
57
+ == 1.1.0 - 23-Aug-2006
58
+ * Added the File.null method which returns the bit bucket on your platform.
59
+ * The suffixes on MS Windows are now based on the PATHEXT environment variable,
60
+ and defaults to '.com', '.bat' and '.exe' only if it's not defined.
61
+ * The File.which and File.whereis methods were tweaked a bit for Windows so
62
+ that they ignore the case of suffixes.
63
+ * Modified the platform checking and path separator handling.
64
+ * Added and tweaked some tests.
65
+
66
+ == 1.0.0 - 2-Jun-2005
67
+ * Modified the File.middle method to accept an optional block.
68
+ * File.whereis is now limited to unique values so that redundant PATH entries
69
+ do not cause redundant entries in the returned array (or block).
70
+ * File.nl_convert and File.touch now return self.
71
+ * File.nl_convert now raises ArgumentError (instead of StandardError) if
72
+ an unknown platform is provided.
73
+ * File.wc now raises ArgumentError (instead of RuntimeError) if a bad option
74
+ is provided.
75
+ * Made documentation rdoc friendly.
76
+ * Test suite updates, corrections and additions.
77
+ * Removed the INSTALL file. See the README instead.
78
+ * Moved project to RubyForge.
79
+
80
+ == 0.1.3 - 5-Dec-2003
81
+ * Modified File#which and File#whereis for Win32 to handle extensions better,
82
+ i.e. you can send "ruby" or "ruby.exe" and get back the same result.
83
+ * Minor test changes to tc_which.rb and tc_whereis.rb.
84
+
85
+ == 0.1.2 - 14-May-2003
86
+ * Modified nl_convert() to allow the destination filename to be the same as the
87
+ source file. In that case, a tempfile is used and copied back over the
88
+ original file.
89
+ * The target file name for nl_convert() now defaults to the source file name and
90
+ the default format is now "dos".
91
+ * Added a tc_constants.rb test suite.
92
+ * Test suite additions/fixes.
93
+ * Updates to MANIFEST.
94
+
95
+ == 0.1.1 - 21-Mar-2003
96
+ * Modified File.tail to return data in the same order that 'tail' does.
97
+ * Modified File.which to return nil if the program is not found.
98
+ * Modified File.whereis now uses '\' instead of '/' on MS Windows.
99
+ * Added File.middle class method.
100
+ * Test suite modification & additions.
101
+ * Thanks go to Shanko for both the spot and patch for tail, which, whereis
102
+ and middle.
103
+
104
+ == 0.1.0 - 18-Mar-2003
105
+ * Initial release
@@ -0,0 +1,17 @@
1
+ * CHANGES
2
+ * README
3
+ * MANIFEST
4
+ * Rakefile
5
+ * ptools.gemspec
6
+ * lib/ptools.rb
7
+ * test/test_constants.rb
8
+ * test/test_head.rb
9
+ * test/test_image.rb
10
+ * test/test_middle.rb
11
+ * test/test_nlconvert.rb
12
+ * test/test_null.rb
13
+ * test/test_tail.rb
14
+ * test/test_touch.rb
15
+ * test/test_wc.rb
16
+ * test/test_which.rb
17
+ * test/test_whereis.rb
data/README ADDED
@@ -0,0 +1,64 @@
1
+ == Description
2
+ The ptools (power tools) library is an additional set of commands for the
3
+ File class based on Unix command line tools.
4
+
5
+ == Prerequisites
6
+ On MS Windows you will need win32-file 0.5.4 or later.
7
+
8
+ == Installation
9
+ gem install ptools
10
+
11
+ == Synopsis
12
+ require "ptools"
13
+
14
+ File.which("ruby") # '/usr/local/bin/ruby'
15
+ File.whereis("ruby") # ['/usr/local/bin/ruby','/opt/bin/ruby']
16
+
17
+ File.head("myfile") # Returns first 10 lines of 'myfile'
18
+ File.middle("myfile",8,12) # Returns lines 8-12 of 'myfile'
19
+ File.tail("myfile",3) # Returns last 3 lines of 'myfile'
20
+ File.wc("myfile",'words') # Returns the number of words in 'myfile'
21
+
22
+ File.touch("newfile") # "newfile" now exists
23
+ File.null # '/dev/null' on Unix, 'NUL' on Windows
24
+ File.binary?('some_file') # true or false
25
+
26
+ # Creates a copy of 'myfile' called 'newfile', in DOS format
27
+ File.nl_convert("myfile", "newfile", "dos")
28
+
29
+ == Known Bugs
30
+ None known. Please report any bugs on the github or RubyForge project page.
31
+
32
+ http://www.rubyforge.org/projects/shards
33
+ http://www.github.com/djberg96/ptools
34
+
35
+ == Acknowledgements
36
+ The File.which method was originally adopted from the FileWhich code posted
37
+ by Michael Granger on the now defunct rubygarden.org website. That code was
38
+ later replaced by a version based on the ruby-which library.
39
+
40
+ The File.nl_convert method is based on the nlcvt program found at
41
+ http://www.perl.com/language/ppt/src/nlcvt/nlcvt, written by Tom Christiansen.
42
+
43
+ The middle() method was provided by Shashank Date.
44
+
45
+ The binary?() method was based almost entirely on a blog post by Ryan
46
+ Davis (who, in turn, based his code on Perl's -B switch).
47
+
48
+ == Future Plans
49
+ Add whatever other tools people think might be useful.
50
+
51
+ == License
52
+ Artistic 2.0
53
+
54
+ == Copyright
55
+ (C) 2003-2010 Daniel J. Berger
56
+ All Rights Reserved.
57
+
58
+ == Warranty
59
+ This package is provided "as is" and without any express or
60
+ implied warranties, including, without limitation, the implied
61
+ warranties of merchantability and fitness for a particular purpose.
62
+
63
+ == Author
64
+ Daniel J. Berger
@@ -0,0 +1,110 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rbconfig'
4
+ include Config
5
+
6
+ desc 'Install the ptools package (non-gem)'
7
+ task :install do
8
+ sitelibdir = CONFIG["sitelibdir"]
9
+ file = "lib/ptools.rb"
10
+ FileUtils.cp(file, sitelibdir, :verbose => true)
11
+ end
12
+
13
+ namespace 'gem' do
14
+ desc 'Create the ptools gem'
15
+ task :create do
16
+ Dir["*.gem"].each{ |f| File.delete(f) } # Clean first
17
+ spec = eval(IO.read('ptools.gemspec'))
18
+ Gem::Builder.new(spec).build
19
+ end
20
+
21
+ desc 'Install the ptools gem'
22
+ task :install => [:create] do
23
+ file = Dir["*.gem"].first
24
+ sh "gem install #{file}"
25
+ end
26
+ end
27
+
28
+ Rake::TestTask.new do |t|
29
+ t.verbose = true
30
+ t.warning = true
31
+ end
32
+
33
+ namespace 'test' do
34
+ Rake::TestTask.new('binary') do |t|
35
+ t.libs << 'test'
36
+ t.verbose = true
37
+ t.warning = true
38
+ t.test_files = FileList['test/test_binary.rb']
39
+ end
40
+
41
+ Rake::TestTask.new('constants') do |t|
42
+ t.libs << 'test'
43
+ t.verbose = true
44
+ t.warning = true
45
+ t.test_files = FileList['test/test_constants.rb']
46
+ end
47
+
48
+ Rake::TestTask.new('head') do |t|
49
+ t.libs << 'test'
50
+ t.verbose = true
51
+ t.warning = true
52
+ t.test_files = FileList['test/test_head.rb']
53
+ end
54
+
55
+ Rake::TestTask.new('middle') do |t|
56
+ t.libs << 'test'
57
+ t.verbose = true
58
+ t.warning = true
59
+ t.test_files = FileList['test/test_middle.rb']
60
+ end
61
+
62
+ Rake::TestTask.new('nlconvert') do |t|
63
+ t.libs << 'test'
64
+ t.verbose = true
65
+ t.warning = true
66
+ t.test_files = FileList['test/test_nlconvert.rb']
67
+ end
68
+
69
+ Rake::TestTask.new('null') do |t|
70
+ t.libs << 'test'
71
+ t.verbose = true
72
+ t.warning = true
73
+ t.test_files = FileList['test/test_null.rb']
74
+ end
75
+
76
+ Rake::TestTask.new('tail') do |t|
77
+ t.libs << 'test'
78
+ t.verbose = true
79
+ t.warning = true
80
+ t.test_files = FileList['test/test_tail.rb']
81
+ end
82
+
83
+ Rake::TestTask.new('touch') do |t|
84
+ t.libs << 'test'
85
+ t.verbose = true
86
+ t.warning = true
87
+ t.test_files = FileList['test/test_touch.rb']
88
+ end
89
+
90
+ Rake::TestTask.new('wc') do |t|
91
+ t.libs << 'test'
92
+ t.verbose = true
93
+ t.warning = true
94
+ t.test_files = FileList['test/test_wc.rb']
95
+ end
96
+
97
+ Rake::TestTask.new('whereis') do |t|
98
+ t.libs << 'test'
99
+ t.verbose = true
100
+ t.warning = true
101
+ t.test_files = FileList['test/test_whereis.rb']
102
+ end
103
+
104
+ Rake::TestTask.new('which') do |t|
105
+ t.libs << 'test'
106
+ t.verbose = true
107
+ t.warning = true
108
+ t.test_files = FileList['test/test_which.rb']
109
+ end
110
+ end
@@ -0,0 +1,406 @@
1
+ require 'rbconfig'
2
+
3
+ if Config::CONFIG['host_os'] =~ /mswin|dos|win32|cygwin|mingw/i
4
+ require 'win32/file'
5
+ end
6
+
7
+ class File
8
+ # The version of the ptools library.
9
+ PTOOLS_VERSION = '1.1.9'
10
+
11
+ # :stopdoc:
12
+
13
+ # The WIN32EXTS string is used as part of a Dir[] call in certain methods.
14
+ if Config::CONFIG['host_os'] =~ /mswin|dos|win32|cygwin|mingw/i
15
+ MSWINDOWS = true
16
+ if ENV['PATHEXT']
17
+ WIN32EXTS = ('.{' + ENV['PATHEXT'].tr(';', ',').tr('.','') + '}').downcase
18
+ else
19
+ WIN32EXTS = '.{exe,com,bat}'
20
+ end
21
+ else
22
+ MSWINDOWS = false
23
+ end
24
+
25
+ IMAGE_EXT = %w/.bmp .gif .jpg .jpeg .png/
26
+
27
+ # :startdoc:
28
+
29
+ # Returns whether or not the file is an image. Only JPEG, PNG, BMP and
30
+ # GIF are checked against.
31
+ #
32
+ # This method does some simple read and extension checks. For a version
33
+ # that is more robust, but which depends on a 3rd party C library (and is
34
+ # difficult to build on MS Windows), see the 'filemagic' library, available
35
+ # on the RAA.
36
+ #
37
+ # Examples:
38
+ #
39
+ # File.image?('somefile.jpg') # => true
40
+ # File.image?('somefile.txt') # => true
41
+ #--
42
+ # The approach I used here is based on information found at
43
+ # http://en.wikipedia.org/wiki/Magic_number_(programming)
44
+ #
45
+ def self.image?(file)
46
+ bool = IMAGE_EXT.include?(File.extname(file).downcase) # Match ext
47
+ bool = bmp?(file) || jpg?(file) || png?(file) || gif?(file) # Check data
48
+ bool
49
+ end
50
+
51
+ # Returns the name of the null device (aka bitbucket) on your platform.
52
+ #
53
+ # Examples:
54
+ #
55
+ # # On Linux
56
+ # File.null # => '/dev/null'
57
+ #
58
+ # # On MS Windows
59
+ # File.null # => 'NUL'
60
+ #--
61
+ # The values I used here are based on information from
62
+ # http://en.wikipedia.org/wiki//dev/null
63
+ #
64
+ def self.null
65
+ case Config::CONFIG['host_os']
66
+ when /mswin|win32|msdos|cygwin|mingw/i
67
+ 'NUL'
68
+ when /amiga/i
69
+ 'NIL:'
70
+ when /openvms/i
71
+ 'NL:'
72
+ else
73
+ '/dev/null'
74
+ end
75
+ end
76
+
77
+ class << self
78
+ alias null_device null
79
+ end
80
+
81
+ # Returns whether or not +file+ is a binary file. Note that this is
82
+ # not guaranteed to be 100% accurate. It performs a "best guess" based
83
+ # on a simple test of the first +File.blksize+ characters.
84
+ #
85
+ # Example:
86
+ #
87
+ # File.binary?('somefile.exe') # => true
88
+ # File.binary?('somefile.txt') # => false
89
+ #--
90
+ # Based on code originally provided by Ryan Davis (which, in turn, is
91
+ # based on Perl's -B switch).
92
+ #
93
+ def self.binary?(file)
94
+ s = (File.read(file, File.stat(file).blksize) || "").split(//)
95
+ ((s.size - s.grep(" ".."~").size) / s.size.to_f) > 0.30
96
+ end
97
+
98
+ # Looks for the first occurrence of +program+ within +path+.
99
+ #
100
+ # On Windows, it looks for executables ending with the suffixes defined
101
+ # in your PATHEXT environment variable, or '.exe', '.bat' and '.com' if
102
+ # that isn't defined, which you may optionally include in +program+.
103
+ #
104
+ # Returns nil if not found.
105
+ #
106
+ # Examples:
107
+ #
108
+ # File.which('ruby') # => '/usr/local/bin/ruby'
109
+ # File.which('foo') # => nil
110
+ #
111
+ def self.which(program, path=ENV['PATH'])
112
+ if path.nil? || path.empty?
113
+ raise ArgumentError, "path cannot be empty"
114
+ end
115
+
116
+ # Bail out early if an absolute path is provided.
117
+ if program =~ /^\/|^[a-z]:[\\\/]/i
118
+ program += WIN32EXTS if MSWINDOWS && File.extname(program).empty?
119
+ found = Dir[program].first
120
+ if found && File.executable?(found) && !File.directory?(found)
121
+ return found
122
+ else
123
+ return nil
124
+ end
125
+ end
126
+
127
+ # Iterate over each path glob the dir + program.
128
+ path.split(File::PATH_SEPARATOR).each{ |dir|
129
+ next unless File.exists?(dir) # In case of bogus second argument
130
+ file = File.join(dir, program)
131
+
132
+ # Dir[] doesn't handle backslashes properly, so convert them. Also, if
133
+ # the program name doesn't have an extension, try them all.
134
+ if MSWINDOWS
135
+ file = file.tr("\\", "/")
136
+ file += WIN32EXTS if File.extname(program).empty?
137
+ end
138
+
139
+ found = Dir[file].first
140
+
141
+ # Convert all forward slashes to backslashes if supported
142
+ if found && File.executable?(found) && !File.directory?(found)
143
+ found.tr!(File::SEPARATOR, File::ALT_SEPARATOR) if File::ALT_SEPARATOR
144
+ return found
145
+ end
146
+ }
147
+
148
+ nil
149
+ end
150
+
151
+ # Returns an array of each +program+ within +path+, or nil if it cannot
152
+ # be found.
153
+ #
154
+ # On Windows, it looks for executables ending with the suffixes defined
155
+ # in your PATHEXT environment variable, or '.exe', '.bat' and '.com' if
156
+ # that isn't defined, which you may optionally include in +program+.
157
+ #
158
+ # Examples:
159
+ #
160
+ # File.whereis('ruby') # => ['/usr/bin/ruby', '/usr/local/bin/ruby']
161
+ # File.whereis('foo') # => nil
162
+ #
163
+ def self.whereis(program, path=ENV['PATH'])
164
+ if path.nil? || path.empty?
165
+ raise ArgumentError, "path cannot be empty"
166
+ end
167
+
168
+ paths = []
169
+
170
+ # Bail out early if an absolute path is provided.
171
+ if program =~ /^\/|^[a-z]:[\\\/]/i
172
+ program += WIN32EXTS if MSWINDOWS && File.extname(program).empty?
173
+ found = Dir[program]
174
+ if found[0] && File.executable?(found[0]) && !File.directory?(found[0])
175
+ return found
176
+ else
177
+ return nil
178
+ end
179
+ end
180
+
181
+ # Iterate over each path glob the dir + program.
182
+ path.split(File::PATH_SEPARATOR).each{ |dir|
183
+ next unless File.exists?(dir) # In case of bogus second argument
184
+ file = File.join(dir, program)
185
+
186
+ # Dir[] doesn't handle backslashes properly, so convert them. Also, if
187
+ # the program name doesn't have an extension, try them all.
188
+ if MSWINDOWS
189
+ file = file.tr("\\", "/")
190
+ file += WIN32EXTS if File.extname(program).empty?
191
+ end
192
+
193
+ found = Dir[file].first
194
+
195
+ # Convert all forward slashes to backslashes if supported
196
+ if found && File.executable?(found) && !File.directory?(found)
197
+ found.tr!(File::SEPARATOR, File::ALT_SEPARATOR) if File::ALT_SEPARATOR
198
+ paths << found
199
+ end
200
+ }
201
+
202
+ paths.empty? ? nil : paths.uniq
203
+ end
204
+
205
+ # In block form, yields the first +num_lines+ from +filename+. In non-block
206
+ # form, returns an Array of +num_lines+
207
+ #
208
+ # Examples:
209
+ #
210
+ # # Return an array
211
+ # File.head('somefile.txt') # => ['This is line1', 'This is line2', ...]
212
+ #
213
+ # # Use a block
214
+ # File.head('somefile.txt'){ |line| puts line }
215
+ #
216
+ def self.head(filename, num_lines=10)
217
+ a = []
218
+ IO.foreach(filename){ |line|
219
+ break if num_lines <= 0
220
+ num_lines -= 1
221
+ if block_given?
222
+ yield line
223
+ else
224
+ a << line
225
+ end
226
+ }
227
+ return a.empty? ? nil : a # Return nil in block form
228
+ end
229
+
230
+ # In block form, yields line +from+ up to line +to+. In non-block form
231
+ # returns an Array of lines from +from+ to +to+.
232
+ #
233
+ def self.middle(filename, from=10, to=20)
234
+ if block_given?
235
+ IO.readlines(filename)[from-1..to-1].each{ |line| yield line }
236
+ else
237
+ IO.readlines(filename)[from-1..to-1]
238
+ end
239
+ end
240
+
241
+ # In block form, yields the last +num_lines+ of file +filename+.
242
+ # In non-block form, it returns the lines as an array.
243
+ #
244
+ # Note that this method slurps the entire file, so I don't recommend it
245
+ # for very large files. Also note that 'tail -f' functionality is not
246
+ # present. See the 'file-tail' library for that.
247
+ #
248
+ # Example:
249
+ #
250
+ # File.tail('somefile.txt') # => ['This is line7', 'This is line8', ...]
251
+ #
252
+ def self.tail(filename, num_lines=10)
253
+ if block_given?
254
+ IO.readlines(filename).reverse[0..num_lines-1].reverse.each{ |line|
255
+ yield line
256
+ }
257
+ else
258
+ IO.readlines(filename).reverse[0..num_lines-1].reverse
259
+ end
260
+ end
261
+
262
+ # Converts a text file from one OS platform format to another, ala
263
+ # 'dos2unix'. The possible values for +platform+ include:
264
+ #
265
+ # * MS Windows -> dos, windows, win32, mswin
266
+ # * Unix/BSD -> unix, linux, bsd
267
+ # * Mac -> mac, macintosh, apple, osx
268
+ #
269
+ # Note that this method is only valid for an ftype of "file". Otherwise a
270
+ # TypeError will be raised. If an invalid format value is received, an
271
+ # ArgumentError is raised.
272
+ #
273
+ def self.nl_convert(old_file, new_file = old_file, platform = 'dos')
274
+ unless File.file?(old_file)
275
+ raise ArgumentError, 'Only valid for plain text files'
276
+ end
277
+
278
+ if platform =~ /dos|windows|win32|mswin|cygwin|mingw/i
279
+ format = "\cM\cJ"
280
+ elsif platform =~ /unix|linux|bsd/i
281
+ format = "\cJ"
282
+ elsif platform =~ /mac|apple|macintosh|osx/i
283
+ format = "\cM"
284
+ else
285
+ raise ArgumentError, "Invalid platform string"
286
+ end
287
+
288
+ orig = $\
289
+ $\ = format
290
+
291
+ if old_file == new_file
292
+ require 'fileutils'
293
+ require 'tempfile'
294
+
295
+ begin
296
+ temp_name = Time.new.strftime("%Y%m%d%H%M%S")
297
+ tf = Tempfile.new('ruby_temp_' + temp_name)
298
+ tf.open
299
+
300
+ IO.foreach(old_file){ |line|
301
+ line.chomp!
302
+ tf.print line
303
+ }
304
+ ensure
305
+ tf.close if tf && !tf.closed?
306
+ end
307
+ File.delete(old_file)
308
+ FileUtils.cp(tf.path, old_file)
309
+ else
310
+ begin
311
+ nf = File.new(new_file, 'w')
312
+ IO.foreach(old_file){ |line|
313
+ line.chomp!
314
+ nf.print line
315
+ }
316
+ ensure
317
+ nf.close if nf && !nf.closed?
318
+ end
319
+ end
320
+
321
+ $\ = orig
322
+ self
323
+ end
324
+
325
+ # Changes the access and modification time if present, or creates a 0
326
+ # byte file +filename+ if it doesn't already exist.
327
+ #
328
+ def self.touch(filename)
329
+ if File.exists?(filename)
330
+ time = Time.now
331
+ File.utime(time, time, filename)
332
+ else
333
+ File.open(filename, 'w'){}
334
+ end
335
+ self
336
+ end
337
+
338
+ # With no arguments, returns a four element array consisting of the number
339
+ # of bytes, characters, words and lines in filename, respectively.
340
+ #
341
+ # Valid options are 'bytes', 'characters' (or just 'chars'), 'words' and
342
+ # 'lines'.
343
+ #
344
+ def self.wc(filename, option='all')
345
+ option.downcase!
346
+ valid = %w/all bytes characters chars lines words/
347
+
348
+ unless valid.include?(option)
349
+ raise ArgumentError, "Invalid option: '#{option}'"
350
+ end
351
+
352
+ n = 0
353
+ if option == 'lines'
354
+ IO.foreach(filename){ n += 1 }
355
+ return n
356
+ elsif option == 'bytes'
357
+ File.open(filename){ |f|
358
+ f.each_byte{ n += 1 }
359
+ }
360
+ return n
361
+ elsif option == 'characters' || option == 'chars'
362
+ File.open(filename){ |f|
363
+ while f.getc
364
+ n += 1
365
+ end
366
+ }
367
+ return n
368
+ elsif option == 'words'
369
+ IO.foreach(filename){ |line|
370
+ n += line.split.length
371
+ }
372
+ return n
373
+ else
374
+ bytes,chars,lines,words = 0,0,0,0
375
+ IO.foreach(filename){ |line|
376
+ lines += 1
377
+ words += line.split.length
378
+ chars += line.split('').length
379
+ }
380
+ File.open(filename){ |f|
381
+ while f.getc
382
+ bytes += 1
383
+ end
384
+ }
385
+ return [bytes,chars,words,lines]
386
+ end
387
+ end
388
+
389
+ private
390
+
391
+ def self.bmp?(file)
392
+ IO.read(file, 3) == "BM6"
393
+ end
394
+
395
+ def self.jpg?(file)
396
+ IO.read(file, 10) == "\377\330\377\340\000\020JFIF"
397
+ end
398
+
399
+ def self.png?(file)
400
+ IO.read(file, 4) == "\211PNG"
401
+ end
402
+
403
+ def self.gif?(file)
404
+ ['GIF89a', 'GIF97a'].include?(IO.read(file, 6))
405
+ end
406
+ end