New Z shell blog

I’ve started a blog exclusively about the astonishingly powerful Z shell.

Check it out here: Focus on Zsh.

The goal is to find some of the more interesting and complex examples of Zsh code, and to break them down, explaining them line by line. Despite having worked with Zsh for many years (over a decade), I consider that I’ve barely scratched the surface of what it can do, and, not finding many instructive Zsh resources, have decide to create one.

Please take a look, and I look forward to your feedback.

Advertisements

A for Alias

In Zsh (and other shells), aliases may be the most important feature for increased productivity.

A simple rule is this: the more often you run a command, the shorter it should be. I’ve written about this before, in Efficient Way to Improve Console Productivity.

I have a number of one-character aliases:

G='| glark'
H='| head'
L='| less'
M='| more'
S='| sort'
T='| tail'
a=alias
c=clear
h='history -5000'
l='ls -CF'
t=cat

I’ll write later about those nifty uppercase ones (and yes, there is the alias “a” for “alias”, but for now, I’ll just show them with examples:

alias G -g '^.='

That was the command that I ran to generate the list above. It expands to “alias | glark -g ‘^.='”.

find src -type d S

That finds all directories and pipes them to sort.

There are three “families” of commands that I run the most often:

  • diff – diff files
  • eye – look at/in files on the command line
  • find – list all files/directories matching a pattern
  • open – open files in editor, browser
  • search – look in files

So I have been writing one-character scripts/functions (in Bash) for each of the above, where the script understands context as well as the targets.

For example, “s pluralize” run from a directory that contains a “Rakefile” will expand to search (using glark) only for Ruby files.

e program.tar.gz” is the equivalent of “tar ztvf program.tar.gz“, and “e program.zip” lists the zip file, with entries sorted by name.

d dir1 dir2” runs a recursive diff on the directories, and “d path/to/file ../dir2” will diff “path/to/file” against “../dir2/path/to/file”, if the latter file exists. I do this to avoid the tedious repetition of comparing one code base to another (such as two branches, when merging them): “diff path/to/file1 ../dir2/path/to/file1“, “diff path/to/file2 ../dir2/path/to/file2“, etc.

Although this project is in its early stage, and the output is still rough (i.e., containing debugging output), it already has been quite useful, so I thought I would share.

The project is at Github here.

RVM, Zsh and Konsole

Today I set up RVM with Zsh (Z shell) with Konsole (the KDE equivalent to gnome-terminal).

The RVM Konsole example shows it with bash, setting the “Command” field to “/bin/bash –login”. The line for Zsh is nearly the same: “/usr/bin/zsh –login”.

If you don’t have this, you’ll get the error:

% which ruby
/usr/bin/ruby
% rvm use 2.0

RVM is not a function, selecting rubies with 'rvm use ...' will not work.

You need to change your terminal emulator preferences to allow login shell.
Sometimes it is required to use `/bin/bash --login` as the command.
Please visit https://rvm.io/integration/gnome-terminal/ for an example.

Note that you’ll need to have RVM as the first component in the PATH (“echo $PATH”).

With the “Command” field set to “/usr/bin/zsh –login” (that’s “dash dash login”), when you start a new terminal you should get:

% which ruby
/home/jpace/.rvm/rubies/ruby-1.9.3-p551/bin/ruby
% rvm use 2.0
Using /home/jpace/.rvm/gems/ruby-2.0.0-p598
% which ruby
/home/jpace/.rvm/rubies/ruby-2.0.0-p598/bin/ruby

zsh Event Tricks

I’ve been a Z shell (zsh) user for perhaps 15 years, being a tcsh user before that.

Unfortunately, it appears that there is no zsh book from my preferred technical books publishers, O’Reilly, Pragmatic Programmers or Manning. Thus my knowledge is from the zshall man page (all 15,000+ lines, when you can find it) and from experience.

I’d like to share a few examples of what one can do with this shell, and I’m going to go from most to least recent in what I’ve found and used.

The latest thing that I learned is how to get previous arguments. I’d known about “!!” to get the previous full command line, so if I needed the second argument, I’d do “!!<tab>”, then backspace (or search back, i.e., “<ctrl>r”) to the end of the argument, delete (“<ctrl>k”) to the end of the line, then move to the beginning of the argument “<alt>b”, then delete word-by-word “<alt><backspace>” through all the other arguments that “!!<tab>” expanded to.

What a mess, although doing that a few hundred times made it easy, although far from efficient.

So when perusing the 15,000 zshall man page (one day I’ll make that my summer reading) I saw that one can write “!!:2” to get the second argument of the previous line. Hurrah. Note that, of course, arguments are zero-indexed.

And the leading “!!” can be of the form “!-3”, meaning “the third most recent”, and “!-1” is the same as “!!”.

I haven’t used this much, but the word designators (the argument after the “:”) can be a range, so for the second through fourth argument of the command before last, the command would be “!-2:2-4”. If there is no starting number for the range, e.g., “!!:-2”, then that is the same as 0 through N, the first N+1 arguments from the earlier command.

In action, this looks like:

designators

Another form of syntax, as seen in the example above, is !N, where N is the number of the command line to reference. In the example, 3066 is the command line in history, so !3066:3 refers to the fourth word in that command.

In a subsequent post, I’ll discuss the prompt that you just saw, and why having the command-line number is useful.

Efficient Way to Improve Console Productivity

One of the principles of efficiency when programming is to avoid unnecessary repetition (DRY), be it in code, or in physical and mental tasks. My goal is to write at least one tweak per day to my environment, whether a macro in my editor (Emacs), or a shell script or alias in my console environment, which is Z shell. (Note that this applies to other shells also.)

Reading Matthew Might’s article on console hacks inspired me to use that to quickly and easily find candidates for aliases and functions in Z shell.

The following command sorts the history by frequency of use:

% history -1000000 | cut -c8- | sort | uniq -c | sort -n | tail -15

The output from my recent work with DoctorJ is:

     11 cd ~ijdkproj
     12 gitpullall
     12 myprod.rb
     12 rake
     13 ..
     14 gitdfs
     15 c
     15 la
     20 sd
     24 scrub
     27 git status
     28 git push -u origin master
     37 git diff
     39 ls
     51 gct
     52 gitdelta.rb

(If you’re wondering what the “..” command is, that’s an alias for “cd ..”.)

In the frequency list the salient command in terms of length is “git push -u origin master”, executed 28 times. So we can consider an alias for it, such as “gpom”, and see whether it already exists as a function, alias, or program:

% which gpom
gpom not found

Since it doesn’t already exist, we can add it to the list of aliases (mine are in ~/System/Zsh/aliases.zsh):

alias gpom=’git push -u origin master’

On Github I’ve posted my Z shell configuration, with the updated aliases file here.

Searching Companion Files

This little ditty (there are no large ditties) looks for a file in the same directory as another file, and then searches that file for the string “desc”, using glark. Note that this is in Z shell.

% for i in **/foo.xml; do n=`dirname $i`/bar.txt; glark --label=$n desc $n; done