YkLib 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +6 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +7 -0
  7. data/Gemfile.lock +34 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +44 -0
  10. data/Rakefile +6 -0
  11. data/YkLib.gemspec +29 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/lib/YkLib/Yk/__advance__.rb +151 -0
  15. data/lib/YkLib/Yk/__defun__.rb +44 -0
  16. data/lib/YkLib/Yk/__hook__.rb +244 -0
  17. data/lib/YkLib/Yk/__minmax__.rb +123 -0
  18. data/lib/YkLib/Yk/__stdlog.rb +329 -0
  19. data/lib/YkLib/Yk/adhocLiterals/email.rb +119 -0
  20. data/lib/YkLib/Yk/adhocLiterals/path.rb +402 -0
  21. data/lib/YkLib/Yk/adhocLiterals/tag.rb +19 -0
  22. data/lib/YkLib/Yk/adhocLiterals/url.rb +36 -0
  23. data/lib/YkLib/Yk/adhocLiterals.rb +199 -0
  24. data/lib/YkLib/Yk/auto_escseq.rb +5 -0
  25. data/lib/YkLib/Yk/auto_pstore.rb +179 -0
  26. data/lib/YkLib/Yk/bsearch.rb +120 -0
  27. data/lib/YkLib/Yk/clambda.rb +309 -0
  28. data/lib/YkLib/Yk/confLine.rb +423 -0
  29. data/lib/YkLib/Yk/create_tty_width_available.rb +24 -0
  30. data/lib/YkLib/Yk/crypt.rb +26 -0
  31. data/lib/YkLib/Yk/debug2 +1 -0
  32. data/lib/YkLib/Yk/debug2.rb +473 -0
  33. data/lib/YkLib/Yk/debugout.rb +139 -0
  34. data/lib/YkLib/Yk/email_tz.rb +533 -0
  35. data/lib/YkLib/Yk/enum_expect.rb +170 -0
  36. data/lib/YkLib/Yk/errlog.rb +5 -0
  37. data/lib/YkLib/Yk/escseq.rb +59 -0
  38. data/lib/YkLib/Yk/eval_alt.rb +281 -0
  39. data/lib/YkLib/Yk/expector.rb +93 -0
  40. data/lib/YkLib/Yk/fetch.rb +556 -0
  41. data/lib/YkLib/Yk/fetch_old.rb +290 -0
  42. data/lib/YkLib/Yk/fib.rb +158 -0
  43. data/lib/YkLib/Yk/file_aux.rb +843 -0
  44. data/lib/YkLib/Yk/file_aux2.rb +919 -0
  45. data/lib/YkLib/Yk/file_aux_old.rb +160 -0
  46. data/lib/YkLib/Yk/filemod.rb +19 -0
  47. data/lib/YkLib/Yk/force_escseq.rb +3 -0
  48. data/lib/YkLib/Yk/generator__.rb +144 -0
  49. data/lib/YkLib/Yk/generator__.rb.org +139 -0
  50. data/lib/YkLib/Yk/indenter/argless_case.rb +46 -0
  51. data/lib/YkLib/Yk/indenter/each_token.rb +671 -0
  52. data/lib/YkLib/Yk/indenter/free_case.rb +313 -0
  53. data/lib/YkLib/Yk/indenter/if_less.rb +53 -0
  54. data/lib/YkLib/Yk/indenter/independent_ensure.rb +23 -0
  55. data/lib/YkLib/Yk/indenter/independent_rescue.rb +23 -0
  56. data/lib/YkLib/Yk/indenter/operand_circumflex.rb +0 -0
  57. data/lib/YkLib/Yk/indenter/operand_period.rb +16 -0
  58. data/lib/YkLib/Yk/indenter/parenless_and.rb +37 -0
  59. data/lib/YkLib/Yk/indenter/post_test.rb +48 -0
  60. data/lib/YkLib/Yk/indenter/token.rb +1525 -0
  61. data/lib/YkLib/Yk/indenter.rb +1382 -0
  62. data/lib/YkLib/Yk/inot.rb +265 -0
  63. data/lib/YkLib/Yk/intf.rb +815 -0
  64. data/lib/YkLib/Yk/io_aux.rb +1332 -0
  65. data/lib/YkLib/Yk/ioctl.rb +60 -0
  66. data/lib/YkLib/Yk/ipcc.rb +87 -0
  67. data/lib/YkLib/Yk/ipcountry.rb +207 -0
  68. data/lib/YkLib/Yk/ipv4adr.rb +318 -0
  69. data/lib/YkLib/Yk/localmail.rb +276 -0
  70. data/lib/YkLib/Yk/method_chain.rb +359 -0
  71. data/lib/YkLib/Yk/misc_tz.rb +1716 -0
  72. data/lib/YkLib/Yk/missing_method.rb +50 -0
  73. data/lib/YkLib/Yk/mojiConv.rb +257 -0
  74. data/lib/YkLib/Yk/nostdlog.rb +4 -0
  75. data/lib/YkLib/Yk/on_marshal.rb +20 -0
  76. data/lib/YkLib/Yk/overrider.rb +47 -0
  77. data/lib/YkLib/Yk/path.rb +293 -0
  78. data/lib/YkLib/Yk/path_aux.rb +883 -0
  79. data/lib/YkLib/Yk/path_aux_alt.rb +0 -0
  80. data/lib/YkLib/Yk/path_rep.rb +1267 -0
  81. data/lib/YkLib/Yk/pg_setup.rb +917 -0
  82. data/lib/YkLib/Yk/procinfo.rb +314 -0
  83. data/lib/YkLib/Yk/proclist.rb +492 -0
  84. data/lib/YkLib/Yk/property.rb +863 -0
  85. data/lib/YkLib/Yk/ranger.rb +606 -0
  86. data/lib/YkLib/Yk/resolv_tz.rb +88 -0
  87. data/lib/YkLib/Yk/rlprompt.rb +73 -0
  88. data/lib/YkLib/Yk/rootexec.rb +48 -0
  89. data/lib/YkLib/Yk/rpm-packageproxy.rb +784 -0
  90. data/lib/YkLib/Yk/rpm-packageproxy2.rb +1430 -0
  91. data/lib/YkLib/Yk/rwhen.rb +21 -0
  92. data/lib/YkLib/Yk/selector.rb +124 -0
  93. data/lib/YkLib/Yk/set.rb +170 -0
  94. data/lib/YkLib/Yk/shellquote.rb +300 -0
  95. data/lib/YkLib/Yk/sio.rb +1001 -0
  96. data/lib/YkLib/Yk/sio0.rb +835 -0
  97. data/lib/YkLib/Yk/sio_aux.rb +1524 -0
  98. data/lib/YkLib/Yk/sio_inot.rb +86 -0
  99. data/lib/YkLib/Yk/sock_aux.rb +42 -0
  100. data/lib/YkLib/Yk/spipe.rb +843 -0
  101. data/lib/YkLib/Yk/sql_table.rb +565 -0
  102. data/lib/YkLib/Yk/stdlog.rb +4 -0
  103. data/lib/YkLib/Yk/syscommand.rb +173 -0
  104. data/lib/YkLib/Yk/sysinit.rb +75 -0
  105. data/lib/YkLib/Yk/ttyFontWidth.rb +46113 -0
  106. data/lib/YkLib/Yk/tty_char.dump +0 -0
  107. data/lib/YkLib/Yk/tty_char.rb +47 -0
  108. data/lib/YkLib/Yk/tty_char_create.rb +437031 -0
  109. data/lib/YkLib/Yk/tty_char_static.rb +437016 -0
  110. data/lib/YkLib/Yk/tty_rewrite.rb +142 -0
  111. data/lib/YkLib/Yk/tty_str.rb +461 -0
  112. data/lib/YkLib/Yk/tty_width.dat.rb +114 -0
  113. data/lib/YkLib/Yk/tty_width.rb +180 -0
  114. data/lib/YkLib/Yk/tty_width_available +569 -0
  115. data/lib/YkLib/Yk/tty_width_list +0 -0
  116. data/lib/YkLib/Yk/tty_width_list.linux +280 -0
  117. data/lib/YkLib/Yk/tty_width_list.windows +324 -0
  118. data/lib/YkLib/Yk/tz_tty +0 -0
  119. data/lib/YkLib/Yk/tz_tty.rb +0 -0
  120. data/lib/YkLib/Yk/uprepos.rb +94 -0
  121. data/lib/YkLib/Yk/userinfo.rb +91 -0
  122. data/lib/YkLib/Yk/with.rb +109 -0
  123. data/lib/YkLib/version.rb +3 -0
  124. data/lib/YkLib.rb +6 -0
  125. metadata +170 -0
