I recently upgraded KDE Plasma to v6, got ZSH instead of BASH in it and because I like some of its smart completion features and such, I decided to try to learn working with it. But I have a hard time getting used to it as a decades long BASH user. Maybe I'm searching wrong but I can't figure out how to configure some basic stuff that I find convenient in BASH.
I'm having the following troubles:
<ALT+.>
(ALT+period) in BASH invokes the last word from the previous command. E.g., I dols file.txt <ENTER>
, thencat <ALT+.>
and I getcat file.txt
. The caret (cursor) is after the word inserted by the key combo. This doesn't work for me in ZSH. I can do!$<TAB>
instead of<ALT+.>
but that's not too convenient. I also have working solution written by GPT but it throws me an error even tho it works. See my.zshrc
below. I have also found this question—vi mode - How to useAlt + .
in zsh with Vim bindings - Unix & Linux Stack Exchange—where I learned I can use<ALT>+_
but that's not exactly comfortable either for two reasons: Firstly, underscore is bound to<SHIFT>+-
on US and CZ keyboards which I use (so it's actually uncomfortable<ALT>+<SHIFT>+-
combo which has the potential to change keyboard layout with<ALT>+<SHIFT>
), and secondly, it produces the same error "No such shell function insert-last-word" as the binding I already have. I triedappend-last-word
instead which doesn't work at all.<HOME>
and<END>
to jump to the start/end of the current line. I can do <CTRL+A>/<CTRL+E> to do the start/end jumps but that's not exactly convenient either.I have there working binding to use
<ALT>+LEFT/WRITE_ARROW
to jump by words. However, this doesn't seem to respect$WORDCHARS
, e.g., if there's a path (includes/
), it jumps over it as a whole. What may I be doing wrong? My$WORDCHARS
:
$ echo $WORDCHARS
*?_-.[]~=/&;!#$%^(){}<>
- Edit: one more thing: I just installed a package (
sudo pacman -S hdparm
successfully. And right after that, when I try to invoke the command, I typehdpar<TAB>
, expecting to get thehdparm
auto-completed. Nope, I get various completely random suggestions (cdparanoia gdparttopng
), none of them beinghdparm
. When I type the command in full, though, it works, so that means it is a valid command. Do I need to run some completion update? :o (sorry, confused and slightly disillusioned).
I found that bindkey -e # Use emacs key bindings
brings some things to life, such as <CTRL+R>
for reverse search. But not all of them, see my biggest pains above.
Here's the config I have in ~/.zshrc
: (I'm posting it in its entirety but everything below line 52 is out of this question's scope, it works fine and is unrelated.) Please see the comments in the file for explanations of what doesn't work and how
# The following lines were added by compinstall
zstyle ':completion:*' completer _expand _complete _ignored _approximate
zstyle ':completion:*' format 'Completing %d'
zstyle ':completion:*' list-colors ''
zstyle ':completion:*' matcher-list '' 'm:{[:lower:]}={[:upper:]}' 'm:{[:lower:][:upper:]}={[:upper:][:lower:]}' 'r:|[._-]=** r:|=** l:|=*'
zstyle ':completion:*' menu select=2
zstyle ':completion:*' select-prompt %SScrolling active: current selection at %p%s
zstyle ':completion:*' use-compctl true
zstyle :compinstall filename '/home/edison23/.zshrc'
autoload -Uz compinit
compinit
# End of lines added by compinstall
# Lines configured by zsh-newuser-install
HISTFILE=~/.bash_history
HISTSIZE=1000000
SAVEHIST=1000000
unsetopt autocd
bindkey -v
# End of lines configured by zsh-newuser-install
#PS1='%d $ '
autoload -U colors && colors
PS1="%{$fg[red]%}%n%{$reset_color%}@%{$fg[blue]%}%m %{$fg[yellow]%}%~ %{$reset_color%}$ "
# Set key bindings to emulate Bash behavior
bindkey -e # Use emacs key bindings
# Should bind <ALT+.> to inserting last word but it works only for the last word of *the same command*,
# e.g. `cat foo; echo bar; cat <alt+.>` gives me `cat foo` instead of `cat bar`. Not desired.
# bindkey '^[.' history-beginning-search-backward
# This works but throws "No such shell function `insert-last-word'" error at the same time which is annoying, to say the least.
# Define the widget
zle -N insert-last-word
# Bind the widget to Alt + .
bindkey '^[.' insert-last-word
# Move to the beginning and end of the line using Home and End keys
# Doesn't work at all
bindkey 'Home' beginning-of-line # Home key to go to the start of the line
bindkey 'End' end-of-line # End key to go to the end of the line
# Move by words using <ALT+LEFT/RIGHT> (works)
# TODO: Any option to customize word delimiters?
bindkey "^[[1;3C" forward-word
bindkey "^[[1;3D" backward-word
# Everything below is fine and of no relation to the question posted on SO
# ls aliases
alias ll='ls -la -v --time-style=posix-long-iso --group-directories-first --color=always'
alias la='ls -A'
alias l='ls -CF'
#ls hidden files, no sorting
alias ls='ls -v --color="auto" --time-style=posix-long-iso --group-directories-first'
# CRC32 into filename
# rhash required, I think
alias embedcrc32='rhash -e --embed-crc-delimiter="."'
# Copy node path
# Use `| xsel -bi` on X11
fpath() {
echo -n `readlink -f "${1}"` | wl-copy
}
# color diff
alias dwdiff_rw='dwdiff -P -cred,green -A best -w [- -x -] -y {+ -z +}'
Thank you very much for your time, help, and patience with a ZSH newbie. Any bonus useful tips and tricks appreciated as well :)
1 Answer 1
Emacs vs vi bindings
Both bash and zsh give you a choice of vi-like or emacs-like bindings, with emacs being the default. In zsh, unlike bash, if the VISUAL
or EDITOR
environment variables are set to anything that contains vi
then zsh turns on vi-like bindings. In zsh, many useful commands only have a default binding in emacs mode. Put bindkey -e
in your .zshrc
to use emacs-like bindings regardless of the contents of those variables.
Insert last word
Alt+. to insert the last shell word of the previous command works out of the box in zsh just like bash.
written by GPT
That's your problem.
Looking in your configuration file, I see you've tried to make it work differently, but I'm not sure what you wanted to achieve. If you want something different from ksh/bash/zsh's Alt+., I suggest you ask a new question here.
bindkey '^[.' insert-last-word
is already the default setting. You're getting an error message because of zle -N insert-last-word
: that defines insert-last-word
as a widget (i.e. something that can be bound to a key) which invokes the function of the same name. But there is no function by that name. insert-last-word
already exists as a built-in widget.
Zsh has some useful related commands which are not bound by default.
copy-prev-shell-word
copies a word from the same command line. You get the last word by default, or the nth earlier word with a numeric argument (e.g.ESC 2 ESC +
to copy the next-to-last word if you've bound the command withbindkey '^[+' copy-prev-shell-word
).copy-earlier-word
extendsinsert-last-word
with a facility to get a word other than the last one. This one is a loadable function, so you need to load it, then make a widget for it and then you can bind it to a key.autoload -U copy-earlier-word zle -N copy-earlier-word bindkey '^[,' copy-earlier-word
Cursor motion keys
See Home key not working in terminal
Word motion
forward-word
and such does respect WORDCHARS
. If you want word motion to stop at slashes, remove /
from $WORDCHARS
.
If you'd like more flexibility, zsh ships with a word-style widget set. It makes word motion obey the current word style, with a widget select-word-style
to change that. You can also bind keys to word motion commands with a specific word style.
Cache of completions
Both bash and zsh maintain a cache of the locations of commands in the search path ($PATH
). In both shells, if you install a new executable earlier in the path than an existing one with the same name, the shell will remember the old location until you tell it to update the cache with the hash
command.
In zsh, annoyingly, negative results are also cached. So if you install a new executable, you need to tell zsh to reload the list of commands with rehash
or hash -rf
.
Zsh tips for a bash convert
- Zsh's default configuration is very barebones — it's basically unchanged from over 30 years ago.
zsh-newuser-install
gives you a few basics but there is much more that's available if you only know where to find it. There are a few zsh configuration management frameworks that activate features in batches and give you easy access to third-party plugins. Their downside is that instead of trying to understand zsh, you end up trying to understand that framework and zsh. YMMV. - What are the practical differences between Bash and Zsh?
- Why zsh is cooler than your shell
- Import bash history to zsh
-
Copying Kali Linux's
.zshrc
gives a nice look. gitlab.com/kalilinux/packages/kali-defaults/-/blob/…horsey_guy– horsey_guy2025年07月14日 23:34:39 +00:00Commented Jul 14 at 23:34 -
Sorry for the late accept of your answer Thank you very much for your time and the links, context and all. BTW yes, you were right I screwed up the configuration in the first place. Nonetheless, the info you gave helps with other things I had no idea about.edison23– edison232025年07月24日 17:25:47 +00:00Commented Jul 24 at 17:25
bash
features instead ofzsh
feature why usezsh
at all?exec bash
or for a stronger fixchsh /bin/bash