riel 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/README +0 -0
  2. data/lib/riel/ansicolor.rb +93 -0
  3. data/lib/riel/array.rb +20 -0
  4. data/lib/riel/command.rb +30 -0
  5. data/lib/riel/date.rb +16 -0
  6. data/lib/riel/dir.rb +90 -0
  7. data/lib/riel/enumerable.rb +66 -0
  8. data/lib/riel/env.rb +49 -0
  9. data/lib/riel/file.rb +212 -0
  10. data/lib/riel/filetype.rb +189 -0
  11. data/lib/riel/hash.rb +12 -0
  12. data/lib/riel/io.rb +20 -0
  13. data/lib/riel/log.rb +548 -0
  14. data/lib/riel/matchdata.rb +13 -0
  15. data/lib/riel/optproc.rb +369 -0
  16. data/lib/riel/pathname.rb +16 -0
  17. data/lib/riel/rcfile.rb +35 -0
  18. data/lib/riel/regexp.rb +152 -0
  19. data/lib/riel/setdiff.rb +53 -0
  20. data/lib/riel/size_converter.rb +62 -0
  21. data/lib/riel/string.rb +81 -0
  22. data/lib/riel/tempfile.rb +28 -0
  23. data/lib/riel/text.rb +408 -0
  24. data/lib/riel/timer.rb +52 -0
  25. data/lib/riel.rb +13 -0
  26. data/test/riel/array_test.rb +22 -0
  27. data/test/riel/command_test.rb +28 -0
  28. data/test/riel/date_test.rb +17 -0
  29. data/test/riel/dir_test.rb +98 -0
  30. data/test/riel/enumerable_test.rb +27 -0
  31. data/test/riel/env_test.rb +52 -0
  32. data/test/riel/file_test.rb +242 -0
  33. data/test/riel/filetype_test.rb +32 -0
  34. data/test/riel/hash_test.rb +12 -0
  35. data/test/riel/io_test.rb +22 -0
  36. data/test/riel/log_test.rb +184 -0
  37. data/test/riel/matchdata_test.rb +15 -0
  38. data/test/riel/optproc_test.rb +233 -0
  39. data/test/riel/pathname_test.rb +36 -0
  40. data/test/riel/rcfile_test.rb +44 -0
  41. data/test/riel/regexp_test.rb +24 -0
  42. data/test/riel/setdiff_test.rb +26 -0
  43. data/test/riel/size_converter_test.rb +64 -0
  44. data/test/riel/string_test.rb +58 -0
  45. data/test/riel/tempfile_test.rb +16 -0
  46. data/test/riel/text_test.rb +102 -0
  47. data/test/riel/timer_test.rb +43 -0
  48. metadata +134 -0
data/README ADDED
File without changes
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ # Attribute codes:
5
+ # 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
6
+ # Text color codes:
7
+ # 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
8
+ # Background color codes:
9
+ # 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
10
+
11
+ module ANSIColor
12
+
13
+ ATTRIBUTES = Hash[
14
+ 'none' => '0',
15
+ 'reset' => '0',
16
+ 'bold' => '1',
17
+ 'underscore' => '4',
18
+ 'underline' => '4',
19
+ 'blink' => '5',
20
+ 'reverse' => '7',
21
+ 'concealed' => '8',
22
+ 'black' => '30',
23
+ 'red' => '31',
24
+ 'green' => '32',
25
+ 'yellow' => '33',
26
+ 'blue' => '34',
27
+ 'magenta' => '35',
28
+ 'cyan' => '36',
29
+ 'white' => '37',
30
+ 'on_black' => '40',
31
+ 'on_red' => '41',
32
+ 'on_green' => '42',
33
+ 'on_yellow' => '43',
34
+ 'on_blue' => '44',
35
+ 'on_magenta' => '45',
36
+ 'on_cyan' => '46',
37
+ 'on_white' => '47',
38
+ ]
39
+
40
+ ATTRIBUTES.each do |name, val|
41
+ eval <<-EODEF
42
+ def ANSIColor.#{name}
43
+ "\\e[#{val}m"
44
+ end
45
+ EODEF
46
+ end
47
+
48
+ def ANSIColor.attributes
49
+ ATTRIBUTES.collect { |name, val| name }
50
+ end
51
+
52
+ # returns the code for the given color string, which is in the format:
53
+ # [foreground] on [background]. Note that the foreground and background sections
54
+ # can have modifiers (attributes). Examples:
55
+ # black
56
+ # blue on white
57
+ # bold green on yellow
58
+ # underscore bold magenta on cyan
59
+ # underscore red on bold cyan
60
+
61
+ def ANSIColor.code(str)
62
+ fg, bg = str.split(/\s*\bon_?\s*/)
63
+ (fg ? foreground(fg) : "") + (bg ? background(bg) : "")
64
+ end
65
+
66
+ # returns the code for the given background color(s)
67
+ def ANSIColor.background(bgcolor)
68
+ make_code("on_" + bgcolor)
69
+ end
70
+
71
+ # returns the code for the given foreground color(s)
72
+ def ANSIColor.foreground(fgcolor)
73
+ make_code(fgcolor)
74
+ end
75
+
76
+ protected
77
+
78
+ def ANSIColor.make_code(str)
79
+ if str
80
+ str.split.collect do |s|
81
+ if attr = ATTRIBUTES[s]
82
+ "\e[#{attr}m"
83
+ else
84
+ $stderr.puts "WARNING: ANSIColor::make_code(" + str + "): unknown color: " + s
85
+ return ""
86
+ end
87
+ end.join("")
88
+ else
89
+ ""
90
+ end
91
+ end
92
+
93
+ end
data/lib/riel/array.rb ADDED
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ class Array
5
+
6
+ $-w = false
7
+
8
+ # Wraps the array with brackets, and inserts a comma and a space between
9
+ # elements.
10
+
11
+ def to_s
12
+ "[ " + collect { |e| e.to_s }.join(", ") + " ]"
13
+ end
14
+ $-w = true
15
+
16
+ def rand
17
+ return self[Kernel.rand(length)]
18
+ end
19
+
20
+ end
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+ #!ruby -w
4
+
5
+ class Command
6
+
7
+ # Runs the given command and arguments, returning the lines of output. If a
8
+ # block is provided, then it will be called with each line of output. If the
9
+ # block takes two arguments, then the line number is also passed to the block.
10
+
11
+ def self.run(cmd, *args, &blk)
12
+ lines = Array.new
13
+
14
+ IO.popen("#{cmd} #{args.join(' ')}") do |io|
15
+ lnum = 0
16
+ io.each_line do |line|
17
+ lines << line
18
+ if blk
19
+ args = [ line ]
20
+ args << lnum if blk.arity > 1
21
+ blk.call(*args)
22
+ end
23
+ lnum += 1
24
+ end
25
+ end
26
+
27
+ lines
28
+ end
29
+
30
+ end
data/lib/riel/date.rb ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+ #!ruby -w
4
+
5
+ require 'date'
6
+
7
+
8
+ class Date
9
+
10
+ # Returns the number of days in the given month.
11
+
12
+ def self.days_in_month(year, month)
13
+ (Date.new(year, 12, 31) << (12 - month)).day
14
+ end
15
+
16
+ end
data/lib/riel/dir.rb ADDED
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'pathname'
5
+
6
+ class Dir
7
+
8
+ # Returns the home directory, for both Unix and Windows.
9
+ def self.home
10
+ ENV["HOME"] || begin
11
+ hd = ENV["HOMEDRIVE"]
12
+ hp = ENV["HOMEPATH"]
13
+ if hd || hp
14
+ (hd || "") + (hp || "\\")
15
+ end
16
+ end
17
+ end
18
+
19
+ # Removes directories containing no files or files matching only those in
20
+ # args[:deletable_files], which are basenames.
21
+ def self.remove_if_empty(dir, args = Hash.new)
22
+ deletable = args[:deletable] || Array.new
23
+ verbose = args[:verbose]
24
+ level = args[:level] || 0
25
+
26
+ subargs = args.dup
27
+ subargs[:level] = level + 1
28
+
29
+ dir = Pathname.new(dir) unless dir.kind_of?(Pathname)
30
+
31
+ if level <= 1 && verbose
32
+ puts "dir: #{dir}"
33
+ end
34
+
35
+ if dir.readable?
36
+ dir.children.sort.each do |child|
37
+ if child.exist? && child.directory?
38
+ self.remove_if_empty(child, subargs)
39
+ end
40
+ end
41
+
42
+ if dir.expand_path == Pathname.pwd.expand_path
43
+ puts "skipping current directory: #{dir}" if verbose
44
+ else
45
+ can_delete = dir.children.all? do |x|
46
+ bname = x.basename.to_s
47
+ deletable.any? do |del|
48
+ if del.kind_of?(String)
49
+ bname == del
50
+ elsif del.kind_of?(Regexp)
51
+ del.match(bname)
52
+ else
53
+ false
54
+ end
55
+ end
56
+ end
57
+
58
+ if can_delete
59
+ dir.children.each do |x|
60
+ puts "removing file: #{x}" if verbose
61
+ x.delete
62
+ end
63
+
64
+ puts "removing directory: #{dir}" if verbose
65
+
66
+ dir.delete
67
+ else
68
+ # puts "#{dir} not empty"
69
+ end
70
+ end
71
+ elsif verbose
72
+ puts "#{dir} not readable"
73
+ end
74
+ end
75
+
76
+ # Moves and copies files to the given directory, creating
77
+ # it if it does not exist.
78
+ def self.move_and_copy_files(dir, move_files, copy_files)
79
+ dir.mkdir unless dir.exist?
80
+
81
+ move_files.each do |mfile|
82
+ File.move(mfile.to_s, dir.to_s)
83
+ end
84
+
85
+ copy_files.each do |cfile|
86
+ File.copy(cfile.to_s, dir.to_s)
87
+ end
88
+ end
89
+
90
+ end
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ module Enumerable
5
+
6
+ def collect_with_index(&blk)
7
+ ary = []
8
+ self.each_with_index do |item, idx|
9
+ ary << blk.call(item, idx)
10
+ end
11
+ ary
12
+ end
13
+
14
+ NOT_NIL = Object.new
15
+
16
+ def select_with_index(arg = NOT_NIL, &blk)
17
+ ary = []
18
+ self.each_with_index do |item, idx|
19
+ ary << item if _match?(arg, item, idx, &blk)
20
+ end
21
+ ary
22
+ end
23
+
24
+ def detect_with_index(arg = NOT_NIL, &blk)
25
+ self.each_with_index do |item, idx|
26
+ return item if _match?(arg, item, idx, &blk)
27
+ end
28
+ nil
29
+ end
30
+
31
+ alias :orig_select :select
32
+ alias :orig_collect :collect
33
+ alias :orig_detect :detect
34
+ alias :orig_reject :reject
35
+
36
+ origw = $-w
37
+ $-w = false
38
+ def select(arg = NOT_NIL, &blk)
39
+ ary = []
40
+ self.each_with_index do |item, idx|
41
+ ary << item if _match?(arg, item, idx, &blk)
42
+ end
43
+ ary
44
+ end
45
+
46
+ def detect(arg = NOT_NIL, &blk)
47
+ self.each_with_index do |item, idx|
48
+ return item if _match?(arg, item, idx, &blk)
49
+ end
50
+ nil
51
+ end
52
+ $-w = origw
53
+
54
+ def _match?(arg, item, idx, &blk)
55
+ if blk
56
+ args = [ item ]
57
+ args << idx if idx && blk.arity > 1
58
+ blk.call(*args)
59
+ elsif arg == NOT_NIL
60
+ !item.nil?
61
+ else
62
+ arg == item
63
+ end
64
+ end
65
+
66
+ end
data/lib/riel/env.rb ADDED
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ module Env
5
+
6
+ # Returns the home directory, for both Unix and Windows.
7
+
8
+ def self.home_directory
9
+ if hm = ENV["HOME"]
10
+ hm
11
+ else
12
+ hd = ENV["HOMEDRIVE"]
13
+ hp = ENV["HOMEPATH"]
14
+ if hd || hp
15
+ (hd || "") + (hp || "\\")
16
+ else
17
+ nil
18
+ end
19
+ end
20
+ end
21
+
22
+ # matches single and double quoted strings:
23
+ REGEXP = / # either:
24
+ ([\"\']) # start with a quote, and save it ($1)
25
+ ( # save this ($2)
26
+ (?: # either (and don't save this):
27
+ \\. # any escaped character
28
+ | # or
29
+ [^\1\\] # anything that is not a quote ($1), and is not a backslash
30
+ )*? # only up to the next quote
31
+ ) # end of $2
32
+ \1 # end with the same quote we started with
33
+ | # or
34
+ (:?\S+) # plain old nonwhitespace
35
+ /x
36
+
37
+ # amazing that ruby-mode (Emacs) handled all that.
38
+
39
+ # Reads the environment variable, splitting it according to its quoting.
40
+
41
+ def self.split(varname)
42
+ if v = ENV[varname]
43
+ v.scan(REGEXP).collect { |x| x[1] || x[2] }
44
+ else
45
+ []
46
+ end
47
+ end
48
+
49
+ end
data/lib/riel/file.rb ADDED
@@ -0,0 +1,212 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'riel/filetype'
5
+ require 'riel/pathname'
6
+ require 'riel/tempfile'
7
+ require 'fileutils'
8
+
9
+ # this eliminates the world-writable warning when running file operations
10
+ # (opening, finding, executing):
11
+
12
+ orig_verbose = $VERBOSE
13
+ $VERBOSE = nil
14
+ path = ENV['PATH'].dup
15
+ $VERBOSE = orig_verbose
16
+
17
+ class File
18
+
19
+ def self.text?(file)
20
+ return File.file?(file) && FileType.instance.text?(file)
21
+ end
22
+
23
+ def self.binary?(file)
24
+ return !self.text?(file)
25
+ end
26
+
27
+ # Returns whether the given object is a file. Ignores errors.
28
+ def self.is_file?(fd)
29
+ begin
30
+ return self.stat(fd).file?
31
+ rescue
32
+ # ignore files that could not be read, etc.
33
+ return false
34
+ end
35
+ end
36
+
37
+ # Returns whether the given file is writable. Ignores errors.
38
+ def self.is_writable?(file)
39
+ begin
40
+ return self.stat(file).writable?
41
+ rescue
42
+ # ignore files that could not be read, etc.
43
+ return false
44
+ end
45
+ end
46
+
47
+ # Returns whether the given object is a directory. Ignores errors.
48
+ def self.is_directory?(fd)
49
+ begin
50
+ return self.stat(fd).directory?
51
+ rescue
52
+ # ignore files that could not be read, etc.
53
+ return false
54
+ end
55
+ end
56
+
57
+ # Returns an array of all files under the given directory.
58
+ def self.find_files(dir)
59
+ files = Array.new
60
+ Find.find(dir) { |f| files.push(f) if is_file?(f) }
61
+ files
62
+ end
63
+
64
+ # Returns an array of all directory under the given directory.
65
+ def self.find_directories(dir)
66
+ dirs = Array.new
67
+ Find.find(dir) { |d| dirs.push(d) if is_directory?(d) }
68
+ dirs
69
+ end
70
+
71
+ # Removes the file/directory, including all subelements. Use with caution!
72
+ def self.remove_recursively(fd)
73
+ #$$$ this is rmtree
74
+ if fd.directory?
75
+ fd.children.each { |x| remove_recursively(x) }
76
+ end
77
+ fd.unlink
78
+ end
79
+
80
+ # Creates the given directory.
81
+ def self.mkdir(dir)
82
+ pn = Pathname.new(dir)
83
+ pn.mkdir unless pn.exist?
84
+ end
85
+
86
+ # Moves the files to the given directory, creating it if it does not exist.
87
+ def self.move_files(dir, files)
88
+ mkdir(dir)
89
+
90
+ files.each do |file|
91
+ FileUtils.move(file.to_s, dir.to_s)
92
+ end
93
+ end
94
+
95
+ # Copies the files to the given directory, creating it if it does not exist.
96
+ def self.copy_files(dir, files)
97
+ mkdir(dir)
98
+
99
+ files.each do |file|
100
+ FileUtils.copy(file.to_s, dir.to_s)
101
+ end
102
+ end
103
+
104
+ # Converts the argument to a Pathname.
105
+ def self._to_pathname(file)
106
+ file.kind_of?(Pathname) ? file : Pathname.new(file.to_s)
107
+ end
108
+
109
+ # Reads a file line by line. Returns the pathname for the file, or nil if it
110
+ # does not exist.
111
+ def self.read_file(file, &blk)
112
+ fpn = _to_pathname(file)
113
+ if fpn.exist?
114
+ fpn.open do |f|
115
+ blk.call f.read
116
+ end
117
+ fpn
118
+ else
119
+ nil
120
+ end
121
+ end
122
+
123
+ # Reads a file line by line, calling the given block. Returns the pathname for
124
+ # the file, or nil if it does not exist.
125
+ def self.read_file_lines(file, &blk)
126
+ fpn = _to_pathname(file)
127
+ if fpn.exist?
128
+ fpn.open do |f|
129
+ f.each_line do |line|
130
+ blk.call line
131
+ end
132
+ fpn
133
+ end
134
+ else
135
+ nil
136
+ end
137
+ end
138
+
139
+ # Opens a file for writing and delegates to the given block.
140
+ def self.open_writable_file(file, &blk)
141
+ fpn = _to_pathname(file)
142
+
143
+ fpn.open(File::WRONLY | File::TRUNC | File::CREAT) do |f|
144
+ blk.call(f)
145
+ end
146
+
147
+ fpn
148
+ end
149
+
150
+ # Writes a file, using the <code>write</code> method.
151
+ def self.write_file(file, &blk)
152
+ open_writable_file(file) do |io|
153
+ io.write blk.call
154
+ end
155
+ end
156
+
157
+ # Writes a file, using puts (thus making it better for text files).
158
+ def self.put_file(file, &blk)
159
+ open_writable_file(file) do |io|
160
+ io.puts blk.call
161
+ end
162
+ end
163
+
164
+ # Opens a tempfile for writing, delegates to the given block, and renames the
165
+ # temp file to <code>file</code>. If <code>tempfile</code> is specified, it
166
+ # will be used as the temp file name. Ditto for <code>tempdir</code>, which
167
+ # defaults to Dir::tmpdir (e.g. "/tmp")
168
+
169
+ def self.open_via_temp_file(file, tempfile = nil, tempdir = Dir::tmpdir, &blk)
170
+ tempname = nil
171
+
172
+ fpn = _to_pathname(file)
173
+ tempfile ||= fpn.rootname
174
+
175
+ Tempfile.open(tempfile) do |tf|
176
+ blk.call(tf)
177
+ tempname = tf.path
178
+ end
179
+
180
+ FileUtils.mv(tempname, file.to_s)
181
+ end
182
+
183
+ # Writes a file, using write, buffering it via a temp file.
184
+ def self.write_via_temp_file(file, &blk)
185
+ open_via_temp_file(file) do |io|
186
+ io.write blk.call
187
+ end
188
+ end
189
+
190
+ # Writes a file, using puts, buffering it via a temp file.
191
+ def self.put_via_temp_file(file, &blk)
192
+ open_via_temp_file(file) do |io|
193
+ io.puts blk.call
194
+ end
195
+ end
196
+
197
+ # Returns a file for the given basename, sequentially appending an integer
198
+ # until one is found that does not exist. For example, "foo.3" if "foo",
199
+ # "foo.1", and "foo.2" already exist.
200
+ def self.get_unused_file_name(basename)
201
+ tgt = basename
202
+ if tgt.exist?
203
+ i = 1
204
+ while tgt.exist?
205
+ tgt = Pathname.new(basename.to_s + "." + i.to_s)
206
+ i += 1
207
+ end
208
+ end
209
+ tgt
210
+ end
211
+
212
+ end