I'm trying to auto-expand aliases as I type in zsh using the globalias plugin from oh-my-zsh. It was working when I first installed the plugin, but now it has broken. I think it broke after I rearranged the lines in my ~/.zshrc but I'm not sure.
I've tried to simplify the problem by removing everything except the following lines form my ~/.zshrc (I got this from a reddit thread but it also looks v similar to the function in the globalias plugin):
function expand-alias() {
zle _expand_alias
zle self-insert
}
zle -N expand-alias
bindkey -M main ' ' expand-alias
When I source this file and type a space in my prompt, I see
No such widget `_expand_alias'
I've tried googling and it seems like _expand_alias should be a built-in ZLE function, but when I look for it with zle -la | grep _expand_alias it's not there.
I'm not sure what to try next? I can't find a way to reset zsh or the built-in ZLE commands.
I solved it by adding the line autoload -Uz compinit && compinit near the start of my ~/.zshrc.
Hope this helps someone!
Related
In this question, the inimitable Dennis Williamson mentions how to bind a keystroke to a command that will run in the background of the Bash shell, with bind -x. How can the same thing be done in Zsh?
(I couldn't find this in the zshzle man page, but it's possible that I overlooked it.)
You can use zle -M to display info underneath your command line. For example:
.who() {
zle -M "$(who)"
}
# Create a new widget `who` that calls our function `.who`.
zle -N who .who
# Bind said widget to alt-shift-W.
bindkey '^[W' who
I realize, when I'm in my terminal, I would expect to press Enter on empty input to make a ls or a git status when I'm on a git repos.
How can I achieve that? I mean, have a custom behavior on Empty input -> Enter in zsh?
EDIT: Thanks for the help. Here's my take with preexec...
precmd() {
echo $0;
if ["${0}" -eq ""]; then
if [ -d .git ]; then
git status
else
ls
fi;
else
$1
fi;
}
On Enter zsh calls the accept-line widget, which causes the buffer to be executed as command.
You can write your own widget in order to implement the behaviour you want and rebind Enter:
my-accept-line () {
# check if the buffer does not contain any words
if [ ${#${(z)BUFFER}} -eq 0 ]; then
# put newline so that the output does not start next
# to the prompt
echo
# check if inside git repository
if git rev-parse --git-dir > /dev/null 2>&1 ; then
# if so, execute `git status'
git status
else
# else run `ls'
ls
fi
fi
# in any case run the `accept-line' widget
zle accept-line
}
# create a widget from `my-accept-line' with the same name
zle -N my-accept-line
# rebind Enter, usually this is `^M'
bindkey '^M' my-accept-line
While it would be sufficient to run zle accept-line only in cases where there actually was a command, zsh would not put a new prompt after the output. And while it is possible to redraw the prompt with zle redisplay, this will probably overwrite the last line(s) of the output if you are using multi-line prompts. (Of course there are workarounds for that, too, but nothing as simple as just using zle accept-line.
Warning: This redfines an (the most?) essential part of your shell. While there is nothing wrong with that per se (else I would not have posted it here), it has the very real chance to make your shell unusable if my-accept-line does not run flawlessly. For example, if zle accept-line were to be missing, you could not use Enter to confirm any command (e.g. to redefine my-accept-line or to start an editor). So please, test it before putting it into your ~/.zshrc.
Also, by default accept-line is bound to Ctrl+J, too. I would recommend to leave it that way, to have an easy way to run the default accept-line.
In my .zshrc I use a combination of precmd and preexec found here:
http://zsh.sourceforge.net/Doc/Release/Functions.html#Hook-Functions
I also find that the git-prompt is super useful:
https://github.com/olivierverdier/zsh-git-prompt
I have the following code in my .zshrc and I have .oh-my-zshell installed.
The following line, however, does not work as it is described in other posts:
autoload -U select-word-style
select-word-style bash
Is there other options I need to add in order to make it work?
if you want '^W' bash behavior you may need to unset WORDCHARS or place them in seperate functions and bind you newly created functions.
As i am not using you example, here is my way to accomplish this, second example is also for bash compatibility using <A-Backspace> which respect WORDCHAR defined as follow
x-bash-backward-kill-word(){
WORDCHARS='' zle backward-kill-word
}
zle -N x-bash-backward-kill-word
bindkey '^W' x-bash-backward-kill-word
x-backward-kill-word(){
WORDCHARS='*?_-[]~\!#$%^(){}<>|`##$%^*()+:?' zle backward-kill-word
}
zle -N x-backward-kill-word
bindkey '\e^?' x-backward-kill-word
Is there a way to do the type of auto-suggestion Fish does in Zsh?
https://github.com/tarruda/zsh-autosuggestions does exactly what I wanted. If you want fish-style autopredictions in zsh, use that.
Zsh has predict, run the commands below this and then hit Ctrl-X 1 or just type predict-on to give it a try
#-*-shell-script-*-
autoload predict-on
autoload predict-off
# you may also wish to bind it to some keys...
zle -N predict-on
zle -N predict-off
bindkey '^X1' predict-on
bindkey '^X2' predict-off
Sometimes I want a filename instead of what zsh guesses for me. For example, I have a PNG file without a proper .png suffix, which makes zsh think it isn't a picture and won't list it when I type Tab to complete arguments of display.
I am wondering if there is a key sequence that completes for a filename wherever the context is, like ^XC for _correct_filename, or how to configure zsh to do the thing?
You can add a key binding to do what you want:
zle -C complete complete-word complete-files
bindkey '^X\t' complete
complete-files () { compadd - $PREFIX* }
Edit: Added $PREFIX
You can add those lines to your ~/.zshrc file.
That makes the completion list all files when you press Ctrl-x Tab at each step instead of Tab. You could choose another keystroke combination that suits you.
Or to make ImageMagick completions always include all files, try editing (make a backup first) the file /usr/share/zsh/functions/Completion/Unix/_imagemagick (or similar) and change this to comment out the existing line that begins with _files and add the new one shown:
if (( $# )); then
# _files "$#" -g "*.(#i)(${~formats//:/|})(-.)"
_files "$#"
return
fi
Dennis' answer didn't expand tilde for me, so I would get stuff like complete-files: no matches found: ~/ma* when I tried to invoke it on foo ~/ma. I did find an alternate in the zsh FAQ that will expand them, though:
zle -C complete-file complete-word _generic
zstyle ':completion:complete-file::::' completer _files
bindkey '^xF' complete-file