rush, a shell that will yield to you
DESCRIPTION
Rush is a shell with ruby syntax and idioms. This presentation goes over how to use it and embed it in other applications.TRANSCRIPT
Nicholas Schlueter
rusha shell that will yield to you
http://flickr.com/photos/exquisitur/2551255999/
What is rush?
•Unix shell with ruby syntax and idioms
•by Adam Wiggins (Heroku)
Install and Run$ sudo gem install rush
$ rush
rush> home=> localhost:/Users/schlueter/
No Working Directory$ home
=> localhost:/Users/schlueter
$ root=> localhost:////
$ rushmate = home["mydev/github/rushmate/"]=> localhost:/Users/schlueter/mydev/github/rushmate/
But ls Still Works$ home["mydev/github/rushmate/"].ls
/Users/schlueter/mydev/github/rushmate/ coverage/ lib/ test/ History.txt MIT-LICENSE Manifest.txt
Make a Variable
$ rushmate = home["mydev/github/rushmate/"]
File Manipulation
http://flickr.com/photos/takashi/18862634/
Rename
# assign a file to a variable
$ file = rushmate['app/models/rushmate.rb']
$ file.rename 'russian_mate.rb'
Duplicate a File
$ file = rushmate['README']
$ file.duplicate 'README.markdown'
Copy Different Directory
$ file = rushmate['README']
$ file.copy_to other_project['README']
Move
$ file = rushmate['README']
$ file.move_to home['Desktop/']
Write a File
$ file = rushmate['README']
$ file.write "You Read Me"
Read a File
$ rushmate["README"].contents
You Read Me
File Globbing
Basic Globbing
$ rushmate["**/*.rb"].../mydev/github/rushmate/lib/rushmate.rb.../mydev/github/rushmate/lib/rushmate/command.rb.../mydev/github/rushmate/lib/rushmate/exit.rb...=> 9 x Rush::File
Glob into an Editor
$ rushmate["**/*.rb"].vi
$ rushmate["**/*.rb"].mate
Operate on Results
$ rails_proj['**/*.rhtml'].each { |f| f.rename f.name.gsub(/\.rhtml/, '.html.erb') }
Results Are an Array
$ rushmate["**/*.rb"].reject {|f| f.name.match(/test.rb/)}
Go Nuts!
$ rails_project["**/*.rhtml"] + rails_project["**/*.html.erb"]
embed
http://flickr.com/photos/liamngls/413522957/
Rush::EmbeddableShell.new.execute_in_shell do #anything in here delegates to rushend
Sake Quick Index of RDoc
task 'rdoc:local' => 'rush' do shell = Rush::EmbeddableShell.new shell.execute_in_shell do
endend
ruby = root["/Library/Ruby/Gems/1.8/"] indexes = ruby["doc/*/rdoc/index.html"] hrefs = indexes.collect { |f| path = f.full_path text = path.match(/doc\/(.*)\/rdoc/)[1] "<a href=\"#{path}\">#{text}</a>" } home["rdoc.html"].write hrefs.join("<br />") home.bash("open rdoc.html")
sake rdoc:local
Refactoring
http://flickr.com/photos/tonyjcase/2262229518/
Search$ work["**/*.rb"].search(/\bRushmate\b/)
.../test/user_input_test.rb => assert_equal("foo", Rushmate::.../lib/rushmate/command.rb => module Rushmate.../lib/rushmate/exit.rb => module Rushmate...7 matching files with 25 matching lines
$ work["**/*.rb"].search(/\bRushmate\b/).mate
and Replace$ rushmate["**/*.rb"].replace_contents!(/\bRushmate\b/, "RussianMate").../lib/rushmate.rb.../lib/rushmate/command.rb.../lib/rushmate/exit.rb=> 9 x Rush::File
Regex is your friend
$ project_files.replace_contents! (/User.authenticate\(\s*(.*),\s*(.*)\)/, 'User.authenticate(\\2, \\1)')
User.authenticate(user, password)User.authenticate(password, user)
Processes
$ ff = processes.filter(:cmdline => /firefox/).first
• ff.alive?
• ff.mem
• ff.pid
• ff.cpu
• ff.kill
Real World
Rush::EmbeddableShell.new.execute_in_shell do
end
ff_processes = processes.filter(:cmdline => /firefox/) if ff = ff_processes.select{|p| p.mem > 400000}.first ff_cmdline = ff.cmdline ff.kill home.bash ff_cmdline, :background => true end
Permissions$ file.access = {:user_can => :read_and_write, :group_and_other_can => :read }
$ file.access[:user_can_read]=> true
Use BASH if you must
$ rushmate.bash "rm -rf ."
# D'oh!
Shell Locally Act Globally
Remote$ remote = Rush::Box.new('[email protected]')
$ remote["/u/app/current/REVISION"].contents=> 160
Starts a Mongrel on Remote Server
Use in production with caution
Customize# setup variables to common directoriesrushmate = home["mydev/github/rushmate/"]
# setup variables to common serversqa = Rush::Box.new('[email protected]')
~/.rush/evn.rb
Cheap Backupdef cheap_backup(directory) unless directory.dir? puts "cheap backup only works on dirs" return end backup_path = directory.path + "/" + directory.name + ".bak" if self[backup_path].exists? puts "backup already exists" else directory.duplicate(directory.name + ".bak") endend
Extend
# allows you to run # directory.coveragedef coverage self.rake("coverage")end
~/.rush/commands.rb
Another Command
def ruby_files self["**/*.rb"]end
$ rushmate.ruby_files.../mydev/github/rushmate/lib/rushmate.rb.../mydev/github/rushmate/lib/rushmate/command.rb.../mydev/github/rushmate/lib/rushmate/exit.rb...=> 9 x Rush::File
TextMateRushmate::Command.new { # find ruby files with the current word in textmate found_files = project_directory["**/#{current_word.downcase}.rb"] if found_files.size == 1 found_files.mate else menu_files = found_files.collect { |f| f.full_path.gsub(project_directory.full_path, "") } project_directory[user_input.quick_menu_from_array(menu_files)].mate end}
The Take Away
Questions
?