drx 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/ext/drx_ext.c +102 -5
  2. data/lib/drx_test.rb +1 -2
  3. data/lib/drxtk.rb +101 -17
  4. 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
- * Gets the Ruby's engine type of a variable.
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 t_get_type(VALUE self, VALUE obj)
195
+ static VALUE t_locate_method(VALUE self, VALUE obj, VALUE method_name)
117
196
  {
118
- return INT2NUM(TYPE(obj));
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
@@ -1,3 +1,4 @@
1
+ require 'rubygems'
1
2
  require 'drxtk'
2
3
 
3
4
  require 'date'
@@ -20,6 +21,4 @@ Drx.examine(zmn)
20
21
  #############################
21
22
 
22
23
  Drx.examinetk(zmn)
23
-
24
- #Drx.examinetk(zmn)
25
24
  #Drx.examinetk("some_string")
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.display_value(obj)
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
- inspect_variable(current_object, @varsbox.get_selection)
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
- # def current_object=(obj)
84
- # @current_object = obj
85
- # end
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 display_value(value)
178
+ def display_hierarchy(obj)
179
+ @list.delete('0', 'end')
113
180
  @objs = []
114
- Drx.examine(value) do |line, obj|
181
+ Drx.examine(obj) do |line, o|
115
182
  @list.insert('end', line)
116
- @objs << obj
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.1
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-03 00:00:00 +02:00
12
+ date: 2009-02-04 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies: []
15
15