utils 0.0.39 → 0.0.40
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.
- data/Rakefile +2 -2
- data/TODO +1 -2
- data/VERSION +1 -1
- data/bin/chroot-libs +8 -4
- data/bin/probe +31 -26
- data/lib/utils/config/config_file.rb +7 -5
- data/lib/utils/config/irbrc +1 -491
- data/lib/utils/config/vim/autoload/rails.vim +16 -16
- data/lib/utils/editor.rb +17 -5
- data/lib/utils/file_xt.rb +3 -6
- data/lib/utils/find.rb +132 -28
- data/lib/utils/finder.rb +5 -5
- data/lib/utils/grepper.rb +7 -4
- data/lib/utils/irb.rb +507 -0
- data/lib/utils/version.rb +1 -1
- data/utils.gemspec +11 -11
- metadata +46 -15
@@ -4021,15 +4021,15 @@ function! s:BufAbbreviations()
|
|
4021
4021
|
Rabbrev coo[ cookies
|
4022
4022
|
Rabbrev fl[ flash
|
4023
4023
|
Rabbrev rr( render
|
4024
|
-
Rabbrev ra( render :action\ =>\
|
4025
|
-
Rabbrev rc( render :controller\ =>\
|
4026
|
-
Rabbrev rf( render :file\ =>\
|
4027
|
-
Rabbrev ri( render :inline\ =>\
|
4028
|
-
Rabbrev rj( render :json\ =>\
|
4029
|
-
Rabbrev rl( render :layout\ =>\
|
4030
|
-
Rabbrev rp( render :partial\ =>\
|
4031
|
-
Rabbrev rt( render :text\ =>\
|
4032
|
-
Rabbrev rx( render :xml\ =>\
|
4024
|
+
Rabbrev ra( render :action\ =>\
|
4025
|
+
Rabbrev rc( render :controller\ =>\
|
4026
|
+
Rabbrev rf( render :file\ =>\
|
4027
|
+
Rabbrev ri( render :inline\ =>\
|
4028
|
+
Rabbrev rj( render :json\ =>\
|
4029
|
+
Rabbrev rl( render :layout\ =>\
|
4030
|
+
Rabbrev rp( render :partial\ =>\
|
4031
|
+
Rabbrev rt( render :text\ =>\
|
4032
|
+
Rabbrev rx( render :xml\ =>\
|
4033
4033
|
endif
|
4034
4034
|
if buffer.type_name('view','helper')
|
4035
4035
|
Rabbrev dotiw distance_of_time_in_words
|
@@ -4037,8 +4037,8 @@ function! s:BufAbbreviations()
|
|
4037
4037
|
endif
|
4038
4038
|
if buffer.type_name('controller')
|
4039
4039
|
Rabbrev re( redirect_to
|
4040
|
-
Rabbrev rea( redirect_to :action\ =>\
|
4041
|
-
Rabbrev rec( redirect_to :controller\ =>\
|
4040
|
+
Rabbrev rea( redirect_to :action\ =>\
|
4041
|
+
Rabbrev rec( redirect_to :controller\ =>\
|
4042
4042
|
Rabbrev rst( respond_to
|
4043
4043
|
endif
|
4044
4044
|
if buffer.type_name() ==# 'model' || buffer.type_name('model-arb')
|
@@ -4076,13 +4076,13 @@ function! s:BufAbbreviations()
|
|
4076
4076
|
Rabbrev asre( assert_response
|
4077
4077
|
Rabbrev art( assert_redirected_to
|
4078
4078
|
endif
|
4079
|
-
Rabbrev :a :action\ =>\
|
4079
|
+
Rabbrev :a :action\ =>\
|
4080
4080
|
" hax
|
4081
|
-
Rabbrev :c :co________\ =>\
|
4081
|
+
Rabbrev :c :co________\ =>\
|
4082
4082
|
inoreabbrev <buffer> <silent> :c <C-R>=<SID>TheCWord()<CR>
|
4083
|
-
Rabbrev :i :id\ =>\
|
4084
|
-
Rabbrev :o :object\ =>\
|
4085
|
-
Rabbrev :p :partial\ =>\
|
4083
|
+
Rabbrev :i :id\ =>\
|
4084
|
+
Rabbrev :o :object\ =>\
|
4085
|
+
Rabbrev :p :partial\ =>\
|
4086
4086
|
Rabbrev logd( logger.debug
|
4087
4087
|
Rabbrev logi( logger.info
|
4088
4088
|
Rabbrev logw( logger.warn
|
data/lib/utils/editor.rb
CHANGED
@@ -6,15 +6,26 @@ module Utils
|
|
6
6
|
|
7
7
|
module SourceLocationExtension
|
8
8
|
def source_location
|
9
|
+
filename = nil
|
10
|
+
linenumber = nil
|
9
11
|
if respond_to?(:to_str)
|
10
12
|
if (string = to_str) =~ FILE_LINENUMBER_REGEXP
|
11
|
-
|
13
|
+
filename = $1
|
14
|
+
linenumber = $2.to_i
|
15
|
+
[ $1, linenumber ]
|
12
16
|
else
|
13
|
-
|
17
|
+
filename = string
|
14
18
|
end
|
15
19
|
else
|
16
|
-
|
20
|
+
filename = to_s
|
17
21
|
end
|
22
|
+
array = linenumber ? [ filename, linenumber ] : [ filename, 1 ]
|
23
|
+
array.singleton_class.instance_eval do
|
24
|
+
define_method(:filename) { filename }
|
25
|
+
define_method(:linenumber) { linenumber }
|
26
|
+
define_method(:to_s) { [ filename, linenumber ].compact * ':' }
|
27
|
+
end
|
28
|
+
array
|
18
29
|
end
|
19
30
|
end
|
20
31
|
|
@@ -38,6 +49,7 @@ module Utils
|
|
38
49
|
alias wait? wait
|
39
50
|
|
40
51
|
def vim
|
52
|
+
vim_in_path = [`which gvim`, `which vim`].map(&:chomp).find(&:full?)
|
41
53
|
@vim ||=
|
42
54
|
case `uname -s`
|
43
55
|
when /\Adarwin/i
|
@@ -46,10 +58,10 @@ module Utils
|
|
46
58
|
then
|
47
59
|
File.join(path, 'Contents/MacOS/Vim')
|
48
60
|
else
|
49
|
-
|
61
|
+
vim_in_path
|
50
62
|
end
|
51
63
|
else
|
52
|
-
|
64
|
+
vim_in_path
|
53
65
|
end
|
54
66
|
end
|
55
67
|
|
data/lib/utils/file_xt.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
require 'dslkit/polite'
|
2
|
+
|
1
3
|
module Utils
|
2
4
|
module FileXt
|
5
|
+
extend DSLKit::Concern
|
3
6
|
include File::Constants
|
4
7
|
|
5
8
|
SEEK_SET = File::SEEK_SET
|
@@ -30,12 +33,6 @@ module Utils
|
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
33
|
-
def self.included(modul)
|
34
|
-
modul.instance_eval do
|
35
|
-
extend ClassMethods
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
36
|
module ClassMethods
|
40
37
|
def binary?(name)
|
41
38
|
File.open(name, 'rb') { |f| f.binary? }
|
data/lib/utils/find.rb
CHANGED
@@ -1,42 +1,146 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
1
3
|
module Utils
|
2
4
|
module Find
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
def find(*paths) # :yield: path
|
10
|
-
paths.collect!{|d| d.dup}
|
11
|
-
while file = paths.shift
|
12
|
-
catch(:prune) do
|
13
|
-
yield file.dup.taint
|
14
|
-
next unless File.exist? file
|
5
|
+
class ConfigurableFinder
|
6
|
+
module PathExtension
|
7
|
+
attr_writer :finder
|
8
|
+
|
9
|
+
def file
|
10
|
+
tried = false
|
15
11
|
begin
|
16
|
-
|
17
|
-
|
12
|
+
file = @finder.get_file(self)
|
13
|
+
if file
|
14
|
+
file.closed? and file.reopen
|
15
|
+
else
|
16
|
+
file = File.new(self)
|
17
|
+
@finder.add_file self, file
|
18
|
+
end
|
19
|
+
return file
|
20
|
+
rescue Errno::EMFILE
|
21
|
+
tried and raise
|
22
|
+
@finder.close_files
|
23
|
+
tried = true
|
24
|
+
retry
|
25
|
+
rescue Errno::ENOENT, Errno::EACCES
|
26
|
+
return
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def pathname
|
31
|
+
Pathname.new(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
def suffix
|
35
|
+
pathname.extname[1..-1]
|
36
|
+
end
|
37
|
+
|
38
|
+
def exist?
|
39
|
+
!!file
|
40
|
+
end
|
41
|
+
|
42
|
+
def stat
|
43
|
+
file and file.stat
|
44
|
+
end
|
45
|
+
|
46
|
+
def lstat
|
47
|
+
file and file.lstat
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize(opts = {})
|
52
|
+
@files = {}
|
53
|
+
opts[:suffix].full? { |s| @suffix = [*s] }
|
54
|
+
@follow_symlinks = opts.fetch(:follow_symlinks, false)
|
55
|
+
end
|
56
|
+
|
57
|
+
def include_suffix?(suffix)
|
58
|
+
@suffix.nil? || @suffix.include?(suffix)
|
59
|
+
end
|
60
|
+
|
61
|
+
def visit_file?(file)
|
62
|
+
suffix = File.extname(file).full?(:[], 1..-1) || ''
|
63
|
+
include_suffix?(suffix)
|
64
|
+
end
|
65
|
+
|
66
|
+
def prepare_file(file)
|
67
|
+
path = file.dup.taint
|
68
|
+
path.extend PathExtension
|
69
|
+
path.finder = self
|
70
|
+
path
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_file(path)
|
74
|
+
@files[path]
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_file(path, file)
|
78
|
+
@files[path] = file
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
def close_files
|
83
|
+
@files.each_value do |f|
|
84
|
+
f.closed? or f.close
|
85
|
+
end
|
86
|
+
nil
|
87
|
+
end
|
88
|
+
|
89
|
+
def stat(file)
|
90
|
+
@follow_symlinks ? file.stat : file.lstat
|
91
|
+
end
|
92
|
+
|
93
|
+
def find(*paths, &block)
|
94
|
+
block_given? or return enum_for(__method__, *paths)
|
95
|
+
|
96
|
+
paths.map! do |d|
|
97
|
+
File.exist?(d) or raise Errno::ENOENT
|
98
|
+
d.dup
|
99
|
+
end
|
100
|
+
|
101
|
+
while file = paths.shift
|
102
|
+
catch(:prune) do
|
103
|
+
file = prepare_file(file)
|
104
|
+
visit_file?(file) and yield file
|
105
|
+
begin
|
106
|
+
s = stat(file) or next
|
107
|
+
rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG
|
108
|
+
next
|
109
|
+
end
|
110
|
+
if s.directory? then
|
18
111
|
begin
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
112
|
+
tried = false
|
113
|
+
fs = Dir.entries(file)
|
114
|
+
rescue Errno::EMFILE
|
115
|
+
tried and raise
|
116
|
+
close_files
|
117
|
+
tried = true
|
118
|
+
retry
|
119
|
+
rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG
|
120
|
+
next
|
121
|
+
end
|
122
|
+
fs.sort!
|
123
|
+
fs.reverse_each do |f|
|
124
|
+
next if f == "." or f == ".."
|
125
|
+
f = File.join(file, f)
|
126
|
+
paths.unshift f.untaint
|
32
127
|
end
|
33
128
|
end
|
34
|
-
rescue Errno::ENOENT, Errno::EACCES
|
35
129
|
end
|
36
130
|
end
|
37
131
|
end
|
38
132
|
end
|
39
133
|
|
134
|
+
# Calls the associated block with the name of every file and directory
|
135
|
+
# listed as arguments, then recursively on their subdirectories, and so on.
|
136
|
+
#
|
137
|
+
# See the +Find+ module documentation for an example.
|
138
|
+
#
|
139
|
+
def find(*paths, &block) # :yield: path
|
140
|
+
paths, options = paths.extract_last_argument_options
|
141
|
+
ConfigurableFinder.new(options).find(*paths, &block)
|
142
|
+
end
|
143
|
+
|
40
144
|
#
|
41
145
|
# Skips the current file or directory, restarting the loop with the next
|
42
146
|
# entry. If the current file is a directory, that directory will not be
|
data/lib/utils/finder.rb
CHANGED
@@ -36,8 +36,8 @@ class Utils::Finder
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def attempt_match?(path)
|
39
|
-
stat =
|
40
|
-
stat.symlink? and stat =
|
39
|
+
stat = path.stat
|
40
|
+
stat.symlink? and stat = path.lstat
|
41
41
|
if @only_directory
|
42
42
|
stat.directory?
|
43
43
|
elsif @directory
|
@@ -54,10 +54,10 @@ class Utils::Finder
|
|
54
54
|
pathes = []
|
55
55
|
find(*@roots) do |filename|
|
56
56
|
begin
|
57
|
-
bn, s =
|
57
|
+
bn, s = filename.pathname.basename, filename.stat
|
58
58
|
if s.directory? && @config.discover.prune?(bn)
|
59
59
|
$DEBUG and warn "Pruning #{filename.inspect}."
|
60
|
-
|
60
|
+
prune
|
61
61
|
end
|
62
62
|
if s.file? && @config.discover.skip?(bn)
|
63
63
|
$DEBUG and warn "Skipping #{filename.inspect}."
|
@@ -73,7 +73,7 @@ class Utils::Finder
|
|
73
73
|
@suffixes = @args['I'].ask_and_send(:split, /[\s,]+/).to_a
|
74
74
|
pathes = pathes.map! do |path, dir, file|
|
75
75
|
if @suffixes.full?
|
76
|
-
@suffixes.include?(
|
76
|
+
@suffixes.include?(path.suffix) or next
|
77
77
|
end
|
78
78
|
if do_match = attempt_match?(path) and $DEBUG
|
79
79
|
warn "Attempt match of #{path.inspect}"
|
data/lib/utils/grepper.rb
CHANGED
@@ -6,6 +6,7 @@ class ::File
|
|
6
6
|
end
|
7
7
|
|
8
8
|
class Utils::Grepper
|
9
|
+
include Utils::Find
|
9
10
|
include Utils::Patterns
|
10
11
|
include Term::ANSIColor
|
11
12
|
|
@@ -71,9 +72,11 @@ class Utils::Grepper
|
|
71
72
|
bn, s = File.basename(filename), File.stat(filename)
|
72
73
|
if s.directory? && @config.search.prune?(bn)
|
73
74
|
$DEBUG and warn "Pruning #{filename.inspect}."
|
74
|
-
|
75
|
+
prune
|
75
76
|
end
|
76
|
-
if s.file? && !@config.search.skip?(bn) &&
|
77
|
+
if s.file? && !@config.search.skip?(bn) &&
|
78
|
+
(!@name_pattern || @name_pattern.match(bn))
|
79
|
+
then
|
77
80
|
File.open(filename, 'rb') do |file|
|
78
81
|
if file.binary? != true
|
79
82
|
$DEBUG and warn "Matching #{filename.inspect}."
|
@@ -147,8 +150,8 @@ class Utils::Grepper
|
|
147
150
|
def search
|
148
151
|
@suffixes = @args['I'].ask_and_send(:split, /[\s,]+/).to_a
|
149
152
|
for dir in @roots
|
150
|
-
|
151
|
-
if @suffixes.empty? || @suffixes.include?(
|
153
|
+
find(dir) do |filename|
|
154
|
+
if @suffixes.empty? || @suffixes.include?(filename.suffix)
|
152
155
|
match(filename)
|
153
156
|
end
|
154
157
|
end
|
data/lib/utils/irb.rb
ADDED
@@ -0,0 +1,507 @@
|
|
1
|
+
require 'tins/xt'
|
2
|
+
require 'irb/completion'
|
3
|
+
require 'enumerator'
|
4
|
+
require 'pp'
|
5
|
+
require_maybe 'ap'
|
6
|
+
if Readline.respond_to?(:point) && Readline.respond_to?(:line_buffer)
|
7
|
+
require 'pry-editline'
|
8
|
+
end
|
9
|
+
require 'utils'
|
10
|
+
$editor = Utils::Editor.new
|
11
|
+
$pager = ENV['PAGER'] || 'less -r'
|
12
|
+
|
13
|
+
if IRB.conf[:PROMPT]
|
14
|
+
IRB.conf[:PROMPT][:CUSTOM] = {
|
15
|
+
:PROMPT_I => ">> ",
|
16
|
+
:PROMPT_N => ">> ",
|
17
|
+
:PROMPT_S => "%l> ",
|
18
|
+
:PROMPT_C => "+> ",
|
19
|
+
:RETURN => " # => %s\n"
|
20
|
+
}
|
21
|
+
IRB.conf[:PROMPT_MODE] = :CUSTOM
|
22
|
+
end
|
23
|
+
|
24
|
+
module Utils
|
25
|
+
module IRB
|
26
|
+
|
27
|
+
module Shell
|
28
|
+
require 'fileutils'
|
29
|
+
include FileUtils
|
30
|
+
require 'utils/find'
|
31
|
+
include Utils::Find
|
32
|
+
|
33
|
+
# Start _ri_ for +pattern+. If +pattern+ is not string like, call it with
|
34
|
+
# pattern.class.name as argument.
|
35
|
+
def ri(*patterns)
|
36
|
+
patterns.map! { |p| p.respond_to?(:to_str) ? p.to_str : p.class.name }
|
37
|
+
system "ri #{patterns.map { |p| "'#{p}'" } * ' '} | #{$pager}"
|
38
|
+
end
|
39
|
+
|
40
|
+
# Restart this irb.
|
41
|
+
def irb_restart
|
42
|
+
exec $0
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return all instance methods of obj's class.
|
46
|
+
def irb_all_class_instance_methods(obj)
|
47
|
+
methods = obj.class.instance_methods
|
48
|
+
irb_wrap_methods obj, methods
|
49
|
+
end
|
50
|
+
|
51
|
+
# Return instance methods of obj's class without the inherited/mixed in
|
52
|
+
# methods.
|
53
|
+
def irb_class_instance_methods(obj)
|
54
|
+
methods = obj.class.instance_methods(false)
|
55
|
+
irb_wrap_methods obj, methods
|
56
|
+
end
|
57
|
+
|
58
|
+
# Return all instance methods defined in module modul.
|
59
|
+
def irb_all_instance_methods(modul)
|
60
|
+
methods = modul.instance_methods
|
61
|
+
irb_wrap_methods modul, methods, true
|
62
|
+
end
|
63
|
+
|
64
|
+
# Return instance methods defined in module modul without the inherited/mixed
|
65
|
+
# in methods.
|
66
|
+
def irb_instance_methods(modul)
|
67
|
+
methods = modul.instance_methods(false)
|
68
|
+
irb_wrap_methods modul, methods, true
|
69
|
+
end
|
70
|
+
|
71
|
+
# Return all methods of obj (including obj's eigenmethods.)
|
72
|
+
def irb_all_methods(obj)
|
73
|
+
methods = obj.methods
|
74
|
+
irb_wrap_methods obj, methods
|
75
|
+
end
|
76
|
+
|
77
|
+
# Return instance methods of obj's class without the inherited/mixed in
|
78
|
+
# methods, but including obj's eigenmethods.
|
79
|
+
def irb_methods(obj)
|
80
|
+
methods = obj.class.ancestors[1..-1].inject(obj.methods) do |all, a|
|
81
|
+
all -= a.instance_methods
|
82
|
+
end
|
83
|
+
irb_wrap_methods obj, methods
|
84
|
+
end
|
85
|
+
|
86
|
+
# Return all eigen methods of obj.
|
87
|
+
def irb_eigen_methods(obj)
|
88
|
+
irb_wrap_methods obj, obj.methods(false)
|
89
|
+
end
|
90
|
+
|
91
|
+
def irb_wrap_methods(obj, methods, modul = false)
|
92
|
+
methods.map do |name|
|
93
|
+
MethodWrapper.new(obj, name, modul) rescue nil
|
94
|
+
end.compact.sort!
|
95
|
+
end
|
96
|
+
|
97
|
+
class WrapperBase
|
98
|
+
include Comparable
|
99
|
+
|
100
|
+
def initialize(name)
|
101
|
+
@name =
|
102
|
+
case
|
103
|
+
when name.respond_to?(:to_str)
|
104
|
+
name.to_str
|
105
|
+
when name.respond_to?(:to_sym)
|
106
|
+
name.to_sym.to_s
|
107
|
+
else
|
108
|
+
name.to_s
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
attr_reader :name
|
113
|
+
|
114
|
+
attr_reader :description
|
115
|
+
|
116
|
+
alias to_str name
|
117
|
+
|
118
|
+
alias inspect description
|
119
|
+
|
120
|
+
alias to_s description
|
121
|
+
|
122
|
+
def ==(name)
|
123
|
+
@name = name
|
124
|
+
end
|
125
|
+
|
126
|
+
alias eql? ==
|
127
|
+
|
128
|
+
def hash
|
129
|
+
@name.hash
|
130
|
+
end
|
131
|
+
|
132
|
+
def <=>(other)
|
133
|
+
@name <=> other.name
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
class MethodWrapper < WrapperBase
|
138
|
+
def initialize(obj, name, modul)
|
139
|
+
super(name)
|
140
|
+
if modul
|
141
|
+
@arity = obj.instance_method(name).arity
|
142
|
+
else
|
143
|
+
@arity = obj.method(name).arity
|
144
|
+
end
|
145
|
+
@description = "#@name(#@arity)"
|
146
|
+
end
|
147
|
+
|
148
|
+
attr_reader :arity
|
149
|
+
end
|
150
|
+
|
151
|
+
class ConstantWrapper < WrapperBase
|
152
|
+
def initialize(obj, name)
|
153
|
+
super(name)
|
154
|
+
@klass = obj.class
|
155
|
+
@description = "#@name:#@klass"
|
156
|
+
end
|
157
|
+
|
158
|
+
attr_reader :klass
|
159
|
+
end
|
160
|
+
|
161
|
+
# Return all the constants defined in +modul+.
|
162
|
+
def irb_constants(modul)
|
163
|
+
modul.constants.map { |c| ConstantWrapper.new(modul.const_get(c), c) }.sort
|
164
|
+
end
|
165
|
+
|
166
|
+
# Return all the subclasses of +klass+. TODO implement subclasses w/out rails
|
167
|
+
def irb_subclasses(klass)
|
168
|
+
klass.subclasses.map { |c| ConstantWrapper.new(eval(c), c) }.sort
|
169
|
+
end
|
170
|
+
|
171
|
+
unless Object.const_defined?(:Infinity)
|
172
|
+
Infinity = 1.0 / 0 # I like to define the infinite.
|
173
|
+
end
|
174
|
+
|
175
|
+
# Output all kinds of information about +obj+. If detailed is given output
|
176
|
+
# details about the methods (+ arity) in inheritance chain of +obj+ as well.
|
177
|
+
# * detailed as 0 output instance methods only of part 0 (the first) of the
|
178
|
+
# chain.
|
179
|
+
# * detailed as 1..2 output instance methods of +obj+ inherited from parts 1
|
180
|
+
# and 2 of the the chain.
|
181
|
+
def irb_info(obj, detailed = nil)
|
182
|
+
if Module === obj
|
183
|
+
modul = obj
|
184
|
+
klassp = Class === modul
|
185
|
+
if klassp
|
186
|
+
begin
|
187
|
+
allocated = modul.allocate
|
188
|
+
rescue TypeError
|
189
|
+
else
|
190
|
+
obj = allocated
|
191
|
+
end
|
192
|
+
end
|
193
|
+
else
|
194
|
+
modul = obj.class
|
195
|
+
end
|
196
|
+
inspected = obj.inspect
|
197
|
+
puts "obj = #{inspected.size > 40 ? inspected[0, 40] + '...' : inspected} is of class #{obj.class}."
|
198
|
+
am = irb_all_methods(obj).size
|
199
|
+
ms = irb_methods(obj).size
|
200
|
+
ems = irb_eigen_methods(obj).size
|
201
|
+
puts "obj: #{am} methods, #{ms} only local#{ems > 0 ? " (#{ems} eigenmethods),": ','} #{am - ms} inherited/mixed in."
|
202
|
+
acim = irb_all_class_instance_methods(obj).size
|
203
|
+
cim = irb_class_instance_methods(obj).size
|
204
|
+
puts "obj: #{acim} instance methods, #{cim} local, #{acim - cim} only inherited/mixed in."
|
205
|
+
if klassp
|
206
|
+
s = modul.superclass
|
207
|
+
puts "Superclass of #{modul}: #{s}"
|
208
|
+
end
|
209
|
+
a = []
|
210
|
+
ec = true
|
211
|
+
begin
|
212
|
+
a << (class << obj; self; end)
|
213
|
+
rescue TypeError
|
214
|
+
ec = false
|
215
|
+
end
|
216
|
+
a.concat modul.ancestors
|
217
|
+
if ec
|
218
|
+
puts "Ancestors of #{modul}: (#{a[0]},) #{a[1..-1].map { |k| "#{k}#{k == s ? '*' : ''}" } * ', '}"
|
219
|
+
else
|
220
|
+
puts "Ancestors of #{modul}: #{a[0..-1].map { |k| "#{k}#{k == s ? '*' : ''}" } * ', '}"
|
221
|
+
end
|
222
|
+
if Class === modul and detailed
|
223
|
+
if detailed.respond_to? :to_int
|
224
|
+
detailed = detailed..detailed
|
225
|
+
end
|
226
|
+
detailed.each do |i|
|
227
|
+
break if i >= a.size
|
228
|
+
k = a[i]
|
229
|
+
puts "#{k}:"
|
230
|
+
puts irb_wrap_methods(obj, k.instance_methods(false)).sort
|
231
|
+
end
|
232
|
+
end
|
233
|
+
nil
|
234
|
+
end
|
235
|
+
|
236
|
+
# Output *all* the irb_info about +obj+. You may need to buy a bigger screen for
|
237
|
+
# this or use:
|
238
|
+
# less { irb_fullinfo object }
|
239
|
+
def irb_fullinfo(obj)
|
240
|
+
irb_info obj, 0..Infinity
|
241
|
+
end
|
242
|
+
|
243
|
+
def capture_output(with_stderr = false)
|
244
|
+
return "missing block" unless block_given?
|
245
|
+
require 'tempfile'
|
246
|
+
begin
|
247
|
+
old_stdout, $stdout = $stdout, Tempfile.new('irb')
|
248
|
+
if with_stderr
|
249
|
+
old_stderr, $stderr = $stderr, $stdout
|
250
|
+
end
|
251
|
+
yield
|
252
|
+
ensure
|
253
|
+
$stdout, temp = old_stdout, $stdout
|
254
|
+
with_stderr and $stderr = old_stderr
|
255
|
+
end
|
256
|
+
temp.rewind
|
257
|
+
temp.read
|
258
|
+
end
|
259
|
+
|
260
|
+
# Use pager on the output of the commands given in the block.
|
261
|
+
def less(with_stderr = false, &block)
|
262
|
+
IO.popen($pager, 'w') do |f|
|
263
|
+
f.write capture_output(with_stderr, &block)
|
264
|
+
f.close_write
|
265
|
+
end
|
266
|
+
nil
|
267
|
+
end
|
268
|
+
|
269
|
+
def irb_time
|
270
|
+
s = Time.now
|
271
|
+
yield
|
272
|
+
d = Time.now - s
|
273
|
+
warn "Took %.3fs seconds." % d
|
274
|
+
d
|
275
|
+
end
|
276
|
+
|
277
|
+
def irb_time_tap
|
278
|
+
r = nil
|
279
|
+
irb_time { r = yield }
|
280
|
+
r
|
281
|
+
end
|
282
|
+
|
283
|
+
def irb_time_watch(duration = 1)
|
284
|
+
start = Time.now
|
285
|
+
pre = nil
|
286
|
+
loop do
|
287
|
+
cur = [ yield ].flatten
|
288
|
+
unless pre
|
289
|
+
pre = cur.map(&:to_f)
|
290
|
+
cur = [ yield ].flatten
|
291
|
+
end
|
292
|
+
expired = Time.now - start
|
293
|
+
diffs = cur.zip(pre).map { |c, p| c - p }
|
294
|
+
rates = diffs.map { |d| d / duration }
|
295
|
+
warn "#{expired} #{cur.zip(rates, diffs).map(&:inspect) * ' '} # / per sec."
|
296
|
+
pre = cur.map(&:to_f)
|
297
|
+
sleep duration
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
def irb_write(filename, text = nil)
|
302
|
+
File.secure_write filename, text, 'wb'
|
303
|
+
end
|
304
|
+
|
305
|
+
def irb_read(filename, chunk_size = 8_192)
|
306
|
+
if block_given?
|
307
|
+
File.open(filename) do |file|
|
308
|
+
until file.eof?
|
309
|
+
yield file.read(chunk_size)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
else
|
313
|
+
IO.read filename
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def irb_load!(*files)
|
318
|
+
files = files.map { |f| f.gsub(/(\.rb)?\Z/, '.rb') }
|
319
|
+
loaded = {}
|
320
|
+
for file in files
|
321
|
+
catch :found do
|
322
|
+
Find.find('.') do |f|
|
323
|
+
File.directory?(f) and next
|
324
|
+
md5_f = Utils::MD5.md5(f)
|
325
|
+
if f.end_with?(file) and !loaded[md5_f]
|
326
|
+
Kernel.load f
|
327
|
+
loaded[md5_f] = true
|
328
|
+
STDERR.puts "Loaded '#{f}'."
|
329
|
+
end
|
330
|
+
end
|
331
|
+
Find.find('.') do |f|
|
332
|
+
File.directory?(f) and next
|
333
|
+
md5_f = Utils::MD5.md5(f)
|
334
|
+
if f.end_with?(file) and !loaded[md5_f]
|
335
|
+
Kernel.load f
|
336
|
+
loaded[md5_f] = true
|
337
|
+
STDERR.puts "Loaded '#{f}'."
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
nil
|
343
|
+
end
|
344
|
+
|
345
|
+
def irb_edit(*files)
|
346
|
+
$editor.full?(:edit, *files)
|
347
|
+
end
|
348
|
+
|
349
|
+
# List contents of directory
|
350
|
+
def ls(*args)
|
351
|
+
puts `ls #{args.map { |x| "'#{x}'" } * ' '}`
|
352
|
+
end
|
353
|
+
|
354
|
+
if defined?(ActiveRecord::Base)
|
355
|
+
$logger = Logger.new(STDERR)
|
356
|
+
def irb_toggle_logging
|
357
|
+
require 'logger'
|
358
|
+
if ActiveRecord::Base.logger != $logger
|
359
|
+
$old_logger = ActiveRecord::Base.logger
|
360
|
+
ActiveRecord::Base.logger = $logger
|
361
|
+
true
|
362
|
+
else
|
363
|
+
ActiveRecord::Base.logger = $old_logger
|
364
|
+
false
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
module Module
|
371
|
+
# Start +ri+ for +module#pattern+, trying to find a method matching +pattern+
|
372
|
+
# for all modules in the ancestors chain of this module.
|
373
|
+
def ri(pattern = nil)
|
374
|
+
if pattern
|
375
|
+
pattern = pattern.to_sym.to_s if pattern.respond_to? :to_sym
|
376
|
+
ancestors.each do |a|
|
377
|
+
if method = a.instance_methods(false).find { |m| pattern === m }
|
378
|
+
a = Object if a == Kernel # ri seems to be confused
|
379
|
+
system "ri #{a}##{method} | #{$pager}"
|
380
|
+
end
|
381
|
+
end
|
382
|
+
else
|
383
|
+
system "ri #{self} | #{$pager}"
|
384
|
+
end
|
385
|
+
return
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
module Regexp
|
390
|
+
# Show the match of this Regexp on the +string+.
|
391
|
+
def show_match(string)
|
392
|
+
string =~ self ? "#{$`}<<#{$&}>>#{$'}" : "no match"
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
module String
|
397
|
+
# Pipe this string into +cmd+.
|
398
|
+
def |(cmd)
|
399
|
+
IO.popen(cmd, 'w+') do |f|
|
400
|
+
f.write self
|
401
|
+
f.close_write
|
402
|
+
return f.read
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
# Write this string into file +filename+.
|
407
|
+
def >>(filename)
|
408
|
+
File.secure_write(filename, self)
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
module Relation
|
413
|
+
def explain
|
414
|
+
connection.select_all("EXPLAIN #{to_sql}")
|
415
|
+
end
|
416
|
+
end
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
module IRB
|
421
|
+
class Context
|
422
|
+
def init_save_history
|
423
|
+
unless (class<<@io;self;end).include?(HistorySavingAbility)
|
424
|
+
@io.extend(HistorySavingAbility)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
def save_history
|
429
|
+
IRB.conf[:SAVE_HISTORY]
|
430
|
+
end
|
431
|
+
|
432
|
+
def save_history=(val)
|
433
|
+
IRB.conf[:SAVE_HISTORY] = val
|
434
|
+
if val
|
435
|
+
main_context = IRB.conf[:MAIN_CONTEXT]
|
436
|
+
main_context = self unless main_context
|
437
|
+
main_context.init_save_history
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
def history_file
|
442
|
+
IRB.conf[:HISTORY_FILE]
|
443
|
+
end
|
444
|
+
|
445
|
+
def history_file=(hist)
|
446
|
+
IRB.conf[:HISTORY_FILE] = hist
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
module HistorySavingAbility
|
451
|
+
include Readline
|
452
|
+
|
453
|
+
def HistorySavingAbility.create_finalizer
|
454
|
+
at_exit do
|
455
|
+
if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) > 0
|
456
|
+
if hf = IRB.conf[:HISTORY_FILE]
|
457
|
+
file = File.expand_path(hf)
|
458
|
+
end
|
459
|
+
file = IRB.rc_file("_history") unless file
|
460
|
+
open(file, 'w' ) do |f|
|
461
|
+
hist = HISTORY.to_a
|
462
|
+
f.puts(hist[-num..-1] || hist)
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
def HistorySavingAbility.extended(obj)
|
469
|
+
HistorySavingAbility.create_finalizer
|
470
|
+
obj.load_history
|
471
|
+
obj
|
472
|
+
end
|
473
|
+
|
474
|
+
def load_history
|
475
|
+
hist = IRB.conf[:HISTORY_FILE]
|
476
|
+
hist = IRB.rc_file("_history") unless hist
|
477
|
+
if File.exist?(hist)
|
478
|
+
open(hist) do |f|
|
479
|
+
f.each {|l| HISTORY << l.chomp}
|
480
|
+
end
|
481
|
+
end
|
482
|
+
end
|
483
|
+
end
|
484
|
+
end
|
485
|
+
IRB.conf[:SAVE_HISTORY] = 1000
|
486
|
+
|
487
|
+
if defined?(ActiveRecord::Relation)
|
488
|
+
class ActiveRecord::Relation
|
489
|
+
include Utils::IRB::Relation
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
class String
|
494
|
+
include Utils::IRB::String
|
495
|
+
end
|
496
|
+
|
497
|
+
class Object
|
498
|
+
include Utils::IRB::Shell
|
499
|
+
end
|
500
|
+
|
501
|
+
class Module
|
502
|
+
include Utils::IRB::Module
|
503
|
+
end
|
504
|
+
|
505
|
+
class Regexp
|
506
|
+
include Utils::IRB::Regexp
|
507
|
+
end
|