Friday, May 11, 2012

Zsh history expansion

You can refer back to prior elements of your command history, modify them, and make new commands. With Zsh expansion, history expansions can be expanded in-line before executing! Start by trying to learn a couple entries and slowly expand while building up your memory of useful mappings.

!$ and !* to reference args from prior commands

I've been using !$ (bang-last) for a while now. It expands to the last arg of the previous command. Use this when you are taking multiple actions with the same argument:

    % touch newfile
    % chmod a+x !$
    % vim !$
I'm now working !* into my command-line-fu, which pulls all the args from the previous command rather than just the last.

History Expansion:

! initiates history expansion, pulling items from your previous commands. The most commonly known/used abbreviation being !! to repeat the last command in full. Similarly !n repeats item n from your history and !-n goes back n commands. !-1 is synonymous with !!. !str is the most recent command to start with str. !# is current command line up to this point.

"Word Designators" can be applied to the selected history item, as we do above with $ and * . 0 is the command, n is the nth argument, x-y is args x through y. x* is like x-$ while x- is like x-$ excluding the last item.

I haven't even gotten started with the modifiers, like G for global on ^search^replace, a and A for prepending the current dir and crazy others.

Examples:

!!                # last command
!$                # final word of prior command
!*                # all words of prior command (excluding the command itself)
!3                # third command from history
!-3:*             # all words from three commands back 
^foo^bar          #last command, with the first substring foo replaced by bar
!-2:s^foo^bar     #full command from 2 back, with the first foo replaced by bar
!-2:s^foo^bar^:G  #full command from 2 back, with all "foo"s replaced by "bar"s

man zshexpn for all the details.
History Expansion

History expansion allows you to use words from previous command lines in the command line you are typing. This simplifies spelling corrections and the repetition of complicated commands or arguments. Immediately before execution, each command is saved in the history list, the size of which is controlled by the HISTSIZE parameter. The one most recent command is always retained in any case. Each saved command in the history list is called a history event and is assigned a number, beginning with 1 (one) when the shell starts up. The history number that you may see in your prompt (see EXPANSION OF PROMPT SEQUENCES in zshmisc(1)) is the number that is to be assigned to the next command.

Overview

A history expansion begins with the first character of the histchars parameter, which is '!' by default, and may occur anywhere on the command line; history expansions do not nest. The '!' can be escaped with '\' or can be enclosed between a pair of single quotes ('') to suppress its special meaning. Double quotes will not work for this. Following this history character is an optional event designator (see the section 'Event Designators') and then an optional word designator (the section 'Word Designators'); if neither of these designators is present, no history expansion occurs.
Input lines containing history expansions are echoed after being expanded, but before any other expansions take place and before the command is executed. It is this expanded form that is recorded as the history event for later references.

By default, a history reference with no event designator refers to the same event as any preceding history reference on that command line; if it is the only history reference in a command, it refers to the previous command. However, if the option CSH_JUNKIE_HISTORY is set, then every history reference with no event specification always refers to the previous command.

For example, '!' is the event designator for the previous command, so '!!:1' always refers to the first word of the previous command, and '!!$' always refers to the last word of the previous command. With CSH_JUNKIE_HISTORY set, then '!:1' and '!$' function in the same manner as '!!:1' and '!!$', respectively. Conversely, if CSH_JUNKIE_HISTORY is unset, then '!:1' and '!$' refer to the first and last words, respectively, of the same event referenced by the nearest other history reference preceding them on the current command line, or to the previous command if there is no preceding reference.

The character sequence '^foo^bar' (where '^' is actually the second character of the histchars parameter) repeats the last command, replacing the string foo with bar. More precisely, the sequence '^foo^bar^' is synonymous with '!!:s^foo^bar^', hence other modifiers (see the section 'Modifiers') may follow the final '^'. In particular, '^foo^bar:G' performs a global substitution.

