I am using zsh.
I have a command foo, and I use alias foo="sudo foo" as a shortcut. I want zsh to complete the command just like I typed foo.
I googled and found compdef _foo f=foo which can deal with it. When I type f something<tab>, the completion works fine. But when I try compdef _foo foo=foo and then foo something<tab>, it does not work.
Is there a way to deal with the Tab completion when I use an alias with the same name as the original command?
The problem is actually a special case happened to me.
As #blueray said, zsh is able to complete commands like sudo foo or an alias of it normally.
Thanks to #rcwnd_cz , I found that adding setopt complete_aliases solves my problem. The point is that I set an alias somewhere else that maps sudo to sudo FOO=bar. As a result, alias foo="sudo foo" is an "alias in alias", and zsh refuses to complete it. Setting setopt complete_aliases solves it perfectly.
Related
I'm facing an issue while trying to use alias in my zsh
If I run alias , I get a list of all my alias, the ones in .aliases file, and the ones that I run manually in zsh:
oloco#Arch: alias
my_manual_alias='yes'
cat='bat --paging=never -l log'
cp='cp -iv'
doc=/home/oloco/Documents
dot=/home/oloco/.dotfiles
dow=/home/oloco/Downloads
egrep='egrep --color=auto'
fgrep='fgrep --color=auto'
But, I I try to echo any of them, nothing is shown:
oloco#Arch: echo $my_manual_alias
Why this behaviour? I think I should get my alias this way...or maybe not?
Thank you in advance!
I have created some console commands in PHP. I need to use autocompletion when I launch my tasks.
I used alias otra="php console.php" in my .zshrc file.
The function itself seems to work but when I type my command name 'otra', there is only folders autocompletion...which is completely irrelevant in my case.
#compdef _otra otra
function _otra {
local line
_arguments -C \
"1: :(createAction createBundle)" \
"*::arg:->args"
}
I want to only have the two words createAction and createBundle to appear when I type otra and type .
EDIT
Ok, it is what I was thinking...if I remove my alias, the completion works but I cannot remove it since otra is not a valid command...
I tried to use setopt no_complete_aliases as I see it in another Stackoverflow post but it does not work for me.
In fact, it was related to the alias but I did not have to set setopt no_complete_aliasesin my case but pretty much the contrary...
After I put setopt complete_aliases in my .zshrc file, it works :D
Here's my .zshrc:
alias inst="adb install -r -d"
notify() {
start=$(date +%s)
"$#"
notify-send "\"$(echo $#)\" took $(($(date +%s) - start)) seconds to finish"
}
When I run the command notify inst app.apk, I get an error:
notify:2: command not found: inst
0.00s user 0.00s system 0% cpu 0.001 total
Can anyone shed some light on why this doesn't work, and hopefully a way to make it work?
When the shell processes commands, among other things (e.g. PATH search) it will check to see if the first token/argument (whitespace delimited) belongs to an alias loaded in the current environment. If the alias you are trying to substitute is not the first token, the substitution will not happen. If your alias happens to not be the name of an executable on the PATH or current directory, the error will propagate back up to a command not found.
Since your question is about the Z Shell, zsh actually provides a lesser-known feature called global aliasing. If an alias is declared with the -g flag, zsh will make the appropriate substitution for not only the first token, but any token, regardless of order.
alias -g inst="adb install -r -d" should do the trick.
Keep in mind that this is a zsh only feature for portability reasons, and make sure that whatever script your writing has a shebang line that invokes the zsh shell: #!/usr/bin/env zsh
I would also recommend to not use zsh global aliasing in important or production scripts. For personal use, it is perfectly fine.
Don't use alias for scripting
First, according to the advanced bash scripting guide:
In a script, aliases have very limited usefulness.
So you may consider not using alias but a function for instance (still from the same page, 2 paragraph lower):
Almost invariably, whatever we would like an alias to do could be accomplished much more effectively with a function.
A hacky solution
If this is for a quick script for yourself using aliases you have in your .zshrc, there is still a way out.
alias foo='echo hello'
bar() {
`alias "$#" | cut -d\' -f2`
}
bar foo # => hello
Alias replacement
from alias man page:
The first word of each simple command, if unquoted, is checked to see if it has an alias. If so, that word is replaced by the text of the alias. The alias name and the replacement text can contain any valid shell input, including shell metacharacters, with the exception that the alias name can not contain `='.
The first word of the replacement text is tested for aliases, but a word that is identical to an alias being expanded is not expanded a second time. This means that one can alias ls to "ls -F", for instance, and Bash does not try to recursively expand the replacement text.
Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt .
The rules concerning the definition and use of aliases are somewhat confusing. Bash always reads at least one complete line of input before executing any of the commands on that line. Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias. This behavior is also an issue when functions are executed. Aliases are expanded when a function definition is read, not when the function is executed, because a function definition is itself a compound command. As a consequence, aliases defined in a function are not available until after that function is executed. To be safe, always put alias definitions on a separate line, and do not use alias in compound commands.
Really quirky title, I know.
Basically, I have this:
alias vv="xclip -selection clipboard -o"
which prints out anything in my clipboard, such as a repository location in ssh-form (git#github.username/repname.git).
Now I'd like to:
git clone vv
I tried several variations of the above, such as trying various switches on the alias, or using different expansions, but with no luck.
Any suggestions?
Global alias might do it... actually it does it:
alias -g vv="$(date)" # replace 'date' with your command of choice
Notice:
it is a global alias, so it works anywhere in the command line (not just the beginning)
$(...) will do command substitution and expand it as a variable, see man zshexpn and search for $(...). By default zsh will not break the results using white-spaces.
[...]
I initially wrote a suggestion to create a (zsh) widget to insert the clipboard into the command line with a given key combination, then I realized that you would just likely hit "Ctrl-Shift-V" or something... :-S
[...]
FYI, this is how you would do this using a zsh widget:
that inserts the clipboard content on the command line, and binding it to some key, as it would allow you to see what you are doing before hitting enter. Place the following into your $fpath, inside a file called insert-clipboard (needs to be loaded with KSH_AUTOLOAD set)
#! /bin/zsh
## Inserts the output of the command into the cmd line buffer
zmodload -i zsh/parameter
insert-clipboard() {
LBUFFER+="$(date)" # REPLACE date BY YOUR COMMAND!
}
At your .zshrc
autoload insert-clipboard # as written, it needs KSH_AUTOLOAD set....
zle -N insert-clipboard
bindkey '^Xu' insert-clipboard # pick a key combination you like...
Is there a way I can get the pwd in an alias in my .zshrc file? I'm trying to do something like the following:
alias cleanup="rm -Rf `pwd`/{foo,bar,baz}"
This worked fine in bash; pwd is always the directory I've cd'd into, however in zsh it seems that it's evaluated when the .zshrc file is first loaded and always stays as my home directory. I've tested using with a really simple alias setup, but it never changes.
How can I have this change, so that calling the alias from a subdirectory always evaluates as that subdir?
EDIT: not sure if this will help, but I'm using zsh via oh-my-zsh on the mac.
When your .zshrc is loaded, the alias command is evaluated. The command consists of two words: a command name (the builtin alias), and one argument, which is the result of expanding cleanup="rm -Rf `pwd`/{foo,bar,baz}". Since backquotes are interpolated between double quotes, this argument expands to cleanup=rm -Rf /home/unpluggd/{foo,bar,baz} (that's a single shell word) where /home/unpluggd is the current directory at that time.
If you want to avoid interpolation at the time the command is defined, use single quotes instead. This is almost always what you want for aliases.
alias cleanup='rm -Rf `pwd`/{foo,bar,baz}'
However this is needlessly complicated. You don't need `pwd/` in front of file names! Just write
alias cleanup='rm -Rf -- {foo,bar,baz}'
(the -- is needed if foo might begin with a -, to avoid its being parsed as an option to rm), which can be simplified since the braces are no longer needed:
alias cleanup='rm -Rf -- foo bar baz'