@@ -0,0 +1,276 @@
1
+
2
+
3
+ require 'Yk/path_aux'
4
+ require 'net/smtp'
5
+ require 'net/pop'
6
+ require 'thread'
7
+ require 'Yk/misc_tz'
8
+ require 'Yk/procinfo'
9
+
10
+
11
+
12
+ class RemoteMail < String
13
+ def send (content, subject = nil)
14
+ LocalMail.each do |m|
15
+ m.sendTo(self, content, subject)
16
+ end
17
+ end
18
+ def self.setMails (lmdir = "/etc/local_mail/remote".check_dir)
19
+ if !defined? @@mails
20
+ @@mails = []
21
+ lmdir.each_entry do |f|
22
+ if f =~ /\@/
23
+ i = 0
24
+ @@mails.push RemoteMail.new(f.basename)
25
+ end
26
+ end
27
+ if !@@mails.significant?
28
+ raise LocalMail::Error.new("cannot find mail configuration")
29
+ end
30
+ end
31
+ @@mails
32
+ end
33
+ def self.send (content, subject = nil)
34
+ if !defined? @@mails
35
+ setMails
36
+ end
37
+ @@mails.each do |e|
38
+ e.send content, subject
39
+ end
40
+ LocalMail.flush
41
+ end
42
+ end
43
+
44
+
45
+ class LocalMail < String
46
+ class Error < Exception
47
+ end
48
+ DEF_LIST = %w[
49
+ SMTP_SERVER
50
+ SMTP_ACCOUNT
51
+ SMTP_PASSWD
52
+ POP_SERVER
53
+ POP_ACCOUNT
54
+ POP_PASSWD
55
+ POP_BEFORE_SMTP
56
+ ]
57
+ @@localMails = []
58
+ def initialize (fileName)
59
+ super fileName.basename
60
+ if CYGWIN || Process.euid == 0
61
+ fileName.read_each_line do |ln|
62
+ ln.strip_comment!
63
+ if ln.significant?
64
+ res = ln.getDefinition DEF_LIST do |k, v|
65
+ instanceVariableSet(k, v)
66
+ end
67
+ if !res
68
+ raise LocalMail::Error.new("illeagal line `#{ln}' at #{i}")
69
+ end
70
+ end
71
+ end
72
+ if !@popAccount
73
+ @popAccount = self
74
+ end
75
+ if !@smtpAccount
76
+ @smtpAccount = @popAccount
77
+ end
78
+ if !@smtpPasswd
79
+ @smtpPasswd = @popPasswd
80
+ end
81
+ end
82
+ @mutex = Mutex.new
83
+ @fmutex = Mutex.new
84
+ @rmutex = Mutex.new
85
+ @mail = self
86
+ @queue = []
87
+ @@localMails.push self
88
+ end
89
+ def recieve mode = nil
90
+ @rmutex.synchronize do
91
+ begin
92
+ pobj = Net::POP3.new(@popServer, 110)
93
+ pobj.open_timeout = 1200
94
+ pobj.start(@popAccount, @popPasswd) do |pop|
95
+ if mode == ""
96
+ next
97
+ end
98
+ hash = Hash.new
99
+ pop.each_mail do |m|
100
+ if mode == "flush"
101
+ m.delete
102
+ next
103
+ end
104
+ pop = m.pop.gsub /\r\n/, "\n"
105
+ begin
106
+ begin
107
+ yield pop #MailipReciever::MailContent.new(m.pop)
108
+ ensure
109
+ m.delete
110
+ end
111
+ rescue Exception, SignalException => e
112
+ raise Reexception.new
113
+ end
114
+ end
115
+ end
116
+ rescue Reexception => e
117
+ e.reraise
118
+ rescue Exception, SignalException => e
119
+ emsg = ""
120
+ if e.to_s != ""
121
+ emsg = " (#{e.to_s.gsub(/\s+/, ' ').strip})"
122
+ end
123
+ errln "#{e.class.to_s}: failed to retrieve a mail from #{@mail}#{emsg}"
124
+ end
125
+ end
126
+ end
127
+ def sendTo (toAdr, content, subject = nil)
128
+ if @popBeforeSmtp
129
+ recieve @popBeforeSmtp
130
+ end
131
+ if subject
132
+ t = content
133
+ content = subject
134
+ subject = t
135
+ end
136
+ c = -%{
137
+ Date: #{arr = Time.now.localtime.to_s.split; arr[0] + ', ' + arr[2] + ' ' + arr[1] + ' ' + arr[5] + ' ' + arr[3] + ' ' + arr[4]}
138
+ From: #{ProcInfo.current.cmdline.shellDQuote} <#{self}>
139
+ To: #{toAdr}
140
+ Subject: #{subject}
141
+ }
142
+ c += "\n" + content.ln
143
+ @mutex.synchronize do
144
+ @queue.push [c, self, toAdr]
145
+ end
146
+ end
147
+ def flush
148
+ @mutex.synchronize do
149
+ if @queue.size == 0
150
+ return
151
+ end
152
+ end
153
+ @fmutex.synchronize do
154
+ connectRetryCount = 0
155
+ begin
156
+ connectRetryCount += 1
157
+ Net::SMTP.start(@smtpServer, 25, 'localhost.localdomain', @smtpAccount, @smtpPasswd, :login) do |smtp|
158
+ while true
159
+ gotItem = false
160
+ params = nil
161
+ @mutex.synchronize do
162
+ if @queue.size > 0
163
+ params = @queue.shift
164
+ gotItem = true
165
+ end
166
+ end
167
+ if !gotItem
168
+ break
169
+ end
170
+ content, fromAdr, toAdr = params
171
+ retryCount = 0
172
+ begin
173
+ retryCount += 1
174
+ smtp.send_mail content, fromAdr, toAdr
175
+ rescue Exception => e
176
+ errln "cannot send from #{fromAdr} to #{toAdr} (#{e.class}:#{e.to_s.gsub(/\s+/, ' ')}.strip); Retring....".ln
177
+ sleep 10
178
+ if retryCount > 3
179
+ errln "All retrials failed. Giving up sending from #{fromAdr} to #{toAdr}.".ln
180
+ else
181
+ retry
182
+ end
183
+ end
184
+ end
185
+ end
186
+ rescue => e
187
+ errln "cannot complete sending mails from #{self} (#{e.class}:#{e.to_s.gsub(/\s+/, ' ')}.strip); Retrying....".ln
188
+ sleep 10
189
+ if connectRetryCount > 3
190
+ errln "All retrials failed. Giving up sending mails from #{self}.".ln
191
+ else
192
+ retry
193
+ end
194
+ end
195
+ end
196
+ end
197
+ def self.chkMails
198
+ if !defined? @@mails
199
+ setMails
200
+ end
201
+ end
202
+ def self.recieve
203
+ chkMails
204
+ tList = []
205
+ @@localMails.each do |m|
206
+ t = Thread.new do
207
+ m.recieve do |c|
208
+ yield c
209
+ end
210
+ end
211
+ tList.push t
212
+ end
213
+ tList.each do |t|
214
+ t.join
215
+ end
216
+ end
217
+ def self.setMails (lmdir = "/etc/local_mail/local".check_dir)
218
+ if !defined? @@mails
219
+ @@mails = []
220
+ lmdir.each_entry do |f|
221
+ if f =~ /\@/
222
+ i = 0
223
+ @@mails.push LocalMail.new(f)
224
+ end
225
+ end
226
+ if !@@mails.significant?
227
+ raise LocalMail::Error.new("cannot find mail configuration")
228
+ end
229
+ end
230
+ @@mails
231
+ end
232
+ def self.each
233
+ chkMails
234
+ @@mails.each do |e|
235
+ yield e
236
+ end
237
+ end
238
+ def self.flush
239
+ chkMails
240
+ @@localMails.each do |m|
241
+ m.flush
242
+ end
243
+ end
244
+ def self.keep
245
+ chkMails
246
+ @@localMails.each do |m|
247
+ m.receive ""
248
+ end
249
+ end
250
+ end
251
+
252
+
253
+ class RemoteMail < String
254
+ def send (content, subject)
255
+ sendToAdmin(content, subject)
256
+ #LocalMail.each do |m|
257
+ # m.sendTo(self, content, subject)
258
+ #end
259
+ end
260
+ def sendTo (mail, content, subject)
261
+ LocalMail.each do |m|
262
+ m.sendTo(mail, content, subject)
263
+ end
264
+ end
265
+ def sendToAdmin (content, subject)
266
+ if (mf = "/etc/local_mail/admin").readable_file?
267
+ adminMail = mf.read.strip
268
+ sendTo adminMail, content, subject
269
+ else
270
+ STDERR.write "#{$0}: cannot send mail: please set /etc/local_mail/admin\n"
271
+ end
272
+ end
273
+ end
274
+
275
+
276
+
@@ -0,0 +1,359 @@
1
+ #!/usr/bin/env ruby
2
+
3
+
4
+ require 'binding_of_caller'
5
+
6
+
7
+ class Module
8
+ def get_instence_method label
9
+ begin
10
+ org_mth = instance_method(label) # original method
11
+ rescue NameError
12
+ end
13
+ if org_mth && instance_methods(false).include?(label)
14
+ return org_mth
15
+ end
16
+ end
17
+ end
18
+
19
+ def Modules *marr, &bl
20
+ marr.each do |m|
21
+ if m.is_a?(Symbol) || m.is_a?(String)
22
+ m = binding.of_caller(1).eval(m.to_s)
23
+ end
24
+ case m
25
+ when ::Class
26
+ m.class_eval &bl
27
+ when ::Module
28
+ m.module_eval &bl
29
+ else
30
+ raise ArgumentError.new("'#{m.inspect}' is not a module")
31
+ end
32
+ end
33
+ end
34
+
35
+ class Class
36
+ def include *modules
37
+ MethodChain.doExtend self, *modules do
38
+ super
39
+ end
40
+ end
41
+ end
42
+
43
+
44
+ class Object
45
+ def extend *modules
46
+ cls = class << self; self; end
47
+ MethodChain.doExtend cls, *modules do
48
+ super
49
+ end
50
+ end
51
+ def __method_chain_caller__ l
52
+ if caller[1] =~ /^(.+?):(\d+)(?::in `(.*)')?/
53
+ f, lno, fname = $1, $2.to_i, $3
54
+ callerMethod = MethodChain.getMethod($1, $2.to_i, l)
55
+ mp = MethodChain::PrevList[callerMethod]
56
+ if mp
57
+ return mp
58
+ else
59
+ mdl = MethodChain::ModList[callerMethod]
60
+ if om = MethodChain::OrgList[[mdl, l]]
61
+ return om
62
+ else
63
+ as = (class << self; self; end).ancestors
64
+ (as.index(mdl) + 1 ... as.size).each do |i|
65
+ c = as[i]
66
+ if ent = MethodChain::EntryList[c][l]
67
+ return ent
68
+ elsif om = MethodChain::OrgList[[c, l]]
69
+ return om
70
+ elsif m = c.get_instence_method(l)
71
+ if m.source_location[0] != "(MethodChain)"
72
+ return m
73
+ end
74
+ end
75
+ end
76
+ raise ArgumentError.new("No super method defined for '#{l}'")
77
+ end
78
+ end
79
+ else
80
+ raise ArgumentError.new("Unknown error: cannot find '#{l}'")
81
+ end
82
+ end
83
+ end
84
+
85
+ class MethodChain
86
+ def self.doExtend cls, *modules
87
+ ks = Hash.new
88
+ (modules + [cls]).each do |mdl|
89
+ MethodChain::EntryList[mdl]&.keys&.each do |k|
90
+ ks[k] = true
91
+ end
92
+ end
93
+ yield
94
+ ks.keys.each do |k|
95
+ MethodChain.checkDispatcher k
96
+ if !MethodChain::EntryList[cls][k]
97
+ om = cls.get_instance_method(k)
98
+ if !om || om.source_location[0] != "(MethodChain)"
99
+ MethodChain::OrgList[[cls, k]] ||= om
100
+ cls.class_eval %{
101
+ def #{k} (...)
102
+ cls = ::ObjectSpace._id2ref(#{cls.__id__})
103
+ cls.ancestors.each do |a|
104
+ if ent = MethodChain::EntryList[a][:#{k}]
105
+ return mth.bind(self).call(...)
106
+ elsif om = MethodChain::OrgList[[cls, :#{k}]]
107
+ return om.bind(self).call(...)
108
+ elsif m = c.get_instence_method(l)
109
+ if m.source_location[0] != "(MethodChain)"
110
+ return m.bind(self).call(...)
111
+ end
112
+ end
113
+ end
114
+ raise ArgumentError.new("No method defined for '#{l}'")
115
+ end
116
+ }, "(MethodChain)", 1
117
+ end
118
+ end
119
+ end
120
+ end
121
+ PrevList = Hash.new
122
+ EntryList = Hash.new{|h, k| h[k] = {}}
123
+ OrgList = {}
124
+ ModList = {}
125
+ def self.getMethod f, lno, label
126
+ MethodRange.getMethod(f, lno, label)
127
+ end
128
+ def self.checkDispatcher l
129
+ if !(Object.instance_method("__method_chain_caller_#{l}") rescue nil)
130
+ Object.class_eval %{
131
+ def __method_chain_caller_#{l} (...)
132
+ mth = __method_chain_caller__ :#{l}
133
+ mth.bind(self).call(...)
134
+ end
135
+ }
136
+ end
137
+ end
138
+ def self.override &bl
139
+ cm = binding.of_caller(1).eval("self")
140
+ cm = ::Object if cm == TOPLEVEL_BINDING.eval("self")
141
+ if !cm.is_a? ::Module
142
+ raise Exception.new("called at non-module context")
143
+ end
144
+ new_defs = Module.new &bl
145
+ new_defs.instance_methods(false).each do |l| # newly defined method
146
+ checkDispatcher l
147
+ new_mth = MethodRange.emerge(cm, new_defs.instance_method(l), "__method_chain_caller_#{l}") # new_mth redefined as __method_chain_caller_
148
+ ModList[new_mth] = cm
149
+ old_ent = EntryList[cm][l]
150
+ EntryList[cm][l] = new_mth
151
+ if !old_ent
152
+ OrgList[[cm, l]] = cm.get_instence_method(l) # original method defined in this class
153
+ if cm.is_a? ::Class
154
+ cm.class_eval %{
155
+ def #{l} (...)
156
+ cls = ::ObjectSpace._id2ref(#{cm.__id__})
157
+ cls.ancestors.each do |a|
158
+ mth = MethodChain::EntryList[a][:#{l}]
159
+ if mth
160
+ return mth.bind(self).call(...)
161
+ end
162
+ end
163
+ end
164
+ }, "(MethodChain)", 1
165
+ end
166
+ else
167
+ PrevList[new_mth] = old_ent
168
+ end
169
+ end
170
+ end
171
+ class MethodRange
172
+ class DefnList
173
+ DFNList = {}
174
+ def self.getRangeByStart f, name, lno
175
+ (DFNList[f] ||= new(f)).getRangeByStart name, lno
176
+ end
177
+ def initialize f
178
+ storedF = ENV['HOME'] + "/.tmp/ruby/Yk/#{File.basename($0)}/" + File.expand_path(f) + "/defnList"
179
+ if File.mtime(f) < (File.mtime(storedF) rescue Time.at(0))
180
+ @defnList = Marshal.load(IO.binread(storedF))
181
+ return
182
+ end
183
+ if f == "(eval)"
184
+ raise ArgumentError.new("cannot use MethodChain for method in evaluated value")
185
+ end
186
+ root = RubyVM::AbstractSyntaxTree.parse_file(f)
187
+ @defnList = Hash.new
188
+ (regMethodDef = -> node do
189
+ if node.inspect =~/\A#\<RubyVM::AbstractSyntaxTree::Node:DEFN@(\d+):\d+\-(\d+):\d+/
190
+ rg = $1.to_i .. $2.to_i
191
+ lst = (@defnList[node.children[0]] ||= [])
192
+ pos = lst.bsearch_index do |item|
193
+ item.first >= rg.first
194
+ end
195
+ pos ||= lst.size
196
+ if pos
197
+ lst.insert pos, rg
198
+ else
199
+ lst.push rg
200
+ end
201
+ end
202
+ if defined?(node.children)
203
+ node.children.each do |e|
204
+ regMethodDef.(e)
205
+ end
206
+ end
207
+ end).(root)
208
+ require "fileutils"
209
+ FileUtils.mkdir_p File.dirname(storedF)
210
+ IO.binwrite(storedF, Marshal.dump(@defnList))
211
+ end
212
+ def getRangeByStart name, lno
213
+ lst = @defnList[name]
214
+ pos = lst.bsearch_index do |item|
215
+ item.first >= lno
216
+ end
217
+ if pos && lst[pos]
218
+ if [pos - 1, pos + 1].find{lst[_1]&.first == lno}
219
+ raise ArgumentError.new("multiple definition of method '#{name}', found in one line")
220
+ else
221
+ lst[pos]
222
+ end
223
+ else
224
+ nil
225
+ end
226
+ end
227
+ end
228
+ OList = {}
229
+ FLnList = {}
230
+ List = Hash.new{|h, k| h[k] = []}
231
+ Item = Struct.new(:rg, :mth)
232
+ attr_reader :method_chain_caller
233
+ def self.emerge cls, mth, l
234
+ (OList[[cls, mth]] ||= new cls, mth, l).method_chain_caller
235
+ end
236
+ def initialize cls, mth, l
237
+ f, lno = mth.source_location
238
+ if f == "(eval)"
239
+ raise ArgumentError.new("cannot use MethodChain for method in evaluated value")
240
+ end
241
+ mrg = DefnList.getRangeByStart f, mth.name, lno
242
+ if !mrg
243
+ raise ArgumentError.new("cannot find 'def #{mth.name}': please note that currently alias_method and method defined in eval are not supported")
244
+ end
245
+ lns = (FLnList[f] ||= IO.readlines(f))
246
+ if (toEv = lns[mrg.first - 1 .. mrg.last - 1].join).sub! /\A\s*def\s+(\w+)/, "def #{l}"
247
+ (m = Module.new).module_eval toEv, f, mrg.first
248
+ @method_chain_caller = m.instance_method(l)
249
+ else
250
+ raise ArgumentError.new("cannot find 'def #{mth.name}': please note that currently alias_method and method defined in eval are not supported")
251
+ end
252
+ pos = (l = List[[f, mth.name]]).bsearch_index{|e| e.rg.first >= mrg.first}
253
+ if pos
254
+ if l[pos].rg.first != mrg.first
255
+ l.insert pos, Item.new(mrg, mth)
256
+ else
257
+ raise ArgumentError.new("method, '#{mth.name}' is defined twice in the same line")
258
+ end
259
+ else
260
+ l.push Item.new(mrg, @method_chain_caller)
261
+ end
262
+ end
263
+ def self.getMethod f, lno, label
264
+ lst = List[[f, label]]
265
+ pos = lst.bsearch_index{|e| lno <= e.rg.first}
266
+ if pos == nil
267
+ pos = lst.size
268
+ end
269
+ smallestIdx = nil
270
+ smallestRangeSize = nil
271
+ if pos
272
+ hit = -> i do
273
+ item = lst[i]
274
+ if item
275
+ if item.rg.first < lno && lno < item.rg.last
276
+ if !smallestRangeSize&.<=(item.rg.size)
277
+ smallestRangeSize = item.rg.size
278
+ smallestIdx = i
279
+ end
280
+ break item.mth
281
+ elsif item.rg.first == lno || lno == item.rg.last
282
+ raise ArgumentEror.new("ambigous calling origin: 'super' should not be located in the same line with method definition starting by 'def' nor finising by 'end'")
283
+ end
284
+ end
285
+ nil
286
+ end
287
+ i = pos - 1
288
+ while hit.(i)
289
+ i -= 1
290
+ end
291
+ i = pos
292
+ while hit.(i)
293
+ i += 1
294
+ end
295
+ if !smallestIdx
296
+ raise ArgumentError.new("cannot find caller")
297
+ end
298
+ return lst[smallestIdx].mth
299
+ end
300
+ raise ArgumentError.new("cannot find calling origin, 'super'")
301
+ end
302
+ end
303
+ end
304
+
305
+
306
+ if File.expand_path($0) == File.expand_path(__FILE__)
307
+
308
+ class Ans
309
+ def test1
310
+ p ":Ans::org_test1"
311
+ end
312
+ end
313
+
314
+
315
+
316
+
317
+ class Des < Ans
318
+ def test1
319
+ p ":Des::org_test1"
320
+ super
321
+ end
322
+ end
323
+
324
+ Des.new.test1
325
+
326
+
327
+ class Des
328
+ MethodChain.override do
329
+ def test1
330
+ p ":Des::new_test1"
331
+ super
332
+ end
333
+ end
334
+ end
335
+
336
+ (d = Des.new).test1
337
+
338
+ class << d
339
+ MethodChain.override do
340
+ def test1
341
+ p ":Singleton::new_test1"
342
+ super
343
+ end
344
+ end
345
+ end
346
+
347
+
348
+ class << d
349
+ MethodChain.override do
350
+ def test1
351
+ p ":Singleton::new_new_test1"
352
+ super
353
+ end
354
+ end
355
+ end
356
+
357
+ d.test1
358
+
359
+ end