14 Feb 2013

Getting Started Configuring Bash/Zsh

I saw a post this afternoon by a member of Ruby Rogue’s Parley list asking how to write Ruby code to help them create a shorthand word for a longer commandline command. It takes moxy to ask questions on a list filled with many experienced developers. I was happy to see that positive responses flowed in. The immediate response was that the individual should perform the action by writing commandline aliases using the shell ‘alias’ command. But that only points the developer in the right direction. Instead of just pointing in the direction, the rest of this post will be walking a new developer through setting up helpful customizations in the shell environment. (Note, the generic information will be fairly compatible whether using the BASH environment or ZShell environment. Moving past general configurations into advanced configurations are where the two start to diverge, particularly with the environmental settings used in .bashrc or .zshrc files. I’ve found that the best remedy for this is reading through and gradually adopting a few lines here and there from well commented .bashrc/.zshrc files). Many of the customizations in the shell relate to minimizing repetitive keystrokes. Imagine the difference between typing

bundle exec rails server

and

be r s

If you’re typing this more than occasionally, it’s a large savings of keystrokes over a period of months. So how is it done? Aliases! Simply put, include the following code in your config file (a generic term that I’ll use for either .bashrc or .zshrc, depending on your shell): alias j="jobs" Or to help avoid dumb mistakes (it makes the remove command verbose and interactive =D. Even astute geeks fat finger the occasional keys ) alias rm="rm -iv".

