Sunday Nov 23, 2008

Open simply whatever non-NetBeans Ruby (on Rails) project in NetBeans

Subtitle: Poor man's, but effective and simple solution

This is a tip (or trick) for how to quickly open any project (Rails or non-Rails one) without any NetBeans metadata in NetBeans. E.g. from RubyForge, Kenai, GitHub, ... or just your local one. In short, all you need is to run nb_ruby_project command (which is Ruby few-liner (excluding NetBeans metadata)) and press C-S-1 in NetBeans.

nb_ruby_project is downloadable/viewable on pastie or here.

You need just change the two lines in the script to point to your netbeans executable and optionally to your userdir if you are using non-default one (e.g. --userdir option during start-up).

NB_BIN = '/path/to/netbeans/bin/netbeans'
# NB_USER_DIR = '/path/to/optional/userdir'

You might also start-up NetBeans before using the script (but not necessary)

$ nb_ruby_project 
Usage: nb_ruby_project <ruby_project_dir> [--rails]

For example see the following two-step (checking out and opening in NetBeans) terminal session for how to open RubyGems project from RubyForge:

$ svn co svn://rubyforge.org/var/svn/rubygems/trunk rubygems
$ nb_ruby_project rubygems

Project: rubygems (non-Rails)

Will create following files (NetBeans metadata) in:
  /space/ruby/sources/rubygems/nbproject/project.xml
  /space/ruby/sources/rubygems/nbproject/project.properties

Press "y<Enter>" to agree: y
Mentioned NetBeans metadata created

Opening 'Rakefile' in NetBeans...

Now the project's Rakefile should be opened in the running NetBeans session (or new NetBeans instance is started). Just press there C-S-1 (Menu | Navigate | Select in Projects) and press <Enter> to confirm the dialog as shown on the image below.

Open RubyGems in NetBeans

After the project is opened you might want to set different Ruby platform, add more sources and/or roots, rename the project, etc.

This is just workaround for the issue 126410 which should enable to do this from NetBeans directly. But I'm using the script very often for RubyForge-alike sites in the meantime, so sharing.... It might be enhanced with bunch of small features, like asking for source roots, being Ruby-independent, etc. But it's just a temporary workaround... hopefully not for too long.

Note that you can open all the gems you have installed on your machine, see your $GEM_HOME/gems directory. You might also use the script from CLI to quickly open projects already containing NetBeans metadata (metadata creation will be just detected and skipped) during browsing your harddisk.

Tuesday Nov 11, 2008

Remote Debugging: explore Ruby code easily

In the NetBeans 7.0 (dev) you may attach debugger to any process which have been started from the command line, with all the goodies of UI debugger frontend. This means that if you just found some strange behaviour or bug in some CLI tool or you are just curious how e.g. gem list, rake -T, etc. commands work, just run then in debug mode from a terminal and attach to them from the frontend.
There is no need to setup a NetBeans project, even not to open the file or doing whatever in NetBeans, just invoking Menu | Debug | Attach action there.

Let's say we are curious how does gem list --local works.

  • you need to have have ruby-debug-ide in version 0.4.1 (just released) or later installed
  • Run rdebug-ide -p 7000 --stop -- `which gem` list --local. On Windows just replace `which gem` with the c:\\full\\path\\to\\the\\gem command
    (the --stop switch ensures that the debugger stops on the first line. This might not be always what you want if you've set the breakpoints in advance in the NetBeans frontend (e.g. after the first run with the --stop switch). Then just omit the switch and debugger will run until the first breakpoint is hit)
  • In NetBeans invoke Menu | Debug | Attach choose Ruby Debugger in the Debugger combobox if there is more choices (you have also e.g. Java support installed)

That's all. Debugger will stop on the first line of the debuggee. After few steps you are inside RubyGems guts peeking around for how does it actually work.

RubyGems debugging

This is the first step letting you to attach NetBeans debugger to the application run from CLI and/or on another machine. Next step is to provide functionality similar to ruby-debug that you will be able to put a call like:

  if something_peculiar_has_happened
    require 'ruby-debug-ide'
    debugger(7000) # 7000 being a port
  end

into your application and attach to it from the frontend.

Altough this is kind of "remote" debugging and you may attach to the process which was run on another machine, there are not yet sources association implemented in NetBeans. So you would have to have sources located on the same paths on the local machine as the one on the debuggee's machine. But for the case similar to the above which are probably the most frequent one this might be very usefull.

Worth to add that the support were added quite recently. I've also made the code base little bit more "aggressive" which should help to stabilize the debugger a bit more among the layers (from base backend up to the frontend) and prevent kind of random exception. So if you found any problems the feedback is more then welcomed. Either let me know here or through the mailing list or Issuezilla. Thanks

Tuesday Oct 21, 2008

Cross-language debugging: from Ruby to Java and back

Until we bring the full support for two ways debugging - from Ruby to Java and vice versa; the following "trick" might be used to debug Ruby and Java at once in the NetBeans 6.5 (you might get 6.5 build here). It might be used to debug standard JRuby applications/scripts, JRuby's Java extension or JRuby's internals itself. I'm using it for some time during development of JRuby Fast Debugger extension.

The trick is to start actually two debugging sessions, one for Ruby part and second for Java part (JVM under which JRuby runtime runs). Sessions then automatically activate themselves when the breakpoint for their language is hit.

Prerequisites

Except the Ruby IDE, we need to have Java support installed if it is not already the case. This can be find out by looking e.g. into the New Project Wizard. If the Java category is there, we have all we need. If not see the How do I install the Java support into the Ruby NetBeans IDE? FAQ.

So how to utilize it

  1. Open a (J)Ruby project utilizing some Java classes
  2. Go to its properties -> Run category and set JVM Arguments to -Xdebug -Xrunjdwp:transport=dt_socket,address=7000,server=y,suspend=y like on the screenshot (for Rails project the field has to be edited through properties file manually).

    JVM Arguments
  3. Then set the breakpoints in the Ruby code and Java code
  4. Start to debug the (J)Ruby project: Menu | Run | Debug Project
  5. Connect to the JRuby's JVM session: Menu | Debug | Attach Debugger, enter the port 7000, confirm the dialog. (Note that this need to be done within 15 seconds after the Ruby debugger was triggered (previous step). If that's not enough for you, you might increase the Ruby debugger timeout)

    Attach Debugger

