drx 0.0.1 → 0.0.2
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/ext/drx_ext.c +102 -5
- data/lib/drx_test.rb +1 -2
- data/lib/drxtk.rb +101 -17
- metadata +2 -2
data/ext/drx_ext.c
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
#include "ruby.h"
|
2
2
|
#include "st.h"
|
3
3
|
|
4
|
+
/**
|
5
|
+
* Gets the Ruby's engine type of a variable.
|
6
|
+
*/
|
7
|
+
static VALUE t_get_type(VALUE self, VALUE obj)
|
8
|
+
{
|
9
|
+
return INT2NUM(TYPE(obj));
|
10
|
+
}
|
11
|
+
|
4
12
|
// Helper for t_get_iv_tbl().
|
5
13
|
int record_var(st_data_t key, st_data_t value, VALUE hash) {
|
6
14
|
// I originally did the following, but it breaks for object::Tk*. Perhaps these
|
@@ -78,7 +86,7 @@ static VALUE t_get_flags(VALUE self, VALUE obj)
|
|
78
86
|
|
79
87
|
// Helper for t_get_m_tbl().
|
80
88
|
int record_method(st_data_t key, st_data_t value, VALUE hash) {
|
81
|
-
// @todo: Store something useful in the values
|
89
|
+
// @todo: Store something useful in the values?
|
82
90
|
rb_hash_aset(hash, key == ID_ALLOCATOR ? rb_str_new2("<Allocator>") : ID2SYM(key), INT2FIX(666));
|
83
91
|
return ST_CONTINUE;
|
84
92
|
}
|
@@ -110,14 +118,102 @@ static VALUE t_get_address(VALUE self, VALUE obj)
|
|
110
118
|
return INT2NUM(obj);
|
111
119
|
}
|
112
120
|
|
113
|
-
|
114
|
-
|
121
|
+
// {{{ Locating methods
|
122
|
+
|
123
|
+
#include "node.h"
|
124
|
+
|
125
|
+
#define RSTR(s) rb_str_new2(s)
|
126
|
+
|
127
|
+
static t_do_locate_method(NODE *ND_method) {
|
128
|
+
NODE *ND_scope = NULL, *ND_block = NULL;
|
129
|
+
VALUE place;
|
130
|
+
char line_s[20];
|
131
|
+
|
132
|
+
//
|
133
|
+
// The NODE_METHOD node
|
134
|
+
//
|
135
|
+
|
136
|
+
if (nd_type(ND_method) != NODE_METHOD/*0*/) {
|
137
|
+
return RSTR("I'm expecting a NODE_METHOD here...");
|
138
|
+
}
|
139
|
+
|
140
|
+
//
|
141
|
+
// The NODE_SCOPE node
|
142
|
+
//
|
143
|
+
|
144
|
+
ND_scope = ND_method->u2.node;
|
145
|
+
|
146
|
+
if (nd_type(ND_scope) == NODE_CFUNC/*2*/) {
|
147
|
+
return RSTR("That's a C function");
|
148
|
+
}
|
149
|
+
|
150
|
+
if (nd_type(ND_scope) == NODE_ATTRSET/*89*/) {
|
151
|
+
return RSTR("That's an attr setter");
|
152
|
+
}
|
153
|
+
|
154
|
+
if (nd_type(ND_scope) == NODE_FBODY/*1*/) {
|
155
|
+
return RSTR("That's an alias");
|
156
|
+
}
|
157
|
+
|
158
|
+
if (nd_type(ND_scope) == NODE_ZSUPER/*41*/) {
|
159
|
+
// @todo The DateTime clas has a lot of these.
|
160
|
+
return RSTR("That's a ZSUPER, whatver the heck it means!");
|
161
|
+
}
|
162
|
+
|
163
|
+
if (nd_type(ND_scope) != NODE_SCOPE/*3*/) {
|
164
|
+
printf("I'm expecting a NODE_SCOPE HERE (got %d instead)\n", nd_type(ND_scope));
|
165
|
+
return RSTR("I'm expecting a NODE_SCOPE HERE...");
|
166
|
+
}
|
167
|
+
|
168
|
+
//
|
169
|
+
// The NODE_BLOCK node
|
170
|
+
//
|
171
|
+
|
172
|
+
ND_block = ND_scope->u3.node;
|
173
|
+
|
174
|
+
if (nd_type(ND_block) != NODE_BLOCK/*4*/) {
|
175
|
+
return RSTR("I'm expecting a NODE_BLOCK here...");
|
176
|
+
}
|
177
|
+
|
178
|
+
sprintf(line_s, "%d:", nd_line(ND_block));
|
179
|
+
place = RSTR(line_s);
|
180
|
+
rb_str_cat2(place, ND_block->nd_file);
|
181
|
+
|
182
|
+
return place;
|
183
|
+
}
|
184
|
+
|
185
|
+
/*
|
186
|
+
* call-seq:
|
187
|
+
* Drx.locate_method(Date, "to_s") => str
|
188
|
+
*
|
189
|
+
* Locates the filename and line-number where a method was defined. Returns a
|
190
|
+
* string of the form "89:/path/to/file.rb", or nil if method doens't exist.
|
191
|
+
* If the method exist but isn't a Ruby method (i.e., if it's written in C),
|
192
|
+
* the string returned will include an erorr message, e.g. "That's a C
|
193
|
+
* function".
|
115
194
|
*/
|
116
|
-
static VALUE
|
195
|
+
static VALUE t_locate_method(VALUE self, VALUE obj, VALUE method_name)
|
117
196
|
{
|
118
|
-
|
197
|
+
const char *c_name;
|
198
|
+
NODE *method_node;
|
199
|
+
|
200
|
+
if (TYPE(obj) != T_CLASS && TYPE(obj) != T_ICLASS && TYPE(obj) != T_MODULE) {
|
201
|
+
rb_raise(rb_eTypeError, "Only T_CLASS/T_MODULE is expected as the argument (got %d)", TYPE(obj));
|
202
|
+
}
|
203
|
+
if (!RCLASS(obj)->m_tbl) {
|
204
|
+
return Qnil;
|
205
|
+
}
|
206
|
+
c_name = StringValuePtr(method_name);
|
207
|
+
ID id = rb_intern(c_name);
|
208
|
+
if (st_lookup(RCLASS(obj)->m_tbl, id, &method_node)) {
|
209
|
+
return t_do_locate_method(method_node);
|
210
|
+
} else {
|
211
|
+
return Qnil;
|
212
|
+
}
|
119
213
|
}
|
120
214
|
|
215
|
+
// }}}
|
216
|
+
|
121
217
|
VALUE mDrx;
|
122
218
|
|
123
219
|
void Init_drx_ext() {
|
@@ -130,6 +226,7 @@ void Init_drx_ext() {
|
|
130
226
|
rb_define_module_function(mDrx, "get_address", t_get_address, 1);
|
131
227
|
rb_define_module_function(mDrx, "get_type", t_get_type, 1);
|
132
228
|
rb_define_module_function(mDrx, "get_ivar", t_get_ivar, 2);
|
229
|
+
rb_define_module_function(mDrx, "locate_method", t_locate_method, 2);
|
133
230
|
rb_define_const(mDrx, "FL_SINGLETON", INT2FIX(FL_SINGLETON));
|
134
231
|
rb_define_const(mDrx, "T_OBJECT", INT2FIX(T_OBJECT));
|
135
232
|
rb_define_const(mDrx, "T_CLASS", INT2FIX(T_CLASS));
|
data/lib/drx_test.rb
CHANGED
data/lib/drxtk.rb
CHANGED
@@ -4,7 +4,7 @@ require 'tk'
|
|
4
4
|
module Drx
|
5
5
|
def self.examinetk(obj)
|
6
6
|
app = Drx::TkGUI::DrxWindow.new
|
7
|
-
app.
|
7
|
+
app.see(obj)
|
8
8
|
app.run
|
9
9
|
end
|
10
10
|
|
@@ -16,6 +16,9 @@ end
|
|
16
16
|
|
17
17
|
module Drx
|
18
18
|
module TkGUI
|
19
|
+
|
20
|
+
# The 'DRX_EDITOR_COMMAND' environment variable overrides this.
|
21
|
+
EDITOR_COMMAND = 'gedit +%d "%s"'
|
19
22
|
|
20
23
|
class ScrolledListbox < TkFrame
|
21
24
|
def initialize(*args, &block)
|
@@ -53,20 +56,26 @@ module Drx
|
|
53
56
|
|
54
57
|
class DrxWindow
|
55
58
|
def initialize
|
59
|
+
@stack = []
|
56
60
|
root = TkRoot.new
|
61
|
+
@evalbox = TkEntry.new(root) {
|
62
|
+
font 'Courier'
|
63
|
+
pack(:side => 'bottom', :fill => 'both')
|
64
|
+
}
|
65
|
+
TkLabel.new(root, :anchor => 'w') {
|
66
|
+
text 'Type some code to eval in the context of the selected object; prepend with "see" to examine it.'
|
67
|
+
pack(:side => 'bottom', :fill => 'both')
|
68
|
+
}
|
57
69
|
@list = (ScrolledListbox.new(root) {
|
58
|
-
#pack :side => 'left', :fill => 'y'
|
59
70
|
pack :side => 'left', :fill => 'both', :expand => true
|
60
71
|
}).the_list
|
61
72
|
@list.width 52
|
62
73
|
@list.height 25
|
63
74
|
@list.focus
|
64
75
|
@varsbox = (ScrolledListbox.new(root) {
|
65
|
-
#pack :side => 'left', :fill => 'y'
|
66
76
|
pack :side => 'left', :fill => 'both', :expand => true
|
67
77
|
}).the_list
|
68
78
|
@methodsbox = (ScrolledListbox.new(root) {
|
69
|
-
#pack :side => 'left', :fill => 'y'
|
70
79
|
pack :side => 'left', :fill => 'both', :expand => true
|
71
80
|
}).the_list
|
72
81
|
|
@@ -75,15 +84,75 @@ module Drx
|
|
75
84
|
display_variables(current_object)
|
76
85
|
display_methods(current_object)
|
77
86
|
}
|
87
|
+
@list.bind('ButtonRelease-3') {
|
88
|
+
back
|
89
|
+
}
|
90
|
+
@list.bind('Double-Button-1') {
|
91
|
+
descend_iclass
|
92
|
+
}
|
78
93
|
@varsbox.bind('<ListboxSelect>') {
|
79
|
-
|
94
|
+
print "\n== Variable #{@varsbox.get_selection}\n\n"
|
95
|
+
p selected_var
|
96
|
+
}
|
97
|
+
@varsbox.bind('Double-Button-1') {
|
98
|
+
see selected_var
|
99
|
+
}
|
100
|
+
@varsbox.bind('ButtonRelease-3') {
|
101
|
+
require 'pp'
|
102
|
+
print "\n== Variable #{@varsbox.get_selection}\n\n"
|
103
|
+
pp selected_var
|
104
|
+
}
|
105
|
+
@evalbox.bind('Key-Return') {
|
106
|
+
eval_code
|
107
|
+
}
|
108
|
+
@methodsbox.bind('Double-Button-1') {
|
109
|
+
locate_method(current_object, @methodsbox.get_selection)
|
80
110
|
}
|
81
111
|
end
|
82
112
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
113
|
+
def open_up_editor(filename, lineno)
|
114
|
+
command = sprintf(ENV['DRX_EDITOR_COMMAND'] || EDITOR_COMMAND, lineno, filename)
|
115
|
+
puts "Execting: #{command}..."
|
116
|
+
if !fork
|
117
|
+
if !Kernel.system(command)
|
118
|
+
puts "Could not execure the command '#{command}'"
|
119
|
+
end
|
120
|
+
exit!
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def locate_method(obj, method_name)
|
125
|
+
place = Drx.locate_method(obj, method_name)
|
126
|
+
if !place
|
127
|
+
puts "Method #{method_name} doesn't exist"
|
128
|
+
else
|
129
|
+
if place =~ /\A(\d+):(.*)/
|
130
|
+
open_up_editor($2, $1)
|
131
|
+
else
|
132
|
+
puts "Can't locate method, because: #{place}"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def back
|
138
|
+
if @stack.size > 1
|
139
|
+
@stack.pop
|
140
|
+
see @stack.pop
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def selected_var
|
145
|
+
Drx.get_ivar(current_object, @varsbox.get_selection)
|
146
|
+
end
|
147
|
+
|
148
|
+
def eval_code
|
149
|
+
code = @evalbox.get.strip
|
150
|
+
see = !!code.sub!(/^see\s/, '')
|
151
|
+
result = current_object.instance_eval(code)
|
152
|
+
p result
|
153
|
+
see(result) if see
|
154
|
+
end
|
155
|
+
|
87
156
|
def current_object
|
88
157
|
@current_object
|
89
158
|
end
|
@@ -92,15 +161,12 @@ module Drx
|
|
92
161
|
@varsbox.delete('0', 'end')
|
93
162
|
if (Drx.has_iv_tbl(obj))
|
94
163
|
vars = Drx.get_iv_tbl(obj).keys.map do |v| v.to_s end.sort
|
164
|
+
# Get rid of gazillions of Tk classes:
|
165
|
+
vars = vars.reject { |v| v =~ /Tk|Ttk/ }
|
95
166
|
@varsbox.insert('end', *vars)
|
96
167
|
end
|
97
168
|
end
|
98
169
|
|
99
|
-
def inspect_variable(obj, var_name)
|
100
|
-
print "\n== Variable #{var_name}\n\n"
|
101
|
-
p Drx.get_ivar(obj, var_name)
|
102
|
-
end
|
103
|
-
|
104
170
|
def display_methods(obj)
|
105
171
|
@methodsbox.delete('0', 'end')
|
106
172
|
if (Drx.is_class_like(obj))
|
@@ -109,14 +175,32 @@ module Drx
|
|
109
175
|
end
|
110
176
|
end
|
111
177
|
|
112
|
-
def
|
178
|
+
def display_hierarchy(obj)
|
179
|
+
@list.delete('0', 'end')
|
113
180
|
@objs = []
|
114
|
-
Drx.examine(
|
181
|
+
Drx.examine(obj) do |line, o|
|
115
182
|
@list.insert('end', line)
|
116
|
-
@objs <<
|
183
|
+
@objs << o
|
117
184
|
end
|
118
185
|
end
|
119
186
|
|
187
|
+
def see(obj)
|
188
|
+
@current_object = obj
|
189
|
+
@stack << obj
|
190
|
+
display_hierarchy(obj)
|
191
|
+
display_variables(obj)
|
192
|
+
display_methods(obj)
|
193
|
+
end
|
194
|
+
|
195
|
+
def descend_iclass
|
196
|
+
obj = if Drx.get_type(current_object) == Drx::T_ICLASS
|
197
|
+
Drx.get_klass(current_object)
|
198
|
+
else
|
199
|
+
current_object
|
200
|
+
end
|
201
|
+
see(obj)
|
202
|
+
end
|
203
|
+
|
120
204
|
def run
|
121
205
|
Tk.mainloop
|
122
206
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: drx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mooffie
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-02-
|
12
|
+
date: 2009-02-04 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|