1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
|
require 'tempfile'
require "util"
class Numeric
def to_pretty_s
%w(zero one two three four five six seven eight nine ten)[self] || to_s
end
end
class String
def dcfirst; self[0..0].downcase + self[1..-1] end
def blank?; self =~ /\A\s*\z/ end
def underline; self + "\n" + ("-" * self.length) end
def pluralize n, b=true
s = (n == 1 ? self : (self == 'bugfix' ? 'bugfixes' : self + "s")) # oh yeah
b ? n.to_pretty_s + " " + s : s
end
def shortened_email; self =~ /<?(\S+?)@.+/ ? $1 : self end
def multistrip; strip.gsub(/\n\n+/, "\n\n") end
end
class Array
def listify prefix=""
return "" if empty?
"\n" +
map_with_index { |x, i| x.to_s.gsub(/^/, "#{prefix}#{i + 1}. ") }.
join("\n")
end
end
class Time
def pretty; strftime "%c" end
def pretty_date; strftime "%Y-%m-%d" end
def ago
diff = (Time.now - self).to_i.abs
if diff < 60
"second".pluralize diff
elsif diff < 60*60*3
"minute".pluralize(diff / 60)
elsif diff < 60*60*24*3
"hour".pluralize(diff / (60*60))
elsif diff < 60*60*24*7*2
"day".pluralize(diff / (60*60*24))
elsif diff < 60*60*24*7*8
"week".pluralize(diff / (60*60*24*7))
elsif diff < 60*60*24*7*52
"month".pluralize(diff / (60*60*24*7*4))
else
"year".pluralize(diff / (60*60*24*7*52))
end
end
end
module Lowline
def run_editor
f = Tempfile.new "ditz"
yield f
f.close
editor = ENV["EDITOR"] || "/usr/bin/vi"
cmd = "#{editor} #{f.path.inspect}"
mtime = File.mtime f.path
system cmd or raise Error, "cannot execute command: #{cmd.inspect}"
File.mtime(f.path) == mtime ? nil : f.path
end
def ask q, opts={}
default_s = case opts[:default]
when nil; nil
when ""; " (enter for none)"
else; " (enter for #{opts[:default].inspect})"
end
tail = case q
when /[:?]$/; " "
when /[:?]\s+$/; ""
else; ": "
end
while true
prompt = [q, default_s, tail].compact.join
if Ditz::has_readline?
ans = Readline::readline(prompt)
else
print prompt
ans = STDIN.gets.strip
end
if opts[:default]
ans = opts[:default] if ans.blank?
else
next if ans.blank? && !opts[:empty_ok]
end
break ans unless (opts[:restrict] && ans !~ opts[:restrict])
end
end
def ask_via_editor q, default=nil
fn = run_editor do |f|
f.puts(default || "")
f.puts q.gsub(/^/, "## ")
f.puts "##"
f.puts "## Enter your text above. Lines starting with a '#' will be ignored."
end
return unless fn
IO.read(fn).gsub(/^#.*$/, "").multistrip
end
def ask_multiline q
puts "#{q} (ctrl-d, ., or /stop to stop, /edit to edit, /reset to reset):"
ans = ""
while true
if Ditz::has_readline?
line = Readline::readline('> ')
else
(line = STDIN.gets) && line.strip!
end
if line
if Ditz::has_readline?
Readline::HISTORY.push(line)
end
case line
when /^\.$/, "/stop"
break
when "/reset"
return ask_multiline(q)
when "/edit"
return ask_via_editor(q, ans)
else
ans << line + "\n"
end
else
puts
break
end
end
ans.multistrip
end
def ask_yon q
while true
print "#{q} (y/n): "
a = STDIN.gets.strip
break a if a =~ /^[yn]$/i
end =~ /y/i
end
def ask_for_many plural_name, name=nil
name ||= plural_name.gsub(/s$/, "")
stuff = []
while true
puts
puts "Current #{plural_name}:"
if stuff.empty?
puts "None!"
else
stuff.each_with_index { |c, i| puts " #{i + 1}) #{c}" }
end
puts
ans = ask "(A)dd #{name}, (r)emove #{name}, or (d)one"
case ans
when "a", "A"
ans = ask "#{name.capitalize} name", ""
stuff << ans unless ans =~ /^\s*$/
when "r", "R"
ans = ask "Remove which #{name}? (1--#{stuff.size})"
stuff.delete_at(ans.to_i - 1) if ans
when "d", "D"
break
end
end
stuff
end
def ask_for_selection stuff, name, to_string=:to_s
puts "Choose a #{name}:"
stuff.each_with_index do |c, i|
pretty = case to_string
when block_given? && to_string # heh
yield c
when Symbol
c.send to_string
when Proc
to_string.call c
else
raise ArgumentError, "unknown to_string argument type; expecting Proc or Symbol"
end
puts " #{i + 1}) #{pretty}"
end
j = while true
i = ask "#{name.capitalize} (1--#{stuff.size})"
break i.to_i if i && (1 .. stuff.size).member?(i.to_i)
end
stuff[j - 1]
end
end
|