looksee 1.0.0-universal-java-1.6
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/CHANGELOG +14 -0
- data/LICENSE +22 -0
- data/README.markdown +161 -0
- data/Rakefile +10 -0
- data/ext/extconf.rb +9 -0
- data/ext/mri/1.9.2/debug.h +36 -0
- data/ext/mri/1.9.2/id.h +170 -0
- data/ext/mri/1.9.2/method.h +103 -0
- data/ext/mri/1.9.2/node.h +483 -0
- data/ext/mri/1.9.2/thread_pthread.h +27 -0
- data/ext/mri/1.9.2/vm_core.h +707 -0
- data/ext/mri/1.9.2/vm_opts.h +51 -0
- data/ext/mri/env-1.8.h +27 -0
- data/ext/mri/eval_c-1.8.h +27 -0
- data/ext/mri/mri.c +269 -0
- data/ext/mri/node-1.9.h +35 -0
- data/ext/rbx/rbx.c +13 -0
- data/lib/looksee.rb +5 -0
- data/lib/looksee/adapter.rb +10 -0
- data/lib/looksee/adapter/base.rb +100 -0
- data/lib/looksee/adapter/rubinius.rb +73 -0
- data/lib/looksee/clean.rb +122 -0
- data/lib/looksee/columnizer.rb +73 -0
- data/lib/looksee/core_ext.rb +59 -0
- data/lib/looksee/editor.rb +58 -0
- data/lib/looksee/help.rb +54 -0
- data/lib/looksee/inspector.rb +55 -0
- data/lib/looksee/jruby.jar +0 -0
- data/lib/looksee/lookup_path.rb +95 -0
- data/lib/looksee/rbx.bundle +0 -0
- data/lib/looksee/shortcuts.rb +3 -0
- data/lib/looksee/version.rb +11 -0
- data/lib/looksee/wirble_compatibility.rb +86 -0
- data/spec/adapter_spec.rb +546 -0
- data/spec/columnizer_spec.rb +52 -0
- data/spec/core_ext_spec.rb +41 -0
- data/spec/editor_spec.rb +128 -0
- data/spec/inspector_spec.rb +178 -0
- data/spec/lookup_path_spec.rb +84 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/core_ext.rb +25 -0
- data/spec/support/temporary_classes.rb +102 -0
- data/spec/support/test_adapter.rb +72 -0
- data/spec/wirble_compatibility_spec.rb +116 -0
- metadata +158 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
module Looksee
|
2
|
+
module Adapter
|
3
|
+
class Base
|
4
|
+
#
|
5
|
+
# Return the chain of classes and modules which comprise the
|
6
|
+
# object's method lookup path.
|
7
|
+
#
|
8
|
+
def lookup_modules(object)
|
9
|
+
modules = []
|
10
|
+
klass = internal_class(object)
|
11
|
+
while klass
|
12
|
+
modules << internal_class_to_module(klass)
|
13
|
+
klass = internal_superclass(klass)
|
14
|
+
end
|
15
|
+
modules
|
16
|
+
end
|
17
|
+
|
18
|
+
#
|
19
|
+
# Return a description of the given module.
|
20
|
+
#
|
21
|
+
# This is used for the module labels in the Inspector output.
|
22
|
+
#
|
23
|
+
def describe_module(mod)
|
24
|
+
num_brackets = 0
|
25
|
+
object = mod
|
26
|
+
while singleton_class?(object)
|
27
|
+
num_brackets += 1
|
28
|
+
object = singleton_instance(object)
|
29
|
+
end
|
30
|
+
|
31
|
+
if object.is_a?(Module)
|
32
|
+
description = module_name(object)
|
33
|
+
if description.empty?
|
34
|
+
description = "unnamed #{object.is_a?(Class) ? 'Class' : 'Module'}"
|
35
|
+
end
|
36
|
+
else
|
37
|
+
description = "#{module_name(object.class)} instance"
|
38
|
+
end
|
39
|
+
|
40
|
+
if num_brackets == 0
|
41
|
+
description
|
42
|
+
else
|
43
|
+
"#{'['*num_brackets}#{description}#{']'*num_brackets}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def internal_superclass(klass)
|
48
|
+
raise NotImplementedError, "abstract"
|
49
|
+
end
|
50
|
+
|
51
|
+
def internal_class(object)
|
52
|
+
raise NotImplementedError, "abstract"
|
53
|
+
end
|
54
|
+
|
55
|
+
def internal_class_to_module(internal_class)
|
56
|
+
raise NotImplementedError, "abstract"
|
57
|
+
end
|
58
|
+
|
59
|
+
def internal_public_instance_methods(mod)
|
60
|
+
raise NotImplementedError, "abstract"
|
61
|
+
end
|
62
|
+
|
63
|
+
def internal_protected_instance_methods(mod)
|
64
|
+
raise NotImplementedError, "abstract"
|
65
|
+
end
|
66
|
+
|
67
|
+
def internal_private_instance_methods(mod)
|
68
|
+
raise NotImplementedError, "abstract"
|
69
|
+
end
|
70
|
+
|
71
|
+
def internal_undefined_instance_methods(mod)
|
72
|
+
raise NotImplementedError, "abstract"
|
73
|
+
end
|
74
|
+
|
75
|
+
def singleton_class?(object)
|
76
|
+
raise NotImplementedError, "abstract"
|
77
|
+
end
|
78
|
+
|
79
|
+
def singleton_instance(singleton_class)
|
80
|
+
raise NotImplementedError, "abstract"
|
81
|
+
end
|
82
|
+
|
83
|
+
def module_name(mod)
|
84
|
+
raise NotImplementedError, "abstract"
|
85
|
+
end
|
86
|
+
|
87
|
+
if RUBY_VERSION >= '1.9.0' || Looksee.ruby_engine == 'rbx'
|
88
|
+
def source_location(method)
|
89
|
+
method.is_a?(UnboundMethod) or
|
90
|
+
raise TypeError, "expected UnboundMethod, got #{method.class}"
|
91
|
+
method.source_location
|
92
|
+
end
|
93
|
+
else
|
94
|
+
def source_location(method)
|
95
|
+
raise NotImplementedError, 'abstract'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'looksee/adapter/base'
|
2
|
+
require 'looksee/rbx'
|
3
|
+
|
4
|
+
module Looksee
|
5
|
+
module Adapter
|
6
|
+
class Rubinius < Base
|
7
|
+
def internal_superclass(klass)
|
8
|
+
klass.direct_superclass
|
9
|
+
end
|
10
|
+
|
11
|
+
def internal_class_to_module(internal_class)
|
12
|
+
if internal_class.is_a?(::Rubinius::IncludedModule)
|
13
|
+
internal_class.module
|
14
|
+
else
|
15
|
+
internal_class
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def internal_public_instance_methods(mod)
|
20
|
+
mod.method_table.public_names
|
21
|
+
end
|
22
|
+
|
23
|
+
def internal_protected_instance_methods(mod)
|
24
|
+
mod.method_table.protected_names
|
25
|
+
end
|
26
|
+
|
27
|
+
def internal_private_instance_methods(mod)
|
28
|
+
mod.method_table.private_names
|
29
|
+
end
|
30
|
+
|
31
|
+
def internal_undefined_instance_methods(mod)
|
32
|
+
names = []
|
33
|
+
mod.method_table.each_entry do |entry|
|
34
|
+
names << entry.name if entry.visibility.equal?(:undef)
|
35
|
+
end
|
36
|
+
names
|
37
|
+
end
|
38
|
+
|
39
|
+
def singleton_class?(object)
|
40
|
+
object.is_a?(Class) && object.__metaclass_object__
|
41
|
+
end
|
42
|
+
|
43
|
+
def singleton_instance(singleton_class)
|
44
|
+
singleton_class?(singleton_class) or
|
45
|
+
raise TypeError, "expected singleton class, got #{singleton_class.class}"
|
46
|
+
singleton_class.__metaclass_object__
|
47
|
+
end
|
48
|
+
|
49
|
+
def module_name(mod)
|
50
|
+
mod.is_a?(Module) or
|
51
|
+
raise TypeError, "expected module, got #{mod.class}"
|
52
|
+
mod.__name__
|
53
|
+
end
|
54
|
+
|
55
|
+
def source_location(method)
|
56
|
+
method.is_a?(UnboundMethod) or
|
57
|
+
raise TypeError, "expected UnboundMethod, got #{method.class}"
|
58
|
+
source_location = method.source_location and
|
59
|
+
return source_location
|
60
|
+
|
61
|
+
# #source_location doesn't always work. If it returns nil, try
|
62
|
+
# a little harder.
|
63
|
+
case (executable = method.executable)
|
64
|
+
when ::Rubinius::BlockEnvironment::AsMethod
|
65
|
+
method = executable.instance_variable_get(:@block_env).method
|
66
|
+
[method.file.to_s, method.lines[1]]
|
67
|
+
when ::Rubinius::DelegatedMethod
|
68
|
+
executable.instance_variable_get(:@receiver).source_location
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require "rbconfig"
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Looksee
|
6
|
+
autoload :VERSION, 'looksee/version'
|
7
|
+
autoload :Adapter, 'looksee/adapter'
|
8
|
+
autoload :Columnizer, 'looksee/columnizer'
|
9
|
+
autoload :Editor, 'looksee/editor'
|
10
|
+
autoload :Help, 'looksee/help'
|
11
|
+
autoload :Inspector, 'looksee/inspector'
|
12
|
+
autoload :LookupPath, 'looksee/lookup_path'
|
13
|
+
autoload :WirbleCompatibility, 'looksee/wirble_compatibility'
|
14
|
+
|
15
|
+
class << self
|
16
|
+
#
|
17
|
+
# The default options passed to #ls.
|
18
|
+
#
|
19
|
+
# Default: <tt>[:public, :protected, :private, :undefined,
|
20
|
+
# :overridden]</tt>
|
21
|
+
#
|
22
|
+
attr_accessor :default_specifiers
|
23
|
+
|
24
|
+
#
|
25
|
+
# The width to use for displaying output, when not available in
|
26
|
+
# the COLUMNS environment variable.
|
27
|
+
#
|
28
|
+
# Default: 80
|
29
|
+
#
|
30
|
+
attr_accessor :default_width
|
31
|
+
|
32
|
+
#
|
33
|
+
# The default styles to use for the +inspect+ strings.
|
34
|
+
#
|
35
|
+
# This is a hash with keys:
|
36
|
+
#
|
37
|
+
# * :module
|
38
|
+
# * :public
|
39
|
+
# * :protected
|
40
|
+
# * :private
|
41
|
+
# * :undefined
|
42
|
+
# * :overridden
|
43
|
+
#
|
44
|
+
# The values are format strings. They should all contain a single
|
45
|
+
# "%s", which is where the name is inserted.
|
46
|
+
#
|
47
|
+
# Default:
|
48
|
+
#
|
49
|
+
# {
|
50
|
+
# :module => "\e[1;37m%s\e[0m", # white
|
51
|
+
# :public => "\e[1;32m%s\e[0m", # green
|
52
|
+
# :protected => "\e[1;33m%s\e[0m", # yellow
|
53
|
+
# :private => "\e[1;31m%s\e[0m", # red
|
54
|
+
# :undefined => "\e[1;34m%s\e[0m", # blue
|
55
|
+
# :overridden => "\e[1;30m%s\e[0m", # black
|
56
|
+
# }
|
57
|
+
#
|
58
|
+
attr_accessor :styles
|
59
|
+
|
60
|
+
#
|
61
|
+
# The editor command, used for Object#edit.
|
62
|
+
#
|
63
|
+
# This string should contain a "%f", which is replaced with the
|
64
|
+
# file name, and/or "%l" which is replaced with the line number. A
|
65
|
+
# "%%" is replaced with "%".
|
66
|
+
#
|
67
|
+
# If the LOOKSEE_EDITOR environment variable is set, it is used as
|
68
|
+
# the default. Otherwise, we use the following heuristic:
|
69
|
+
#
|
70
|
+
# If EDITOR is set, we use that. If it looks like vi, emacs, or
|
71
|
+
# textmate, we also append options to position the cursor on the
|
72
|
+
# appropriate line. If EDITOR is not set, we use "vi +%l %f".
|
73
|
+
#
|
74
|
+
attr_accessor :editor
|
75
|
+
|
76
|
+
#
|
77
|
+
# The interpreter adapter.
|
78
|
+
#
|
79
|
+
# Encapsulates the interpreter-specific functionality.
|
80
|
+
#
|
81
|
+
attr_accessor :adapter
|
82
|
+
|
83
|
+
#
|
84
|
+
# Wrapper around RUBY_ENGINE that's always defined.
|
85
|
+
#
|
86
|
+
attr_accessor :ruby_engine
|
87
|
+
|
88
|
+
#
|
89
|
+
# Show a quick reference.
|
90
|
+
#
|
91
|
+
def help
|
92
|
+
Help.new
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
self.default_specifiers = [:public, :protected, :private, :undefined, :overridden]
|
97
|
+
self.default_width = 80
|
98
|
+
self.styles = {
|
99
|
+
:module => "\e[1;37m%s\e[0m", # white
|
100
|
+
:public => "\e[1;32m%s\e[0m", # green
|
101
|
+
:protected => "\e[1;33m%s\e[0m", # yellow
|
102
|
+
:private => "\e[1;31m%s\e[0m", # red
|
103
|
+
:undefined => "\e[1;34m%s\e[0m", # blue
|
104
|
+
:overridden => "\e[1;30m%s\e[0m", # black
|
105
|
+
}
|
106
|
+
self.editor = ENV['LOOKSEE_EDITOR'] || ENV['EDITOR'] || 'vi'
|
107
|
+
|
108
|
+
if Object.const_defined?(:RUBY_ENGINE)
|
109
|
+
self.ruby_engine = RUBY_ENGINE
|
110
|
+
else
|
111
|
+
self.ruby_engine = 'ruby'
|
112
|
+
end
|
113
|
+
|
114
|
+
case ruby_engine
|
115
|
+
when 'jruby'
|
116
|
+
self.adapter = Adapter::JRuby.new
|
117
|
+
when 'rbx'
|
118
|
+
self.adapter = Adapter::Rubinius.new
|
119
|
+
else
|
120
|
+
self.adapter = Adapter::MRI.new
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Looksee
|
2
|
+
module Columnizer
|
3
|
+
class << self
|
4
|
+
#
|
5
|
+
# Arrange the given strings in columns, restricted to the given
|
6
|
+
# width. Smart enough to ignore content in terminal control
|
7
|
+
# sequences.
|
8
|
+
#
|
9
|
+
def columnize(strings, width)
|
10
|
+
return '' if strings.empty?
|
11
|
+
|
12
|
+
num_columns = 1
|
13
|
+
layout = [strings]
|
14
|
+
loop do
|
15
|
+
break if layout.first.length <= 1
|
16
|
+
next_layout = layout_in_columns(strings, num_columns + 1)
|
17
|
+
break if layout_width(next_layout) > width
|
18
|
+
layout = next_layout
|
19
|
+
num_columns += 1
|
20
|
+
end
|
21
|
+
|
22
|
+
pad_strings(layout)
|
23
|
+
rectangularize_layout(layout)
|
24
|
+
layout.transpose.map do |row|
|
25
|
+
' ' + row.compact.join(' ')
|
26
|
+
end.join("\n") << "\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
private # -----------------------------------------------------
|
30
|
+
|
31
|
+
def layout_in_columns(strings, num_columns)
|
32
|
+
strings_per_column = (strings.length / num_columns.to_f).ceil
|
33
|
+
(0...num_columns).map{|i| strings[i*strings_per_column...(i+1)*strings_per_column] || []}
|
34
|
+
end
|
35
|
+
|
36
|
+
def layout_width(layout)
|
37
|
+
widths = layout_column_widths(layout)
|
38
|
+
widths.inject(0){|sum, w| sum + w} + 2*layout.length
|
39
|
+
end
|
40
|
+
|
41
|
+
def layout_column_widths(layout)
|
42
|
+
layout.map do |column|
|
43
|
+
column.map{|string| display_width(string)}.max || 0
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def display_width(string)
|
48
|
+
# remove terminal control sequences
|
49
|
+
string.gsub(/\e\[.*?m/, '').length
|
50
|
+
end
|
51
|
+
|
52
|
+
def pad_strings(layout)
|
53
|
+
widths = layout_column_widths(layout)
|
54
|
+
layout.each_with_index do |column, i|
|
55
|
+
column_width = widths[i]
|
56
|
+
column.each do |string|
|
57
|
+
padding = column_width - display_width(string)
|
58
|
+
string << ' '*padding
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def rectangularize_layout(layout)
|
64
|
+
return if layout.length == 1
|
65
|
+
height = layout[0].length
|
66
|
+
layout[1..-1].each do |column|
|
67
|
+
column.length == height or
|
68
|
+
column[height - 1] = nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Looksee
|
2
|
+
module ObjectMixin
|
3
|
+
#
|
4
|
+
# Return a Looksee::Inspector for this object.
|
5
|
+
#
|
6
|
+
# +args+ is an optional list of specifiers.
|
7
|
+
#
|
8
|
+
# * +:public+ - include public methods
|
9
|
+
# * +:protected+ - include public methods
|
10
|
+
# * +:private+ - include public methods
|
11
|
+
# * +:undefined+ - include public methods (see Module#undef_method)
|
12
|
+
# * +:overridden+ - include public methods
|
13
|
+
# * +:nopublic+ - include public methods
|
14
|
+
# * +:noprotected+ - include public methods
|
15
|
+
# * +:noprivate+ - include public methods
|
16
|
+
# * +:noundefined+ - include public methods (see Module#undef_method)
|
17
|
+
# * +:nooverridden+ - include public methods
|
18
|
+
# * a string - only include methods containing this string (may
|
19
|
+
# be used multiple times)
|
20
|
+
# * a regexp - only include methods matching this regexp (may
|
21
|
+
# be used multiple times)
|
22
|
+
#
|
23
|
+
# The default (if options is nil or omitted) is given by
|
24
|
+
# #default_lookup_path_options.
|
25
|
+
#
|
26
|
+
def ls(*args)
|
27
|
+
options = {:visibilities => Set[], :filters => Set[]}
|
28
|
+
(Looksee.default_specifiers + args).each do |arg|
|
29
|
+
case arg
|
30
|
+
when String, Regexp
|
31
|
+
options[:filters] << arg
|
32
|
+
when :public, :protected, :private, :undefined, :overridden
|
33
|
+
options[:visibilities].add(arg)
|
34
|
+
when :nopublic, :noprotected, :noprivate, :noundefined, :nooverridden
|
35
|
+
visibility = arg.to_s.sub(/\Ano/, '').to_sym
|
36
|
+
options[:visibilities].delete(visibility)
|
37
|
+
else
|
38
|
+
raise ArgumentError, "invalid specifier: #{arg.inspect}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
lookup_path = LookupPath.new(self)
|
42
|
+
Inspector.new(lookup_path, options)
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Open an editor at the named method's definition.
|
47
|
+
#
|
48
|
+
# Uses Looksee.editor to determine the editor command to run.
|
49
|
+
#
|
50
|
+
# Only works for methods for which file and line numbers are
|
51
|
+
# accessible.
|
52
|
+
#
|
53
|
+
def edit(name)
|
54
|
+
Editor.new(Looksee.editor).edit(self, name)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Object.send :include, ObjectMixin
|
59
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'shellwords'
|
2
|
+
|
3
|
+
module Looksee
|
4
|
+
class Editor
|
5
|
+
def initialize(command)
|
6
|
+
@command = command.dup
|
7
|
+
infer_arguments
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :command
|
11
|
+
|
12
|
+
#
|
13
|
+
# Run the editor command for the +method_name+ of +object+.
|
14
|
+
#
|
15
|
+
def edit(object, method_name)
|
16
|
+
method = LookupPath.new(object).find(method_name.to_s) or
|
17
|
+
return
|
18
|
+
file, line = Looksee.adapter.source_location(method)
|
19
|
+
run(file, line) unless line.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Run the editor command for the given file and line.
|
24
|
+
#
|
25
|
+
def run(file, line)
|
26
|
+
system *command_for(file, line)
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Return the editor command for the given file and line.
|
31
|
+
#
|
32
|
+
# This is an array of the command with its arguments.
|
33
|
+
#
|
34
|
+
def command_for(file, line)
|
35
|
+
line = line.to_s
|
36
|
+
words = Shellwords.shellwords(command)
|
37
|
+
words.map! do |word|
|
38
|
+
word.gsub!(/%f/, file)
|
39
|
+
word.gsub!(/%l/, line)
|
40
|
+
word.gsub!(/%%/, '%')
|
41
|
+
word
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def infer_arguments
|
48
|
+
return if command =~ /%[fl]/
|
49
|
+
|
50
|
+
case command[/\S+/]
|
51
|
+
when /\A(?:g?vim?|.*macs|pico|nano)\z/
|
52
|
+
command << " +%l %f"
|
53
|
+
when 'mate'
|
54
|
+
command << " -l%l %f"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|