Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: alias hygiene

To add a few remarks here ...

On Feb 17, 12:30am, Daniel Shahaf wrote:
} Subject: Re: alias hygiene
} Ray Andrews wrote on Wed, 14 Feb 2018 08:09 -0800:
} > 
} >      [ some test ] && alias _grep="egrep --color=always  "$string""
} >                              || alias _grep="egrep --color=always "^|$1|$string""
} I don't understand your question

The way the quoting is arranged here is funny.  If we look at the first
line only, the quotes are such that $string must have a value at the
time the alias is defined (rather than when it is used) and there is a
useless empty quote pair at the end of the line.  Although it may seem
you can nest double quotes when using $(...) or some ${...} syntax --
	echo "Outer and $(echo "inner also") quotes"
-- the presence of the $(...) is important.  In the absence of any of
the balanced-parens or balanced-braces inside, quotes do not nest.

} 1. Calling the alias "_grep" clashes with compsys's function of that name.

This isn't really important; the completion system disables aliases, and
it would not make sense to use the _grep function outside completion, so
in practice there's no conflict.

} 2. Aliases don't have positional parameters.

True (and different from csh aliases which can make history references
to simulate positionals) but ever since the introduction of argument
processing in anonymous functions it has been possible to write

    alias _grep='() { egrep --color=always "^|$1|$string" }'

There are a few reasons (e.g., the previously mentioned clash with a
completion function) why one might prefer this over defining a named
function, and a few other reasons why one might avoid it (see below).

To be pedantic, in the above example

    _grep foo

woould expand to

    () { egrep --color=always "^|$1|$string" } foo

which would pass "foo" to the anonymous sub as "$1".

} 3. Do not interpolate strings into command strings; that's a bobby
} tables bug.

I think this was unintentional, and that instead there's confusion about
the nesting of the quotes.  I think Ray meant to write

    alias _grep='egrep --color=always  "$string"'

(although in that case I'm not sure where $string comes from).

} 4. Those pipe characters are not quoted so they create a pipeline

Another likely case of incorrect quote nesting.

} More information:
} 0. "||" is invalid at the start of a logical line.

Most likely line wrap added in a syntactically invalid place.  (Aside:
The discussion that led up to the ability to make aliases for command
separators was spawned by a desire to be able to put "||" at the start
of a logical line.)

} 1. ... (depends on how you autoload compinit)

No.  Even if compinit is loaded with aliases enabled, there's no explicit
reference to any of the _* functions to cause confusion with the alias,
and aliasing is turned off during _main_complete.  You'd have to jump
through hoops to deliberately break it.


One other remark about aliases with anonymous functions:  It's dangerous
to do this with global aliases.  Example:

    alias -g BODY='() { echo I am a function body }'
    echo this is a BODY

will (with default setopts) create four functions (echo, this, is, a)
all with the same definition -- and that "echo" function calls itself.

Messages sorted by: Reverse Date, Date, Thread, Author