That's it. As can be seen on the following screenshot, after I do a step in the Ruby code, Java debugging session take over the control and I'm debugging the Java code called from Ruby code with the full power of NetBeans Java debugger. Once I'm done with Java side I'll just press F5 (Continue) and Ruby debugging session takes back the control and I can continue with the debugging of Ruby part.
Note that if you have JRuby sources you might just set the breakpoint somewhere in the JRuby interpreter's guts and take a look what going around in there.

Debugging

Clearly not fully-fledged cross-language debugging. Since sessions live their life independently, actions like Step Into, Step Over and similar do not work in the cross-language context. We have to simulate Step Into and similar actions by putting breakpoints on appropriate places. Stacktrace is not shared, so we get two, one for each language, instead of one with nicely mixed frames from both languages. But still, I find it pretty handy during JRuby Fast Debugger development.
If you do not want to repeatedly delete and add the long string from the step 2, you might create a configuration as might be seen in the properties screenshot (JRuby Debug in Configuration combobox).

To watch the progress on fully-fledge cross-language debugging, you might CC yourself to this RFE in the Issuezilla.

Monday Jul 07, 2008

Rake Task Runner

Executing Rake tasks in the NetBeans 6.1 is little bit cumbersome and inconvenient. To run a single Rake task you have to invoke project's context menu, navigate to the desired task, usually with the sluggish help of mouse. Clearly, the same for debugging a Rake task. If you have made a change to the Rakefile you have to manually trigger the Refresh List action, again the same long way through the context menu.

Old, 6.1 way:
6.1.png

Working on the debug-commons project I often ended up in the command line which was kind of bad feeling when working on NetBeans Ruby IDE ;)

This has changed in NetBeans 6.5 with new Rake Task Runner and few related changes. Now running/debugging a Rake task is quicker then using the command line.

  • CLI: rake test<Enter>
  • NetBeans: <Alt+Shift-R>te<Enter>

Few key strokes saved in NetBeans ;) Moreover you will get another bunch of features in Rake Task Runner.

New 6.5 Rake Runner:
6.5.png

It might be easily invoked through Alt+Shift-R (or through the project context menu if you really prefer the mouse way). Then just type few (not necessarily first) letters of the task to be run and press <Enter> like you are used to from Go To File or Go To Type dialogs.

To run the same task again just press Alt+Shift-R, <Enter>. The lastly run task is remembered. Or you might use Rerun button in the Output Window's tab.

Other features, new in 6.5:

  • possibility to pass parameters to Rake tasks (e.g. to db:migrate or test tasks)
  • possibility to see undocumented task (rake tool by default does not show tasks without description)
  • automatic detection of changes in the Rakefile
  • full description of each Rake task
  • merge of Debug and Run task context menu (just check the checkbox to debug the task)
  • better diagnostic when something goes wrong

Another related change is pre-generated useful Rakefile for newly created Ruby project. In 6.1, when you created a new project, you got an empty Rakefile. In 6.5 you will get Rakefile template containing classic tasks like clean, gem, rdoc, test, etc. (thank to Dudley Flanders for suggestions).

Also few menu items among the IDE are tied up with the pre-generated Rakefile, like Build and Clean actions in project's context menu which did nothing in 6.1.

Thanks to Erno, his Test Runner cooperates with the Rake Runner as well. So when you trigger tasks like test or spec, Test Runner will jump in and shows test result in a nice UI manner.

There are still a lot of place for improvements. If you have more ideas which you would like to see in NetBeans let us know. We have only a few days until Feature Freeze, so sooner is better. To try the new features you need to get 6.5 build as described in the wiki. As with all dev builds there might be some not-yet-discovered bugs, so better to keep one dev build, which works for you, back. I'm using 6.5 for my daily Ruby and Java job without too much issues. So encouraging you to try it as well ;). Moreover with 6.5 dev builds we might come with a fix to a bug you find in hours when at least somehow possible. That's much harder with already released 6.1.

Wednesday May 07, 2008

Scripting NetBeans in Ruby

Few times we were asked whether is is possible to write NetBeans Ruby IDE extensions in Ruby. We usually replied not yet. But having:

  • NetBeans running on the JVM
  • JRuby on the same VM
  • JSR 223 which is part of JDK 6

there are no reasons why it should not be possible now.

So I've started to peek around what would be needed to provide convenient extension with which the Rubyists would be able to start to tweak NetBeans IDE in Ruby language only. I did not start exactly with such support, but instead started with kind of NetBeans Ruby IDE scripting support. I've recalled Jesse's idea for IDE scripted by JavaScript and applied similar to Ruby.

Working with NetBeans Ruby's dev builds and very often starting with clear userdir and still reopening my projects, I now have the following script instead which I simply run from CLI after fresh NetBeans starts up (just work from IRB as well):

  1 require 'nb_ext'
  2 netbeans = NBExt.find_first
  3 netbeans.attach
  4 netbeans.open_projects(
  5   '/space/java/netbeans-hg/main/ruby.debugger',
  6   '/space/java/netbeans-hg/main/ruby.platform',
  7   '/space/java/netbeans-hg/main/ruby.project'
  8 )

How does it work?

Below are some details of implementation with inlined snippets of code for convenience. Full code might be downloaded here, Java agent here.

(2) The script finds running NetBeans instance. The find_first methods goes through the currently running JVM instances and greps for the NetBeans and returns the first one (or nil). Thus if you are running more NetBeans instances use find_by_userdir or find_all instead.

  1 vm_desc = VirtualMachine.list.detect do |desc|
  2   desc.display_name =~ /org.netbeans.Main/i
  3 end

(3) attach to it via Attach API

  1 VirtualMachine.attach(@vm_desc)t

(4) and opens given project(s) in the running NetBeans IDE. open_projects method just compose projects to be opened with the code utilizing NetBeans APIs (open_projects_code.rb) and sends it to the agent, running inside NetBeans process VM, for evaluation.

   1 def open_projects(\*projects)
   2   code = "projects = ['#{projects.join("','")}']\\n"
   3   code_file = File.join('code', 'open_projects_code.rb')
   4   code << File.read(code_file)
   5   eval_code(code)
   6 end
   7 
   8 def eval_code(code)
   9   output = Tempfile.new('output')
  10   @vm.load_agent(@agent_jar, "#{output.path}#{File::PATH_SEPARATOR}#{code}")
  11   File.read(output.path)
  12 end

Template for opening projects is simple:

   1 include Java
   2 
   3 import 'java.net.URI'
   4 import 'org.netbeans.api.project.FileOwnerQuery'
   5 import 'org.netbeans.api.project.ui.OpenProjects'
   6 
   7 raise("projects must be defined") unless defined?(projects)
   8 
   9 to_open = projects.map do |prj|
  10   uri = URI.new("file://#{prj}")
  11   FileOwnerQuery.get_owner(uri)
  12 end.compact
  13 
  14 to_open_p = to_open.to_java('org.netbeans.api.project.Project')
  15 OpenProjects.getDefault().open(to_open_p, false)

Note that projects variable is defined in the open_projects method code composition. Likely templating mechanism would fit here.

Everything written in the Ruby language, just agent class is written in Java (with future JRuby compiler even this piece could be written in Ruby).

Just a playground so far…

This is really just an example how it might be done. Developing such extensions, or writing such scripts, is still little awkward and not that easy to test and one needs to know NetBeans APIs, but that's likely OK when wanting to write NetBeans extensions/scripts.
In the future we could bridge some basic NetBeans APIs to Ruby, like the artificial open_projects method above, to make it easy to write such scripts which adds e.g. new menu items. Also it should not be hard to write some support into NetBeans where you would manage your scripts and which will be automatically loaded when NetBeans starts up. Ideally there would be also some support for testing such script -> write in IDE, run/test it in IDE. Not that simple, but something like this.

It depends whether there is really such a request from NetBeans Ruby users and whether the effort spends on the support does worth it, whether the NetBeans users would like to script or extends NetBeans in Ruby and what would be such use-cases.

If you have any ideas how such support should look like or how does it look in other IDEs, Editors supporting Ruby extensions, let me know.

Can I try it?

Yes, you can. But it might not be that easy at the moment since we are facing issue with bundled tweaked JRuby. So firstly you might try to download and install this NetBeans module (4384kB!, contains jruby.jar) which should enable JRuby scripting in Netbeans. I've spent some time with this but still does not work. On the other hand my colleague Erno, does not have problems I'm encountering. So your mileage may vary.
If it throws strange JRuby internal exceptions, use second brute-force method, and just copy-paste jruby.jar from your JRuby distribution (lib/jruby.jar) and jruby-engine jar to your $JAVA_HOME/jre/lib/ext directory. Then start the NetBeans IDE and above should work. You will get some exceptions from our NetBeans Ruby lexer/parser if you used brute-force method, but for playing should be enough until we solve the issue appropriately.

About

Martin Krauskopf

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today