irb 1.0.0

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