Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Since I have been using rc as my interactive shell since approximately 2001 and since I tend to have a PERFECTIONISTIC attitude towards the software that I use every day like the OP has, I will give a list of what I like and dislike about rc (relative to bash) in order of decreasing importance or significance. (Specifically, since about 2001, I have been using the port of rc by Byron Rakitzis on Linux and OS X.)

If you like Unix shells, then you probably want to skip this comment since it is my opinion that all unix shells including rc suck for interactive use.

The original meaning of the word "shell" was a interface layer between the core Unix system and the user. I now consider Emacs my shell, and I try to replace interactive use of rc, bash or other traditional Unix shells with interactive use of Emacs whenever practical.

E.g., to escape from the hassle described below caused by equal signs in Youtube URLs, I defined an Emacs Lisp function M-x youtube-dl so that I no longer need to use a Unix shell to interact with the command-line program youtube-dl. (This works for me because 99.9 percent of my interactions with rc are through Emacs. Consequently, I do not need to switch from Terminal.app to Emacs.app to type M-x youtube-dl because Emacs.app already has the focus even when I am interacting with rc, and Terminal.app is not even running most of the time on my system.)

I tend to define new commands and wrap/redefine existing commands like ls a lot, which of course means writing some code. Consequently, the list below includes problems I encountered (in bash and in rc) in writing and maintaining code that defines new interactive commands and defines wrappers around existing interactive commands. (My .rcrc file -- which is rc's analog to .bash_profile and .bashrc -- is currently 704 lines long and contains 112 definitions of rc functions, but about half of those 112 are "of historical interest only". I.e., maybe I should have deleted most of them by now.)

Here starts the list.

Backslash does not quote the next character in rc like it does in bash.

Consequently, to refer to a file name with space in it, you have to do it 'like this' rather than like\ this.

Unfortunately, all the softwares I am aware of that do tab completion of file names quote spaces and pound signs like\ this, which makes it tedious in rc commandlines to type file names with spaces and pound signs in them. This has been for me the biggest disadvantage of rc relative to other shells. It has been especially painful OS X where spaces in file names are not rare, but even on linux it was painful for me to specify file names like #long_name_here# which Emacs was in the habit of leaving around until I figured out how to get it to stop doing that.

Parenthetically, I ran into the same basic problem with all the Plan-9 and Plan-9-inspired software I tried to embrace (e.g., Wily, Acme via plan9port): namely, although the design decisions work okay for people who use only Plan 9, the mismatch between the Plan 9 way of doing things and the OS X or Linux way of doing things makes it unworthwhile to use a Plan-9-inspired tool or a tool ported from Plan 9 on OS X or Linux. E.g., on Plan 9, file-name completion via the tab key is simply unavailable, which works on Plan 9 because everyone including the providers of the basic system keeps path names nice and short.

In bash et al, you can have an equal sign in a file name or a URL without needing to quote it. In contrast, in rc, you need to quote it. this is a hassle for me since youtube URLs have equal signs in them, and I am in the habit of pasting them into shell commandlines a lot.

The thing I like most about rc relative to bash is that a function definition begins with the characters "fn foo" where "foo" is the name of the function. This makes it easier to use plain old "find in page" functionality to navigate to a function definition in a file full of function definitions. In other words, in bash et al, you have to type "foo()" to search for the start of the definition of the function foo whereas in rc you can type "fn foo " which is easier to type.

Moreover, in the process of writing this, I used grep to determine the number of function definition in my .rcrc file (rc's analog to bash's .bashrc file). specifically, I used "grep '^fn ' .rcrc". the analogous operation for bash is harder to express.

Since this thing I like most about rc is a relatively small thing, you would be correct in concluding that I do not believe it is worth it to switch from a normal shell like bash to rc.

Another thing I like about rc: unlike bash, newlines are not somehow in subtle ways significant in "multi-line constructs" like if statements. in other words, if statements, switch statements and for statements in rc resemble statements in normal languages like C more than if statements, etc, in bash do.

The quoting rules are simpler in rc than in bash. Although I found that very appealing in theory before I started using rc, in practice, I still struggled with "quoting-related issues" in rc. for example, the definition of the rc function I used as a wrapper around /bin/ls contained the following code whose purpose is to "print" (cat to stdout) its contents whenever there exists a file named .hdr in the directory being listed.

the code loses whenever the full path to the directory I want to list contains a space. in particular if I cd somehow to /0/library/saved application state, then invoke my wrapper command, the error message

test: application/.hdr: unknown operand

test: application/_darcs: unknown operand

test: application/.alpha: unknown operand

appear in the output, and the .hdr file is not printed. For those readers who know how to fix that bug in the code below, please do not feel you need to educate me about the fix. To write code in rc you have to know some "shell lore", and although some people might take pride in learning shell lore, I'd rather avoid the need to learn it. In most languages (e.g., Python, Ruby, Lisp), there is no special lore one has to learn to ensure that path names with spaces in them are handled correctly.

    # set dirname2 to the directory portion of the last argument.
    # make that directory name an absolute file name.
    # make sure it ends in a slash.
    if (!test -d $*($#*)) {
        dirname2 = `{cd `{dirname $*($#*)}; pwd}^/
    } else {
        dirname = `{cd $*($#*); pwd}
        switch($dirname) {
        case */
            dirname2 = $dirname
        case *
            dirname2 = $dirname^/
        }
    }
    # if a .hdr file exists, print it now:
    if(~ $#* 1) {
        if(test -d $1) {
            if(test -r $dirname2^.hdr) {
                cat $dirname2^.hdr
                echo
            }
        }
    }
in summary, for me switching to rc was probably a waste of my time, and I would have been better off sticking with bash (and better off starting sooner on my slow mission to replace interactive uses of traditional Unix shells with interactive uses of Emacs).


I agree interactive shells suck. I like to use Acme which has been called Plan 9's Emacs, but it uses the shell tools instead of Lisp. In Acme I can enter a shell command -- I can write it directly in the appropriate dir list if I want -- then to execute it either drag over it with the middle button, or select the whole line (by double-clicking after the end; nice and easy) and then middle-click. It's much nicer than groping around blindly in a regular shell window. I've not found it so good when I wanted to use environment variables, but I've just thought on Plan 9 I could edit the files in /env directly. Not sure if that will work correctly though.


You've missed the point of Uriel. Suckless alternatives aren't meant to be more practical than harmful software.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: