-
Notifications
You must be signed in to change notification settings - Fork 8
/
.irbrc
246 lines (216 loc) · 7.36 KB
/
.irbrc
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# You want RubyGems available by default.
require 'rubygems'
require 'pp'
require 'irb/ext/save-history'
IRB.conf[:AUTO_INDENT] = true
IRB.conf[:SAVE_HISTORY] = 1000
IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb_history"
# Do crazy syntax coloring and stuff if gems are available.
# $ gem install wirble hirb bond interactive_editor
begin
require 'wirble'
# Enter 'vi' or 'mate' to open the editor, save and close to evaluate,
# enter again to recall your previous text.
# require 'interactive_editor'
# Bond is better completion, for IRB and more:
# http://tagaholic.me/2009/07/22/better-irb-completion-with-bond.html
require 'bond'
Bond.start
# Custom 'view formats' for object classes, and paging.
# Gives ActiveRecord table views out of the box.
require 'hirb'
# Really only using wirble for color these days.
# Skip libs because we get it all elsewhere (completion, pp, rubygems)
Wirble.init(:skip_history => true, :skip_prompt => true, :skip_libraries => true)
Wirble.colorize
# Should be called after wirble
Hirb.enable
# Example custom Bond completion, for the #reload method below
Bond.complete(:method=>'reload') { $" }
# Toggle completion of inherited methods
# http://tagaholic.me/2009/07/30/changing-readline-completions-with-key-combo.html
# TODO: this is a bit wonky
def toggle_object_complete
# default mode
if @object_complete
Bond.recomplete(:object => 'Object', :place => :last)
Bond.recomplete(:object => 'Object', :on => /([^.\s]+)\.([^.\s]*)$/, :place => :last)
else
non_inherited_methods = proc { |e|
e.object.is_a?(Module) ? e.object.methods(false) : e.object.class.instance_methods(false)
}
Bond.recomplete(:object => 'Object', :place => :last, &non_inherited_methods)
Bond.recomplete(:object => 'Object', :on => /([^.\s]+)\.([^.\s]*)$/, :place => :last, &non_inherited_methods)
end
@object_complete = !@object_complete
end
rescue LoadError
# But if not, we'll do the good stuff anyway
require 'irb/completion'
# Easily see all the methods local to an object's class
# Wirble's `po` method does this
class Object
def local_methods
(methods - Object.instance_methods).sort
end
private :local_methods
end
# Completion for the ri methods defined below, for irb/completion.
#
# Note that the completion matches only object instance methods, but the ri
# methods do support finding instance methods from a class, e.g.
# `String.ri_count`.
#
# TODO: need a Bond version of this
RICompletionProc = proc { |input|
bind = IRB.conf[:MAIN_CONTEXT].workspace.binding
case input
when /(\s*(.*)\.ri_)(.*)/
pre = $1
receiver = $2
meth = $3 ? /\A#{Regexp.quote($3)}/ : /./
begin
candidates = eval("#{receiver}.methods", bind).map do |meth|
case meth
when /[A-Za-z_]/ then meth
else %{"#{meth}"} # needs escaping
end
end
candidates = candidates.grep(meth)
candidates.map { |s| pre + s.to_s }
rescue Exception
candidates = []
end
when /([A-Z]\w+)#(\w*)/
klass = $1
meth = $2 ? /\A#{Regexp.quote($2)}/ : /./
candidates = eval("#{klass}.instance_methods(false)", bind)
candidates = candidates.grep(meth)
candidates.map { |s| "'#{klass}##{s}'" }
else
IRB::InputCompletor::CompletionProc.call(input)
end
}
#Readline.basic_word_break_characters= " \t\n\"\\'`><=;|&{("
Readline.basic_word_break_characters= " \t\n\\><=;|&"
Readline.completion_proc = RICompletionProc
end
# Log Rails stuff like SQL/Mongo queries to $stdout if in Rails console
if defined?(Rails) && Rails.respond_to?(:logger) # Rails 3 style
require 'logger'
Rails.logger = Logger.new($stdout)
def toggle_db_logging
if $db_logging_enabled
ActiveRecord::Base.logger = Logger.new(nil) if defined?(ActiveRecord)
Mongoid.logger = Logger.new(nil) if defined?(Mongoid)
$db_logging_enabled = false
else
ActiveRecord::Base.logger = Rails.logger if defined?(ActiveRecord)
Mongoid.logger = Rails.logger if defined?(Mongoid)
$db_logging_enabled = true
end
end
toggle_db_logging
# Rails < 3.0.0
elsif ENV.include?('RAILS_ENV') && !Object.const_defined?('RAILS_DEFAULT_LOGGER')
require 'logger'
RAILS_DEFAULT_LOGGER = Logger.new($stdout)
end
# Re-installing a gem locally as you change code gets old, no? Enter:
# http://tagaholic.me/2009/02/05/local-gem-loads-your-current-code-now.html
#
# Just set the env var in irb or in client code you're working on to switch
# between rubygems and your local edits.
#
# ENV['LOCAL_GEMS'] = 'true'
#
if ENV['LOCAL_GEMS']
begin
require 'local_gem'
require 'local_gem/override'
load File.join(ENV['HOME'], '.localgems')
rescue LoadError
puts "*** local_gem doesn't appear to be installed. `gem install local_gem`"
end
end
# Reload a matching library that has been required, if you changed it
def reload(require_regex)
$".grep(/#{require_regex}/).each { |e| $".delete(e) && require(e) }
end
# Iterative development: watch a file and eval it when it changes.
# Ctrl-C to exit the subshell and 'return' to irb.
# Hat tip: http://po-ru.com/diary/iterative-development-in-irb/
#
# These days you should probably just use Guard :-)
def loop_execute(file)
old_mtime = nil
loop do
# print("\e[sWaiting...")
sleep(0.5) while (mtime = File.stat(file).mtime) == old_mtime
# print("\e[u\e[K")
begin
r = eval(File.read(file))
puts("=> #{r.inspect}")
rescue IRB::Abort
puts("Abort")
return
rescue Exception => e
puts("#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}")
end
old_mtime = mtime
end
end
# The below adds nice ri documentation via obj.ri_* with completion,
# and supports the old Wirble way with `r 'String#count'` and completion
# as well, using above RICompletionProc. Courtesy:
#
# http://eigenclass.org/hiki/irb+ri+completion
#
# The author recommends FastRI because RI is so slow.
module Kernel
def r(arg)
puts `ri "#{arg}"`
end
private :r
end
class Object
def puts_ri_documentation_for(obj, meth)
case self
when Module
# This is to approximate instance and class methods in inherited order
candidates = ancestors.zip(self.class.ancestors).flatten.compact.uniq
# Checks both class- and instance-specific forms simply for more precise
# output--could check 'klass.meth' only for speed, the search is equivalent.
candidates = candidates.flat_map { |klass| ["#{klass}::#{meth}", "#{klass}##{meth}"] }
else
candidates = self.class.ancestors.map { |klass| "#{klass}##{meth}" }
end
candidates.each do |candidate|
# desc = `fri '#{candidate}'`
# unless desc.chomp == "nil"
# uncomment to use ri (and some patience)
desc = `ri -T '#{candidate}' 2>/dev/null`
unless desc.empty?
puts desc
return true
end
end
false
end
private :puts_ri_documentation_for
def method_missing(meth, *args, &block)
if md = /ri_(.*)/.match(meth.to_s)
unless puts_ri_documentation_for(self, md[1])
"Ri doesn't know about ##{meth}"
end
else
super
end
end
# Helpful for classes instead of instances, e.g. `String.ri_ '#count'`
def ri_(meth)
unless puts_ri_documentation_for(self, meth.to_s)
"Ri doesn't know about ##{meth}"
end
end
end