If the shell encounters the character sequence '!"' in the input, the history mechanism is temporarily disabled until the current list (see zshmisc(1)) is fully parsed. The '!"' is removed from the input, and any subsequent '!' characters have no special significance.

A less convenient but more comprehensible form of command history support is provided by the fc builtin.

Event Designators

An event designator is a reference to a command-line entry in the history list. In the list below, remember that the initial '!' in each item may be changed to another character by setting the histchars parameter.
!
Start a history expansion, except when followed by a blank, newline, '=' or '('. If followed immediately by a word designator (see the section 'Word Designators'), this forms a history reference with no event designator (see the section 'Overview').

!!

Refer to the previous command. By itself, this expansion repeats the previous command.

!n

Refer to command-line n.

!-n

Refer to the current command-line minus n.

!str

Refer to the most recent command starting with str.

!?str[?]
Refer to the most recent command containing str. The trailing '?' is necessary if this reference is to be followed by a modifier or followed by any text that is not to be considered part of str.
!#
Refer to the current command line typed in so far. The line is treated as if it were complete up to and including the word before the one with the '!#' reference.

!{...}

Insulate a history reference from adjacent characters (if necessary).

Word Designators

A word designator indicates which word or words of a given command line are to be included in a history reference. A ':' usually separates the event specification from the word designator. It may be omitted only if the word designator begins with a '^', '$', '*', '-' or '%'. Word designators include:
0
The first input word (command).

n

The nth argument.

^

The first argument. That is, 1.

$

The last argument.

%

The word matched by (the most recent) ?str search.

x-y

A range of words; x defaults to 0.

*

All the arguments, or a null value if there are none.

x*

Abbreviates 'x-$'.

x-

Like 'x*' but omitting word $.

Note that a '%' word designator works only when used in one of '!%', '!:%' or '!?str?:%', and only when used after a !? expansion (possibly in an earlier command). Anything else results in an error, although the error may not be the most obvious one.
Modifiers

After the optional word designator, you can add a sequence of one or more of the following modifiers, each preceded by a ':'. These modifiers also work on the result of filename generation and parameter expansion, except where noted.
a
Turn a file name into an absolute path: prepends the current directory, if necessary, and resolves any use of '..' and '.' in the path. Note that the transformation takes place even if the file or any intervening directories do not exist.

A

As 'a', but also resolve use of symbolic links where possible. Note that resolution of '..' occurs before resolution of symbolic links. This call is equivalent to a unless your system has the realpath system call (modern systems do).

c

Resolve a command name into an absolute path by searching the command path given by the PATH variable. This does not work for commands containing directory parts. Note also that this does not usually work as a glob qualifier unless a file of the same name is found in the current directory.

e

Remove all but the extension.

h

Remove a trailing pathname component, leaving the head. This works like 'dirname'.

l

Convert the words to all lowercase.

p

Print the new command but do not execute it. Only works with history expansion.

q

Quote the substituted words, escaping further substitutions. Works with history expansion and parameter expansion, though for parameters it is only useful if the resulting text is to be re-evaluated such as by eval.

Q

Remove one level of quotes from the substituted words.

r

Remove a filename extension of the form '.xxx', leaving the root name.

s/l/r[/]
Substitute r for l as described below. The substitution is done only for the first string that matches l. For arrays and for filename generation, this applies to each word of the expanded text. See below for further notes on substitutions.
The forms 'gs/l/r' and 's/l/r/:G' perform global substitution, i.e. substitute every occurrence of r for l. Note that the g or :G must appear in exactly the position shown.
&
Repeat the previous s substitution. Like s, may be preceded immediately by a g. In parameter expansion the & must appear inside braces, and in filename generation it must be quoted with a backslash.

t

Remove all leading pathname components, leaving the tail. This works like 'basename'.

u

Convert the words to all uppercase.

x

Like q, but break into words at whitespace. Does not work with parameter expansion.

No comments: