Tuesday, November 4, 2014

bash shell tab auto-completion and history command completion

If you have this in your /etc/inputrc or ~/.inputrc, you will no longer have to hit the <tab> key twice to produce a list of all possible completions. A single <tab> will suffice. This setting is highly recommended.

# vi ~/.bash_profile
#!/bin/bash
source ~/.bashrc # get aliases

# vi ~/.bashrc
### alias
alias ls='ls --color=auto'
alias ll='ls -l'
alias h='history'

### ls with color
export CLICOLOR=1 # Use colors (if possible)
export LSCOLORS="ExGxFxdxCxDxDxBxBxExEx"

### display history command with date and time
export HISTTIMEFORMAT="%m/%d/%y %T "

### Prompt
PS1='\e[0;32m\u@\h \w #\e[m '

#######
# Note: on Ubuntu, xterm-256color may be in different place, try this:
# find /lib/terminfo /usr/share/terminfo -name "*256*"
# Note: tmux respects screen-256color
#######
#if [ -e /usr/share/terminfo/x/xterm-256color ]; then
# export TERM='xterm-256color'
#else
# export TERM='xterm-color'
#fi

### Make bash check its window size after a process completes
#shopt -s checkwinsize

Bash tab auto-completion and history completion by using ~/.inputrc:
# vi ~/.inputrc
### enable filename tab auto-completion
set show-all-if-ambiguous on
set show-all-if-unmodified on

### if you don't want case-sensitivity
#set completion-ignore-case on

### bash history completion to complete what's already on the line
### arrow up
"\e[A": history-search-backward
### arrow down
"\e[B": history-search-forward

Note: A bit background explanation:
Bash is using readline to handle the prompt. ~/.inputrc is the configuration file for readline.
Read the bash manual for more information about readline. There you can also find more history related readline commands.

To get the escape codes for the arrow keys you can do the following:
  1. Start cat in a terminal (just cat, no further arguments).
  2. Type keys on keyboard, you will get things like ^[[A for up arrow and ^[[B for down arrow.
  3. Replace ^[ with \e.
Note: Normally, Up and Down are bound to the Readline functions previous-history and next-history respectively. I prefer to bind PgUp/PgDn to these functions, instead of displacing the normal operation of Up/Down.

# vi ~/.inputrc
"\e[5~": history-search-backward
"\e[6~": history-search-forward

Note: use "bind -p" or "bind -P" to get a list of bash key bindings.

Note: .inputrc will get read whenever you start a new bash process.

Note: After you modify ~/.inputrc, restart your shell or use Ctrl+X, Ctrl+R to tell it to re-read ~/.inputrc.

Note: please notice that ~/.inputrc and /etc/inputrc are NOT bash scripts, so please don’t try to source them. So, restart your Terminal.

Bash tab auto-completion and history completion by using ~/.bashrc:
# vi ~/.bashrc
### bash history completion to complete what's already on the line
bind '"\e[A": history-search-backward'
bind '"\e[B": history-search-forward'

From the bash manpage:
When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable. The --noprofile option may be used when the shell is started to inhibit this behavior.

When a login shell exits, bash reads and executes commands from the file ~/.bash_logout, if it exists.

When an interactive shell that is not a login shell is started, bash reads and executes commands from ~/.bashrc, if that file exists. This may be inhibited by using the --norc option. The --rcfile file option will force bash to read and execute commands from file instead of ~/.bashrc.

Thus, if you want to get the same behavior for both login shells and interactive non-login shells, you should put all of your commands in either .bashrc or .bash_profile, and then have the other file source the first one.

===================================================
When working with Linux, Unix, and Mac OS X, I always forget which bash config file to edit when I want to set my PATH and other environmental variables for my shell. Should you edit .bash_profile or .bashrc in your home directory?
You can put configurations in either file, and you can create either if it doesn’t exist. But why two different files? What is the difference?
According to the bash man page, .bash_profile is executed for login shells, while .bashrc is executed for interactive non-login shells.

What is a login or non-login shell?

When you login (type username and password) via console, either sitting at the machine, or remotely via ssh: .bash_profile is executed to configure your shell before the initial command prompt.

But, if you’ve already logged into your machine and open a new terminal window (xterm) inside Gnome or KDE, then .bashrc is executed before the window command prompt. .bashrc is also run when you start a new bash instance by typing /bin/bash in a terminal.

Why two different files?

Say, you’d like to print some lengthy diagnostic information about your machine each time you login (load average, memory usage, current users, etc). You only want to see it on login, so you only want to place this in your .bash_profile. If you put it in your .bashrc, you’d see it every time you open a new terminal window.

Mac OS X — an exception

An exception to the terminal window guidelines is Mac OS X’s Terminal.app, which runs a login shell by default for each new terminal window, calling .bash_profile instead of .bashrc. Other GUI terminal emulators may do the same, but most tend not to.

Recommendation

Most of the time you don’t want to maintain two separate config files for login and non-login shells — when you set a PATH, you want it to apply to both. You can fix this by sourcing .bashrc from your .bash_profile file, then putting PATH and common settings in .bashrc.

To do this, add the following lines to .bash_profile:
if [ -f ~/.bashrc ]; then
   source ~/.bashrc
fi
Now when you login to your machine from a console .bashrc will be called.

Reference:
http://www.caliban.org/bash/index.shtml

http://stackoverflow.com/questions/902946/about-bash-profile-bashrc-and-where-should-alias-be-written-in

http://www.joshstaiger.org/archives/2005/07/bash_profile_vs.html

http://askubuntu.com/questions/59846/bash-history-search-partial-up-arrow

No comments: