riel 1.0.0

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