I’ve taken to heart the adage, which I can’t attribute precisely, that anything typed more than a couple times on the commandline should be shortened to save future keystrokes. To prove this point, I currently have greater than 100 aliases and growing. Note that the following is from dumping all of my aliases to STDOUT via alias > jist -p -c and is not representative of one of my alias files. (For that, see the second inset codeblock).Here’s an example of one of my alias files… appropriately called ‘aliases.conf.zsh’:(Original code is at: https://github.com/zph/zph/blob/master/home/.zsh.d/aliases.conf.zsh) So that’s ‘aliases’. I find that they’re easier to keep organized if I setup a dedicated ‘.zsh.d’ folder. By which I mean that I created a folder called ‘.zsh.d’ in the base of my home directory with the following layout:

This folder contains all of the ‘zsh’ configuration files on my system other than ‘.zshrc’. Each general category of config files gets its own file, ie git.zsh, ruby.zsh, homebrew.zsh, etc. Helps me keep everything organized =D. I set the following lines in my ‘~/.zshrc’ to source each file within the ‘.zsh.d’ directory that has the extension of ‘.zsh’

_source_zshd(){
# Finally, source all the files in zsh.d (ALPHA order)
  for zshd in $(find ~/.zsh.d/*.zsh | sort );
    do source "${zshd}"
  done
}

This isn’t necessary, but it helps me keep the individual configurations nicely ordered. To recap, use aliases. Use the daylights out of them. Make your shell a finely honed tool that’s nicely crafted to your needs. Oh yeah… do the same with ‘functions’ which I can cover in a future blog post. And look into FASD because it’s awesome like Narwhals! Questions, thoughts, jeers, feedback… catch me on ‘ye ol Twitters’ @_ZPH

14 Feb 2013

Make the Shell Your $HOME

Let’s talk about how to use the shell. It’s a dirty secret that many of the repetitive commands used in the day-to-day world of developers are rudimentary shell commands.

Think of the activity of making a new folder and moving into that folder to start writing code, it looks something like this: mkdir new_project; cd new_project; vim new_project_code_file.rb.

Tighten it up and pay attention to simple improvements in the shell environment. ( My experiences are with BASH and ZSH ). That command becomes the following command with a little bit of improved shell configs: mkdircd new_project (makes dir and cds in the same command); e !!1_code_file.rb.

What’s in this shorter series of commands? Let’s break it down to parts:

  • mkdir and cd are replaced by a single new command mkdircd. We save the repetition of typing the folder name twice by compressing the command into a single request. It’s accomplished by setting up an alias in the shell configs.
  • vim new_project_code_file.rb is replaced with e !!1_code_file.rb. The e command is another shell tweak of mine. e is a shell function that steps in for the vim command and opens files for editing in a more intelligent way. See the source here: e (Note that it also depends upon the wonderful FASD utility available on Github.com).
  • !!1 becomes the first argument from the prior line, i.e. the first item after the command itself. Using !!1, !!2, !!3 has saved me countless seconds of retyping the same long folder/file names.

So, make the shell work for you! If you’re spending time in a new envionrment like the Linux Terminal or OSX’s Terminal, learn to configure that BASH or ZSH environment.

It will pay off nicely!

If you liked the article, follow me on Twitter at @_ZPH.

27 May 2012

Todo.txt Count in RPrompt ZSH

I’ve been using Todo.txt for at least a year, both from the commandline and the Android app.

It’s great keeping a todo list in text files, synchronized across multiple devices via Dropbox, but there’s one nagging thing in my system.
That nagging issue is that Todo.txt doesn’t nag me enough about the issues in my todo list! So, I’m taking steps to resolve this by adding a function to my zshrc configuration.

I mapped out the basic command in the shell by combining todo’s ls, grep (to keep only lines starting with numbers), and then a wordcount by line.

The following function was taken from Wynnnetherland.com and modified since I installed todo.txt through Homebrew, and since I prefer a different command to count the items.

todo\_count(){ if $(which todo.sh &\> /dev/null) then num=$(echo $(todo.sh ls | grep "^[0-9]" | wc -l)) let todos=num if [$todos != 0] then echo "$todos" else echo "" fi else echo "" fi } function zle-line-init zle-keymap-select { RPS1="${${KEYMAP/vicmd/\>\>\> ○[$(todo\_count)]}/(main|viins)/± \<\<\<[$(todo\_count)]}" RPS2=$RPS1 zle reset-prompt }

The following is a diff of the difference showing the updated function [gist id=2817309]

Now my right hand prompt shows a nice count of incomplete todo items inside square brackets…like so: [gist id=2817339]

Update: My own syntax highlighting is escaping some of the characters, so here’s a gist of it [gist id=2817304]

21 May 2012

Using ZSH's History Incremental Search with Vi-Mode

I switched to ZSH a few months back and am spending more and more time in commandline + VIM/MacVIM.

Once I added the tag to my dotfile to force vi-mode on the commandline I lost the ability to do incremental searches of my zsh history. So here’s the fix which saves lots of typing:

First, the regular keybind to allow Ctrl-R to enter history search backward mode: bindkey "^R" history-incremental-search-backward

To fix the fact that the prior keymap no longer works in vi-mode zsh, add this to a zsh config: bindkey -M viins '^R' history-incremental-search-backward bindkey -M vicmd '^R' history-incremental-search-backward

Now I can ^R with aplomb…

This is thanks to the explanation from JDeBP over on superuser.com.

07 May 2012

Slick ZSH Trick for Vi-Mode

Found a neat trick today for making the commandline vi-mode much more friendly.

Back-story: As I’ve been spending more time programming, I find myself more comfortable on the commandline and in VIM. Also, there’s a setting that can be placed in .bashrc and/or .zshrc to allow vi style editing of the commandline. This is all well and good but without any visual indicator of whether I’m in INSERT MODE or NORMAL MODE… well, it’s disorenting.

So the neat trick is to add code in your .zshrc to insert a right-hand side prompt (RPROMPT) that will show a notifier depending on what mode you’re in.

Add the following code (and thank you to wherever I found this trick online)

    function zle-line-init zle-keymap-select {
        RPS1="${${KEYMAP/vicmd/--NOR--}/(main|viins)/--INS--}"
        RPS2=$RPS1
        zle reset-prompt
    }
    zle -N zle-line-init
    zle -N zle-keymap-select

Have another nice trick for your .zshrc, please share it in the comments!

29 Apr 2012

Easier Directory Navigation

Source: http://stackoverflow.com/questions/3986760/cd-1-2-3-etc-in-z-shell

While looking for a zsh compatible way to replace AutoJump with a ZSH compatible option, I found the following: setopt autocd setopt AUTO\_PUSHD The first option allow moving into a new directory by directly typing it’s name without ‘cd DIRECTORY’.

The second option allows easier navigation using ‘dirs -v’ to check for recent directories or cd ~+<tab> for tab completion jumping :).

Another little way to save small repetitions!

As a side note: I’m quite sad not to have the flexibility of AutoJump in my repetoire with ZSH. It’s the only feature I find lacking compared to BASH. Hopefully it works better in ZSH in the near future, or hopefully I can look into why it doesn’t work and learn how to patch it.