Rush: the ruby shell
rush.heroku.com
rush.heroku.com
https://github.com/Spakman/urchin/
I really like a lot about existing shells like Bash and Zsh, so it operates much like a standard shell - pipelines, job control, redirections, tilde expansion, aliasing, globbing, etc.
However, actual shell scripting feels really grim, so sometime in the near future (hopefully) it will be able to pipe into Ruby when needed. This will let you write Ruby directly on the command line, without escaping quotes and such and should make loops and custom shell functions much more fun for a Ruby programmer.
I also fancy experimenting with some things I've not seen in other shells - fuzzy filepath completion, per-project history, etc.
Any ideas are welcome!
Not sure if this exists in Bash at the moment in the various/terminals and consoles but a searchable history of the commands I've run would be handy. Also, some easy way to get command history in segments (maybe allowing me to comment my command history and pull everything from one comment marker to the next) so I can make a repeatable shell script out of the correct set of commands once I get the commands right.
As another idea to play with, if there is a way (probably using github) to index shell recipes others have made and look them up on the command line, that could be fun. So I could do "urchin search 'postgres 9 snow leopard' and grab someone else's command recipe to build postgres if one is out there.
I'd definitely like some clever types of history management. I've not looked too closely at those facilities in other shells (I would guess some of them have some cool ideas), but it sounds like we can certainly come up with some more!
I'm going to quickly lose track of this thread if I'm not careful. Do you use GitHub? Can you contact me there so we can stay in touch more easily, please?
I will definitely be trying out your shell. If you're curious about mine (feel free to steal code, no promises that everything works as committed): https://github.com/afiler/crush
I was having similar thoughts about entering Ruby 'mode' (for want of a better term) with special characters. I'll be checking out your work soon.
All of these things make for some exciting stuff - I didn't realise others might be excited about them too!
Certain things are definitely annoying to do with just the standard set of UNIX tools, but not knowing them well certainly won't help.
myproj['**/*.rb'].search(/^\s*class/).lines.size
And they say perl looks like line noise. The ratio of ispunct to isalpha in that line is 2:3."grep -c" is great if you know it. The problem is it's a trick which only works for grep, and learning and keeping track of all of these tricks for every tool you use is a real pain. Never mind that "grep -c" will never be as flexible as wc.
It's more reliable to follow the Unix philosophy:
Write programs that do one thing and do it well. Write programs to work together.
This is a tough criticism, since "wc -l" is great if you know it too. And that, in the rush version, you need to use .lines on the result of .search() in order to get something you can call .size on to get the exact result you want (because it seems you can't just call .size on the result of .search(), I suspect that would just return a count of files where the string appears at least once).
In that vein, with a pipeline, you can look at each bit independently and reason about it. You can't reason about what .size returns (lines or bytes or whatever) without looking at what is immediately to the left of it (and then you have to know that .lines returns an array and that .size is returning the length of that array). And you have to know that whatever .lines returns actually has a .size method. wc -l always counts lines, no matter what its context is, because it's only ever dealing with text based input, never more complexly structured data like objects or arrays. This may or may not be what you want, but it does lend itself to wider (re)usability.
Here is how you go about it, for those interested:
http://ipython.scipy.org/doc/stable/html/interactive/shell.h... http://magazine.redhat.com/2008/02/07/python-for-bash-script...
Seems like, Rush is the ruby counterpart of what IPython is in python.
Conceptually, I like Python much more than shell script, but it seems I end up having to type and think more when simply using it as a shell.
When I get to the point where I actually need a real programming language such as Python to express what I want to do, I generally make a script and don't type it in the shell.
I know there was a RubyOS once, where they were trying to use Ruby in place of the shell.
The ability to easily execute commands on several remote servers is really appealing. At work, I only need to be able to ssh to 5 different servers and I frequently don't have a free screen terminal.
I'm no sysadmin, but I think you're doing it right as is. Scripting languages and DSLs like Chef are designed to be a better solution for those problems than shell scripts.
It's kind of funny, in a way. Perl was originally a scripting language for sysadmin tasks designed to replace shell scripts, that matured into a programming language, that influenced the Ruby programming language, from which we have a Ruby shell in which, presumably, we can write shell scripts again.
http://weblog.jamisbuck.org/2006/9/21/introducing-the-capist...
Firstly, this will never have the adoption of bash, sit down on any Linux and you will be familiar. If you get used to shell and a normal human being which will have some delay context switching it will be a performance hit (same argument I'm sticking with qwerty for now)
Secondly, bash uses a domain specific language to tangle your fillesystem, simple things are simple, and unfortunately harder things Gerald blinked in the process. This comes with the overhead of learning some unintuitive things about ruby (blocks anyone?).
> bash and ssh, we love you, but your era is past.
I'd love for that to be true, but let's see how their first example does compare against bash/ssh:
local = Rush::Box.new('localhost')
remote = Rush::Box.new('my.remote.server.com')
local_dir = local['/Users/adam/myproj/']
remote_dir = remote['/home/myproj/app/']
local_dir.copy_to remote_dir
remote_dir['**/.svn/'].each { |d| d.destroy }
versus remote=my.remote.server.com
local_dir=/Users/adam/myproj/
remote_dir=/home/myproj/app
scp -r $local_dir $remote:$remote_dir
ssh $remote "find $remote_dir -name .svn | xargs rm"
Okay so, bash/ssh is a tiny bit shorter, but that was to be expected.Contrary to bash reputation, there is a lot less hard to type line noisy characters in the bash/ssh version than in the rush one, namely all the |[{ etc of the ruby version.
In my opinion, due to the reduced line noise, the bash/ssh version is a lot easier to read too. But it's less self-explanatory, in that scp/ssh commands are replaced by full names.
One might argue that the rush version is more conceptually elegant, because everything is objects, and you can streamline treatments this way, but :
- Even if this isn't true for bash, in practice it's the same thing, because connection strings are treated like hosts by all relevant programs, directory strings like directories by all relevant programs, etc. You lose in typing but not in usability
- This is in a context of a script where the authors considered it was better to actually have variables for everything, so that, i guess, the thing be better configurable, readable, and reusable. That's a good goal, but it's not always necessary.
Let's see how "raw" versions of the two compare :
scp -r /Users/adam/myproj/ my.remote.server.com:/home/myproj/app
ssh my.remote.server.com "find /home/myproj/app/ -name .svn | xargs rm"
versus root['/Users/adam/myproj/'].copy_to Rush::Box.new('my.remote.server.com')['/home/myproj/app/']
Rush::Box.new('my.remote.server.com')['/home/myproj/app/**/.svn/'].each { |d| d.destroy }
The verboseness is of course worse when you don't declare variables. Let's be honest, i don't often declare variables for one off commands on the shell. I use auto-complete and i'm done with it. And for having typed this rush example by hand, i can assure you i'm not really ready to type that again anytime soon.So i seriously doubt something like rush can replace something like bash/ssh. The benefits are likely to show up for bigger operations, where lots of people already use perl/python/ruby anyway because bash is a PITA for any serious programming, but bash still seems a lot more usable as a "shell", and i kind of understood this was the purpose of this.
Besides that, I like structured data in the form of an object vs parsing everything from text.
However, this really is more of a unix criticism and less a bash criticism.
Why are people approaching a task which has a prerequisite of being speedy with the shell in the first place?
My only complaint about modern shells would be the lack of data structure support. I think it's slowly being remedied what with bash getting basic associative arrays.
But calling bash slow is kind of strange. What are you trying to do in a shell, that you can call it slow? A shell simply parses commands and dispatches them. For example, if you grep a 100GB file and it takes a long time the shell is not the bottleneck.