utils 0.0.39 → 0.0.40
Sign up to get free protection for your applications and to get access to all the features.
- 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
|