irb 1.1.0.pre.3

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