Sean O'Dell
10/3/2003 4:28:00 AM
John Carter wrote:
> Somebody suggested I use zsh instead of bash for my commandline, so I
> looked at it, looked at the syntax for tweaking the profile files, and
> said...
> "Yuck! Another badly designed syntax! Why can't I just use Ruby?"
>
> And that got me thinking.
>
> Consider backquotes.
>
> a = `wc *.c`
>
> What did that do? Same as open("|wc *.c").
>
> It ran bash!
>
> Yuck!
>
> system( "tar -xvzf foo.tgz foo")
>
> What did that do? It ran shell!
>
> Why? Why does a scripting language like Ruby keep invoking an old and bad
> scripting language call shell?
A script language, if it wants to be portable, doesn't "blend" itself
with unix shell programs. Ruby has pipes, sockets and other perfectly
normal programatic ways to communicate between applications.
> Because...
>
> a) Ruby doesn't have a good syntax for invoking and dealing with
> processes and pipes between processes.
It has the IO::pipe method which is pretty standard. You create a pair
of pipes, then fork and exec whatever program you want to communicate with.
> b) Ruby doesn't have a built in understanding of ENV['PATH']
Well, PATH isn't really for programming languages; it's a shell/os
paradigm. Programs *can* make use of it, if they choose to, but I don't
see that as being a languages' responsibility. It's there in the ENV
hash; use it if you need it.
Anyway, it would be pretty simple to implement, and I wouldn't be
surprised if there isn't support for finding programs with it buried
somewhere in one of the libraries distributed with it.
> c) Ruby doesn't have such a simple syntax for globbing (beyond
> Dir['*.c'])
>
> Consider the "rename" facility that comes with perl these days.
> For example, to rename all files matching "*.bak" to strip the exten-
> sion, you might say
>
> rename 's/\.bak$//' *.bak
>
> To translate uppercase names to lower, you'd use
>
> rename 'y/A-Z/a-z/' *
>
> Ooh! Looky! Nice! Wouldn't it be nice to have the power of ruby
> intertwingled with the commandline.
I would write:
Dir["*.bak"].each{|f| File::rename(f, f.gsub(/\.bak$/, "")) }
and:
Dir["*"].each{|f| File::rename(f, f.gsub(/[a-z]/){|s| s.upcase}) }
Wordy, but it should work just fine.
Anyway, Ruby isn't a shell, it's a programming language.
> Ruby does have Shell.rb, which takes us halfway there. (If it had
> decent docs...)
>
> How hard would it be to extend the backtick syntax to be a pure ruby
> thing. ie. So proc_exec doesn't invoke bash, but invokes Shell.rb?
>
> Hmm. Could we even do this entirely in UserLand? ie. Couldn't we
> override proc_exec and replace it with ruby code that parses the
> string, handles the redirects, variable interpolation quoting and
> forks, then just directly execs the program without ever touching sh?
I personally don't think it's Ruby's job to be more like a shell.
Shells do that very well already. Besides, no matter how much you
modified Ruby to make it more shell-like, you are always going to find
things it won't do as well as a shell could, so you will drop out and
ask the shell to do it.
Using a programming language, as opposed to a shell, means that some
things are easier to do, and some things are harder. But I don't think
changing Ruby to make a specific group of tasks easier, when shells
already do those tasks very well, is the answer.
Sean O'Dell