riel 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +0 -0
- data/lib/riel/ansicolor.rb +93 -0
- data/lib/riel/array.rb +20 -0
- data/lib/riel/command.rb +30 -0
- data/lib/riel/date.rb +16 -0
- data/lib/riel/dir.rb +90 -0
- data/lib/riel/enumerable.rb +66 -0
- data/lib/riel/env.rb +49 -0
- data/lib/riel/file.rb +212 -0
- data/lib/riel/filetype.rb +189 -0
- data/lib/riel/hash.rb +12 -0
- data/lib/riel/io.rb +20 -0
- data/lib/riel/log.rb +548 -0
- data/lib/riel/matchdata.rb +13 -0
- data/lib/riel/optproc.rb +369 -0
- data/lib/riel/pathname.rb +16 -0
- data/lib/riel/rcfile.rb +35 -0
- data/lib/riel/regexp.rb +152 -0
- data/lib/riel/setdiff.rb +53 -0
- data/lib/riel/size_converter.rb +62 -0
- data/lib/riel/string.rb +81 -0
- data/lib/riel/tempfile.rb +28 -0
- data/lib/riel/text.rb +408 -0
- data/lib/riel/timer.rb +52 -0
- data/lib/riel.rb +13 -0
- data/test/riel/array_test.rb +22 -0
- data/test/riel/command_test.rb +28 -0
- data/test/riel/date_test.rb +17 -0
- data/test/riel/dir_test.rb +98 -0
- data/test/riel/enumerable_test.rb +27 -0
- data/test/riel/env_test.rb +52 -0
- data/test/riel/file_test.rb +242 -0
- data/test/riel/filetype_test.rb +32 -0
- data/test/riel/hash_test.rb +12 -0
- data/test/riel/io_test.rb +22 -0
- data/test/riel/log_test.rb +184 -0
- data/test/riel/matchdata_test.rb +15 -0
- data/test/riel/optproc_test.rb +233 -0
- data/test/riel/pathname_test.rb +36 -0
- data/test/riel/rcfile_test.rb +44 -0
- data/test/riel/regexp_test.rb +24 -0
- data/test/riel/setdiff_test.rb +26 -0
- data/test/riel/size_converter_test.rb +64 -0
- data/test/riel/string_test.rb +58 -0
- data/test/riel/tempfile_test.rb +16 -0
- data/test/riel/text_test.rb +102 -0
- data/test/riel/timer_test.rb +43 -0
- 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
|
data/lib/riel/command.rb
ADDED
@@ -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
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
|