Using the shell within irb
Wednesday, July 12, 2006 at 12:50PM So, how do you use it? From the irb shell:
irb(main):003:0> shell.echo 'hello world'
=> hello world
Or, something more useful which will return you an array of files you've modified since your last commit to subversion:
irb(main):016:0> shell.svn(:stat).grep(/^M/).collect do |line|
irb(main):017:1* line.gsub(/^M */, '').chomp
irb(main):018:1> end
=> ["app/helpers/application_helper.rb",
"app/controllers/application.rb",
"config/photography_config.rb",
"public/javascripts/lightbox.js",
"public/stylesheets/lightbox.css"]
Oh, and since all the shell commands in your path are now effectively methods, if you have readline and completion switched on, you can do what you'd usually do in the shell:
irb(main):019:0> shell.sv[tab][tab]
shell.svk shell.svnadmin shell.svnserve
shell.svm shell.svndiffshim_py shell.svnversion
shell.svn shell.svndumpfilter
shell.svn_backup_sh shell.svnlook
irb(main):019:0> shell.sv
I've made a few modifications to the default behaviour of the `shell` widget in Ruby core. I'm installing the commands with no prefix, so that it's easier to use. By default, however, that would override the implementation of a function with the latest one found. The default behaviour of the shell is to use the *first* match, so I've fiddled things so that it also uses the first match. This has the added benefit that it doesn't override `Shell`'s internal implemtation of things like `pwd` which otherwise causes the thing to completely break (since it's also *used* internally). That's what `FixAddDelegateCommandToShell` does, for those of you playing along at home.
I've also allowed you to specify arguments to system commands as symbols. It feels more natural to me to type `shell.svn :stat` than `shell.svn 'stat'`. I guess YMMV.
Lastly, it's all wrapped up in a singleton widget which lazily loads the shell functionality. That makes it available any time, but pushes the time hit (where it scans `$PATH` and creates all those methods for each command) to the first use, rather than when you launch `irb`.
So there you go. I've found it useful, so I thought I'd share.
Reader Comments (7)
IRB FTW!
Haha, this makes the complete transition to ruby a breezer :P
I got this error message
NoMethodError: undefined method `install_system_commands' for Shell:Class
I just used the posted code from shell_from_irb.rb
Ok, got it.
require 'shell'
Andy: Ah, oops, I forgot to include that bit (I've got
require 'shell'way further up my~/.irbrc). I've fixed the copy here now, too. Thanks!Apart from tab completion, I can't see what this does that you can't do with backticks?
Take your example with modified svn files. This does the same thing:
`svn stat`.grep(/^M/) { |x| x.sub(/^M */, '').chomp }you could simply use ^Z to pause the job and use the shell then getting back to it with %n
Per, Dam: Picky, picky. My solution is sooo much prettier. :-)