irb 1.1.0.pre.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +22 -0
  3. data/README.md +55 -0
  4. data/exe/irb +11 -0
  5. data/irb.gemspec +29 -0
  6. data/lib/irb.rb +855 -0
  7. data/lib/irb/cmd/chws.rb +34 -0
  8. data/lib/irb/cmd/fork.rb +39 -0
  9. data/lib/irb/cmd/help.rb +46 -0
  10. data/lib/irb/cmd/load.rb +67 -0
  11. data/lib/irb/cmd/nop.rb +39 -0
  12. data/lib/irb/cmd/pushws.rb +41 -0
  13. data/lib/irb/cmd/subirb.rb +43 -0
  14. data/lib/irb/color.rb +218 -0
  15. data/lib/irb/completion.rb +339 -0
  16. data/lib/irb/context.rb +459 -0
  17. data/lib/irb/ext/change-ws.rb +46 -0
  18. data/lib/irb/ext/history.rb +120 -0
  19. data/lib/irb/ext/loader.rb +129 -0
  20. data/lib/irb/ext/multi-irb.rb +265 -0
  21. data/lib/irb/ext/save-history.rb +117 -0
  22. data/lib/irb/ext/tracer.rb +72 -0
  23. data/lib/irb/ext/use-loader.rb +77 -0
  24. data/lib/irb/ext/workspaces.rb +67 -0
  25. data/lib/irb/extend-command.rb +328 -0
  26. data/lib/irb/frame.rb +81 -0
  27. data/lib/irb/help.rb +37 -0
  28. data/lib/irb/init.rb +312 -0
  29. data/lib/irb/input-method.rb +298 -0
  30. data/lib/irb/inspector.rb +142 -0
  31. data/lib/irb/lc/.document +4 -0
  32. data/lib/irb/lc/error.rb +32 -0
  33. data/lib/irb/lc/help-message +50 -0
  34. data/lib/irb/lc/ja/encoding_aliases.rb +11 -0
  35. data/lib/irb/lc/ja/error.rb +31 -0
  36. data/lib/irb/lc/ja/help-message +52 -0
  37. data/lib/irb/locale.rb +182 -0
  38. data/lib/irb/magic-file.rb +38 -0
  39. data/lib/irb/notifier.rb +232 -0
  40. data/lib/irb/output-method.rb +92 -0
  41. data/lib/irb/ruby-lex.rb +492 -0
  42. data/lib/irb/ruby-token.rb +267 -0
  43. data/lib/irb/slex.rb +282 -0
  44. data/lib/irb/src_encoding.rb +7 -0
  45. data/lib/irb/version.rb +17 -0
  46. data/lib/irb/workspace.rb +190 -0
  47. data/lib/irb/ws-for-case-2.rb +15 -0
  48. data/lib/irb/xmp.rb +170 -0
  49. metadata +133 -0
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: false
2
+ # save-history.rb -
3
+ # $Release Version: 0.9.6$
4
+ # $Revision$
5
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
6
+ #
7
+ # --
8
+ #
9
+ #
10
+ #
11
+
12
+ require "readline"
13
+
14
+ module IRB
15
+ module HistorySavingAbility # :nodoc:
16
+ end
17
+
18
+ class Context
19
+ def init_save_history# :nodoc:
20
+ unless (class<<@io;self;end).include?(HistorySavingAbility)
21
+ @io.extend(HistorySavingAbility)
22
+ end
23
+ end
24
+
25
+ # A copy of the default <code>IRB.conf[:SAVE_HISTORY]</code>
26
+ def save_history
27
+ IRB.conf[:SAVE_HISTORY]
28
+ end
29
+
30
+ remove_method :save_history= if method_defined?(:save_history=)
31
+ # Sets <code>IRB.conf[:SAVE_HISTORY]</code> to the given +val+ and calls
32
+ # #init_save_history with this context.
33
+ #
34
+ # Will store the number of +val+ entries of history in the #history_file
35
+ #
36
+ # Add the following to your +.irbrc+ to change the number of history
37
+ # entries stored to 1000:
38
+ #
39
+ # IRB.conf[:SAVE_HISTORY] = 1000
40
+ def save_history=(val)
41
+ IRB.conf[:SAVE_HISTORY] = val
42
+ if val
43
+ main_context = IRB.conf[:MAIN_CONTEXT]
44
+ main_context = self unless main_context
45
+ main_context.init_save_history
46
+ end
47
+ end
48
+
49
+ # A copy of the default <code>IRB.conf[:HISTORY_FILE]</code>
50
+ def history_file
51
+ IRB.conf[:HISTORY_FILE]
52
+ end
53
+
54
+ # Set <code>IRB.conf[:HISTORY_FILE]</code> to the given +hist+.
55
+ def history_file=(hist)
56
+ IRB.conf[:HISTORY_FILE] = hist
57
+ end
58
+ end
59
+
60
+ module HistorySavingAbility # :nodoc:
61
+ def HistorySavingAbility.extended(obj)
62
+ IRB.conf[:AT_EXIT].push proc{obj.save_history}
63
+ obj.load_history
64
+ obj
65
+ end
66
+
67
+ def load_history
68
+ return unless self.class.const_defined?(:HISTORY)
69
+ history = self.class::HISTORY
70
+ if history_file = IRB.conf[:HISTORY_FILE]
71
+ history_file = File.expand_path(history_file)
72
+ end
73
+ history_file = IRB.rc_file("_history") unless history_file
74
+ if File.exist?(history_file)
75
+ open(history_file) do |f|
76
+ f.each { |l|
77
+ l = l.chomp
78
+ if self.class == ReidlineInputMethod and history.last&.end_with?("\\")
79
+ history.last.delete_suffix!("\\")
80
+ history.last << "\n" << l
81
+ else
82
+ history << l
83
+ end
84
+ }
85
+ end
86
+ end
87
+ end
88
+
89
+ def save_history
90
+ return unless self.class.const_defined?(:HISTORY)
91
+ history = self.class::HISTORY
92
+ if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) > 0
93
+ if history_file = IRB.conf[:HISTORY_FILE]
94
+ history_file = File.expand_path(history_file)
95
+ end
96
+ history_file = IRB.rc_file("_history") unless history_file
97
+
98
+ # Change the permission of a file that already exists[BUG #7694]
99
+ begin
100
+ if File.stat(history_file).mode & 066 != 0
101
+ File.chmod(0600, history_file)
102
+ end
103
+ rescue Errno::ENOENT
104
+ rescue Errno::EPERM
105
+ return
106
+ rescue
107
+ raise
108
+ end
109
+
110
+ open(history_file, 'w', 0600 ) do |f|
111
+ hist = history.map{ |l| l.split("\n").join("\\\n") }
112
+ f.puts(hist[-num..-1] || hist)
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # irb/lib/tracer.rb -
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+ require "tracer"
13
+
14
+ module IRB
15
+
16
+ # initialize tracing function
17
+ def IRB.initialize_tracer
18
+ Tracer.verbose = false
19
+ Tracer.add_filter {
20
+ |event, file, line, id, binding, *rests|
21
+ /^#{Regexp.quote(@CONF[:IRB_LIB_PATH])}/ !~ file and
22
+ File::basename(file) != "irb.rb"
23
+ }
24
+ end
25
+
26
+ class Context
27
+ # Whether Tracer is used when evaluating statements in this context.
28
+ #
29
+ # See +lib/tracer.rb+ for more information.
30
+ attr_reader :use_tracer
31
+ alias use_tracer? use_tracer
32
+
33
+ # Sets whether or not to use the Tracer library when evaluating statements
34
+ # in this context.
35
+ #
36
+ # See +lib/tracer.rb+ for more information.
37
+ def use_tracer=(opt)
38
+ if opt
39
+ Tracer.set_get_line_procs(@irb_path) {
40
+ |line_no, *rests|
41
+ @io.line(line_no)
42
+ }
43
+ elsif !opt && @use_tracer
44
+ Tracer.off
45
+ end
46
+ @use_tracer=opt
47
+ end
48
+ end
49
+
50
+ class WorkSpace
51
+ alias __evaluate__ evaluate
52
+ # Evaluate the context of this workspace and use the Tracer library to
53
+ # output the exact lines of code are being executed in chronological order.
54
+ #
55
+ # See +lib/tracer.rb+ for more information.
56
+ def evaluate(context, statements, file = nil, line = nil)
57
+ if context.use_tracer? && file != nil && line != nil
58
+ Tracer.on
59
+ begin
60
+ __evaluate__(context, statements, file, line)
61
+ ensure
62
+ Tracer.off
63
+ end
64
+ else
65
+ __evaluate__(context, statements, file || __FILE__, line || __LINE__)
66
+ end
67
+ end
68
+ end
69
+
70
+ IRB.initialize_tracer
71
+ end
72
+
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # use-loader.rb -
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+
13
+ require_relative "../cmd/load"
14
+ require_relative "loader"
15
+
16
+ class Object
17
+ alias __original__load__IRB_use_loader__ load
18
+ alias __original__require__IRB_use_loader__ require
19
+ end
20
+
21
+ module IRB
22
+ module ExtendCommandBundle
23
+ remove_method :irb_load if method_defined?(:irb_load)
24
+ # Loads the given file similarly to Kernel#load, see IrbLoader#irb_load
25
+ def irb_load(*opts, &b)
26
+ ExtendCommand::Load.execute(irb_context, *opts, &b)
27
+ end
28
+ remove_method :irb_require if method_defined?(:irb_require)
29
+ # Loads the given file similarly to Kernel#require
30
+ def irb_require(*opts, &b)
31
+ ExtendCommand::Require.execute(irb_context, *opts, &b)
32
+ end
33
+ end
34
+
35
+ class Context
36
+
37
+ IRB.conf[:USE_LOADER] = false
38
+
39
+ # Returns whether +irb+'s own file reader method is used by
40
+ # +load+/+require+ or not.
41
+ #
42
+ # This mode is globally affected (irb-wide).
43
+ def use_loader
44
+ IRB.conf[:USE_LOADER]
45
+ end
46
+
47
+ alias use_loader? use_loader
48
+
49
+ remove_method :use_loader= if method_defined?(:use_loader=)
50
+ # Sets IRB.conf[:USE_LOADER]
51
+ #
52
+ # See #use_loader for more information.
53
+ def use_loader=(opt)
54
+
55
+ if IRB.conf[:USE_LOADER] != opt
56
+ IRB.conf[:USE_LOADER] = opt
57
+ if opt
58
+ if !$".include?("irb/cmd/load")
59
+ end
60
+ (class<<@workspace.main;self;end).instance_eval {
61
+ alias_method :load, :irb_load
62
+ alias_method :require, :irb_require
63
+ }
64
+ else
65
+ (class<<@workspace.main;self;end).instance_eval {
66
+ alias_method :load, :__original__load__IRB_use_loader__
67
+ alias_method :require, :__original__require__IRB_use_loader__
68
+ }
69
+ end
70
+ end
71
+ print "Switch to load/require#{unless use_loader; ' non';end} trace mode.\n" if verbose?
72
+ opt
73
+ end
74
+ end
75
+ end
76
+
77
+
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # push-ws.rb -
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+
13
+ module IRB # :nodoc:
14
+ class Context
15
+
16
+ # Size of the current WorkSpace stack
17
+ def irb_level
18
+ workspace_stack.size
19
+ end
20
+
21
+ # WorkSpaces in the current stack
22
+ def workspaces
23
+ if defined? @workspaces
24
+ @workspaces
25
+ else
26
+ @workspaces = []
27
+ end
28
+ end
29
+
30
+ # Creates a new workspace with the given object or binding, and appends it
31
+ # onto the current #workspaces stack.
32
+ #
33
+ # See IRB::Context#change_workspace and IRB::WorkSpace.new for more
34
+ # information.
35
+ def push_workspace(*_main)
36
+ if _main.empty?
37
+ if workspaces.empty?
38
+ print "No other workspace\n"
39
+ return nil
40
+ end
41
+ ws = workspaces.pop
42
+ workspaces.push @workspace
43
+ @workspace = ws
44
+ return workspaces
45
+ end
46
+
47
+ workspaces.push @workspace
48
+ @workspace = WorkSpace.new(@workspace.binding, _main[0])
49
+ if !(class<<main;ancestors;end).include?(ExtendCommandBundle)
50
+ main.extend ExtendCommandBundle
51
+ end
52
+ end
53
+
54
+ # Removes the last element from the current #workspaces stack and returns
55
+ # it, or +nil+ if the current workspace stack is empty.
56
+ #
57
+ # Also, see #push_workspace.
58
+ def pop_workspace
59
+ if workspaces.empty?
60
+ print "workspace stack empty\n"
61
+ return
62
+ end
63
+ @workspace = workspaces.pop
64
+ end
65
+ end
66
+ end
67
+
@@ -0,0 +1,328 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # irb/extend-command.rb - irb extend command
4
+ # $Release Version: 0.9.6$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ruby-lang.org)
7
+ #
8
+ # --
9
+ #
10
+ #
11
+ #
12
+ module IRB # :nodoc:
13
+ # Installs the default irb extensions command bundle.
14
+ module ExtendCommandBundle
15
+ EXCB = ExtendCommandBundle # :nodoc:
16
+
17
+ # See #install_alias_method.
18
+ NO_OVERRIDE = 0
19
+ # See #install_alias_method.
20
+ OVERRIDE_PRIVATE_ONLY = 0x01
21
+ # See #install_alias_method.
22
+ OVERRIDE_ALL = 0x02
23
+
24
+ # Quits the current irb context
25
+ #
26
+ # +ret+ is the optional signal or message to send to Context#exit
27
+ #
28
+ # Same as <code>IRB.CurrentContext.exit</code>.
29
+ def irb_exit(ret = 0)
30
+ irb_context.exit(ret)
31
+ end
32
+
33
+ # Displays current configuration.
34
+ #
35
+ # Modifing the configuration is achieved by sending a message to IRB.conf.
36
+ def irb_context
37
+ IRB.CurrentContext
38
+ end
39
+
40
+ @ALIASES = [
41
+ [:context, :irb_context, NO_OVERRIDE],
42
+ [:conf, :irb_context, NO_OVERRIDE],
43
+ [:irb_quit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
44
+ [:exit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
45
+ [:quit, :irb_exit, OVERRIDE_PRIVATE_ONLY],
46
+ ]
47
+
48
+ @EXTEND_COMMANDS = [
49
+ [
50
+ :irb_current_working_workspace, :CurrentWorkingWorkspace, "irb/cmd/chws",
51
+ [:irb_print_working_workspace, OVERRIDE_ALL],
52
+ [:irb_cwws, OVERRIDE_ALL],
53
+ [:irb_pwws, OVERRIDE_ALL],
54
+ [:cwws, NO_OVERRIDE],
55
+ [:pwws, NO_OVERRIDE],
56
+ [:irb_current_working_binding, OVERRIDE_ALL],
57
+ [:irb_print_working_binding, OVERRIDE_ALL],
58
+ [:irb_cwb, OVERRIDE_ALL],
59
+ [:irb_pwb, OVERRIDE_ALL],
60
+ ],
61
+ [
62
+ :irb_change_workspace, :ChangeWorkspace, "irb/cmd/chws",
63
+ [:irb_chws, OVERRIDE_ALL],
64
+ [:irb_cws, OVERRIDE_ALL],
65
+ [:chws, NO_OVERRIDE],
66
+ [:cws, NO_OVERRIDE],
67
+ [:irb_change_binding, OVERRIDE_ALL],
68
+ [:irb_cb, OVERRIDE_ALL],
69
+ [:cb, NO_OVERRIDE],
70
+ ],
71
+
72
+ [
73
+ :irb_workspaces, :Workspaces, "irb/cmd/pushws",
74
+ [:workspaces, NO_OVERRIDE],
75
+ [:irb_bindings, OVERRIDE_ALL],
76
+ [:bindings, NO_OVERRIDE],
77
+ ],
78
+ [
79
+ :irb_push_workspace, :PushWorkspace, "irb/cmd/pushws",
80
+ [:irb_pushws, OVERRIDE_ALL],
81
+ [:pushws, NO_OVERRIDE],
82
+ [:irb_push_binding, OVERRIDE_ALL],
83
+ [:irb_pushb, OVERRIDE_ALL],
84
+ [:pushb, NO_OVERRIDE],
85
+ ],
86
+ [
87
+ :irb_pop_workspace, :PopWorkspace, "irb/cmd/pushws",
88
+ [:irb_popws, OVERRIDE_ALL],
89
+ [:popws, NO_OVERRIDE],
90
+ [:irb_pop_binding, OVERRIDE_ALL],
91
+ [:irb_popb, OVERRIDE_ALL],
92
+ [:popb, NO_OVERRIDE],
93
+ ],
94
+
95
+ [
96
+ :irb_load, :Load, "irb/cmd/load"],
97
+ [
98
+ :irb_require, :Require, "irb/cmd/load"],
99
+ [
100
+ :irb_source, :Source, "irb/cmd/load",
101
+ [:source, NO_OVERRIDE],
102
+ ],
103
+
104
+ [
105
+ :irb, :IrbCommand, "irb/cmd/subirb"],
106
+ [
107
+ :irb_jobs, :Jobs, "irb/cmd/subirb",
108
+ [:jobs, NO_OVERRIDE],
109
+ ],
110
+ [
111
+ :irb_fg, :Foreground, "irb/cmd/subirb",
112
+ [:fg, NO_OVERRIDE],
113
+ ],
114
+ [
115
+ :irb_kill, :Kill, "irb/cmd/subirb",
116
+ [:kill, OVERRIDE_PRIVATE_ONLY],
117
+ ],
118
+
119
+ [
120
+ :irb_help, :Help, "irb/cmd/help",
121
+ [:help, NO_OVERRIDE],
122
+ ],
123
+
124
+ ]
125
+
126
+ # Installs the default irb commands:
127
+ #
128
+ # +irb_current_working_workspace+:: Context#main
129
+ # +irb_change_workspace+:: Context#change_workspace
130
+ # +irb_workspaces+:: Context#workspaces
131
+ # +irb_push_workspace+:: Context#push_workspace
132
+ # +irb_pop_workspace+:: Context#pop_workspace
133
+ # +irb_load+:: #irb_load
134
+ # +irb_require+:: #irb_require
135
+ # +irb_source+:: IrbLoader#source_file
136
+ # +irb+:: IRB.irb
137
+ # +irb_jobs+:: JobManager
138
+ # +irb_fg+:: JobManager#switch
139
+ # +irb_kill+:: JobManager#kill
140
+ # +irb_help+:: IRB@Command+line+options
141
+ def self.install_extend_commands
142
+ for args in @EXTEND_COMMANDS
143
+ def_extend_command(*args)
144
+ end
145
+ end
146
+
147
+ # Evaluate the given +cmd_name+ on the given +cmd_class+ Class.
148
+ #
149
+ # Will also define any given +aliases+ for the method.
150
+ #
151
+ # The optional +load_file+ parameter will be required within the method
152
+ # definition.
153
+ def self.def_extend_command(cmd_name, cmd_class, load_file = nil, *aliases)
154
+ case cmd_class
155
+ when Symbol
156
+ cmd_class = cmd_class.id2name
157
+ when String
158
+ when Class
159
+ cmd_class = cmd_class.name
160
+ end
161
+
162
+ if load_file
163
+ line = __LINE__; eval %[
164
+ def #{cmd_name}(*opts, &b)
165
+ require "#{load_file}"
166
+ arity = ExtendCommand::#{cmd_class}.instance_method(:execute).arity
167
+ args = (1..(arity < 0 ? ~arity : arity)).map {|i| "arg" + i.to_s }
168
+ args << "*opts" if arity < 0
169
+ args << "&block"
170
+ args = args.join(", ")
171
+ line = __LINE__; eval %[
172
+ def #{cmd_name}(\#{args})
173
+ ExtendCommand::#{cmd_class}.execute(irb_context, \#{args})
174
+ end
175
+ ], nil, __FILE__, line
176
+ send :#{cmd_name}, *opts, &b
177
+ end
178
+ ], nil, __FILE__, line
179
+ else
180
+ line = __LINE__; eval %[
181
+ def #{cmd_name}(*opts, &b)
182
+ ExtendCommand::#{cmd_class}.execute(irb_context, *opts, &b)
183
+ end
184
+ ], nil, __FILE__, line
185
+ end
186
+
187
+ for ali, flag in aliases
188
+ @ALIASES.push [ali, cmd_name, flag]
189
+ end
190
+ end
191
+
192
+ # Installs alias methods for the default irb commands, see
193
+ # ::install_extend_commands.
194
+ def install_alias_method(to, from, override = NO_OVERRIDE)
195
+ to = to.id2name unless to.kind_of?(String)
196
+ from = from.id2name unless from.kind_of?(String)
197
+
198
+ if override == OVERRIDE_ALL or
199
+ (override == OVERRIDE_PRIVATE_ONLY) && !respond_to?(to) or
200
+ (override == NO_OVERRIDE) && !respond_to?(to, true)
201
+ target = self
202
+ (class << self; self; end).instance_eval{
203
+ if target.respond_to?(to, true) &&
204
+ !target.respond_to?(EXCB.irb_original_method_name(to), true)
205
+ alias_method(EXCB.irb_original_method_name(to), to)
206
+ end
207
+ alias_method to, from
208
+ }
209
+ else
210
+ print "irb: warn: can't alias #{to} from #{from}.\n"
211
+ end
212
+ end
213
+
214
+ def self.irb_original_method_name(method_name) # :nodoc:
215
+ "irb_" + method_name + "_org"
216
+ end
217
+
218
+ # Installs alias methods for the default irb commands on the given object
219
+ # using #install_alias_method.
220
+ def self.extend_object(obj)
221
+ unless (class << obj; ancestors; end).include?(EXCB)
222
+ super
223
+ for ali, com, flg in @ALIASES
224
+ obj.install_alias_method(ali, com, flg)
225
+ end
226
+ end
227
+ end
228
+
229
+ install_extend_commands
230
+ end
231
+
232
+ # Extends methods for the Context module
233
+ module ContextExtender
234
+ CE = ContextExtender # :nodoc:
235
+
236
+ @EXTEND_COMMANDS = [
237
+ [:eval_history=, "irb/ext/history.rb"],
238
+ [:use_tracer=, "irb/ext/tracer.rb"],
239
+ [:use_loader=, "irb/ext/use-loader.rb"],
240
+ [:save_history=, "irb/ext/save-history.rb"],
241
+ ]
242
+
243
+ # Installs the default context extensions as irb commands:
244
+ #
245
+ # Context#eval_history=:: +irb/ext/history.rb+
246
+ # Context#use_tracer=:: +irb/ext/tracer.rb+
247
+ # Context#use_loader=:: +irb/ext/use-loader.rb+
248
+ # Context#save_history=:: +irb/ext/save-history.rb+
249
+ def self.install_extend_commands
250
+ for args in @EXTEND_COMMANDS
251
+ def_extend_command(*args)
252
+ end
253
+ end
254
+
255
+ # Evaluate the given +command+ from the given +load_file+ on the Context
256
+ # module.
257
+ #
258
+ # Will also define any given +aliases+ for the method.
259
+ def self.def_extend_command(cmd_name, load_file, *aliases)
260
+ line = __LINE__; Context.module_eval %[
261
+ def #{cmd_name}(*opts, &b)
262
+ Context.module_eval {remove_method(:#{cmd_name})}
263
+ require "#{load_file}"
264
+ send :#{cmd_name}, *opts, &b
265
+ end
266
+ for ali in aliases
267
+ alias_method ali, cmd_name
268
+ end
269
+ ], __FILE__, line
270
+ end
271
+
272
+ CE.install_extend_commands
273
+ end
274
+
275
+ # A convenience module for extending Ruby methods.
276
+ module MethodExtender
277
+ # Extends the given +base_method+ with a prefix call to the given
278
+ # +extend_method+.
279
+ def def_pre_proc(base_method, extend_method)
280
+ base_method = base_method.to_s
281
+ extend_method = extend_method.to_s
282
+
283
+ alias_name = new_alias_name(base_method)
284
+ module_eval %[
285
+ alias_method alias_name, base_method
286
+ def #{base_method}(*opts)
287
+ send :#{extend_method}, *opts
288
+ send :#{alias_name}, *opts
289
+ end
290
+ ]
291
+ end
292
+
293
+ # Extends the given +base_method+ with a postfix call to the given
294
+ # +extend_method+.
295
+ def def_post_proc(base_method, extend_method)
296
+ base_method = base_method.to_s
297
+ extend_method = extend_method.to_s
298
+
299
+ alias_name = new_alias_name(base_method)
300
+ module_eval %[
301
+ alias_method alias_name, base_method
302
+ def #{base_method}(*opts)
303
+ send :#{alias_name}, *opts
304
+ send :#{extend_method}, *opts
305
+ end
306
+ ]
307
+ end
308
+
309
+ # Returns a unique method name to use as an alias for the given +name+.
310
+ #
311
+ # Usually returns <code>#{prefix}#{name}#{postfix}<num></code>, example:
312
+ #
313
+ # new_alias_name('foo') #=> __alias_of__foo__
314
+ # def bar; end
315
+ # new_alias_name('bar') #=> __alias_of__bar__2
316
+ def new_alias_name(name, prefix = "__alias_of__", postfix = "__")
317
+ base_name = "#{prefix}#{name}#{postfix}"
318
+ all_methods = instance_methods(true) + private_instance_methods(true)
319
+ same_methods = all_methods.grep(/^#{Regexp.quote(base_name)}[0-9]*$/)
320
+ return base_name if same_methods.empty?
321
+ no = same_methods.size
322
+ while !same_methods.include?(alias_name = base_name + no)
323
+ no += 1
324
+ end
325
+ alias_name
326
+ end
327
+ end
328
+ end