zsh-workers
 help / color / mirror / code / Atom feed
From: Roman Perepelitsa <roman.perepelitsa@gmail.com>
To: dana <dana@dana.is>
Cc: Daniel Shahaf <d.s@daniel.shahaf.name>,
	Zsh hackers list <zsh-workers@zsh.org>
Subject: Re: Official plugin manager?
Date: Sat, 4 Jan 2020 16:46:17 +0100	[thread overview]
Message-ID: <CAN=4vMqm8kLXNjCSoqRnKFo+1tOkEXr9cHJc3CenLUoL9Fk_aw@mail.gmail.com> (raw)
In-Reply-To: <DA9882E9-D7B0-444B-82AE-EA1FE6F1294C@dana.is>

On Sat, Jan 4, 2020 at 1:40 AM dana <dana@dana.is> wrote:
> Actually, if key bindings don't always work well out of the box, and
> especially if we can fix that by simply checking terminfo, shouldn't we do
> that with the default bindings in the shell itself?

If keys such as arrows, home, end and delete just worked, this would be perfect!

My comment presupposed the existing zsh, which requires a few bindkey
commands to make these keys work. The use of terminfo here results in
brittle code. Let me show what I mean.

${terminfo[khome]} expands to the escape sequence for the home key.
Let's try using it:

    autoload -Uz terminfo
    bindkey ${terminfo[khome]} beginning-of-line

Doesn't work. Zsh puts terminal in raw mode (rmkx) when it starts but
${terminfo[khome]} is the escape key for application mode (smkx).
Let's manually switch terminal to application mode.

    echoti smkx

This works. Until we run an application that switches terminal back to
raw mode. To solve this problem we can hook zle-line-init and switch
to application mode from there.

    function zle-line-init () { echoti smkx; }
    zle -N zle-line-init

It's what Debian does. And Oh My Zsh. And Prezto. This works. Until we
source a plugin before setting up bindings and the plugin happens to
hook zle-line-init. Our zle-line-init overrides the plugin's, breaking
it in the process. Let's fix it by calling the plugin's hook from
ours.

    zle -A zle-line-init orig-zle-line-init

    function my-zle-line-init () {
      zle orig-zle-line-init
      echoti smkx
    }

    zle -N zle-line-init my-zle-line-init

This works. Until we source a plugin after setting up bindings and the
plugin happens to hook zle-line-init without calling our hook. This
time it's the plugin breaking our code rather than vise versa.

The alternative to this rather complex and brittle approach is to bind
beginning-of-line to several escape sequences.

    bindkey '^[[H' beginning-of-line  # home in raw mode
    bindkey '^[OH' beginning-of-line  # home in app mode

To avoid having to specify bindings several times, we can translate
escape sequences from application mode to their counterparts in raw
mode, and bind all keys as if the terminal was always in raw mode.

    # Translate application mode (smkx) key escape codes,
    # to raw mode (rmkx).
    bindkey -s '^[OH' '^[[H'  # home
    bindkey -s '^[OF' '^[[F'  # end
    # etc

    bindkey '^[[H' beginning-of-line  # home
    bindkey '^[[F' end-of-line  # end
    # etc

The same approach works with terminals of different type:

    # TTY sends different key codes. Translate them to regular.
    bindkey -s '^[[1~' '^[[H'  # home
    bindkey -s '^[[4~' '^[[F'  # end

And NumLock:

    # If NumLock is off, translate keys to make them appear
    # the same as with NumLock on.
    bindkey -s '^[OM' '^M'  # enter
    bindkey -s '^[Ok' '+'
    bindkey -s '^[Om' '-'
    bindkey -s '^[Oj' '*'
    bindkey -s '^[Oo' '/'
    bindkey -s '^[OX' '='

This makes keys such as `/` and `+` on the numpad work in zsh the same
way they work everywhere else.

The downside of such shotgun-type translation is the possibility of
clashes. It's possible in theory that one terminal's escape code for
the home key is another terminal's code for the end key. This can be
dealt with with some conditionals. I don't have any in my own zshrc as
none of the terminals I use produce clashes on any key sequences. I
imagine not everyone is so lucky.

> Obviously we shouldn't go crazy with it, but i don't see any reason to
> specifically limit the use of styles. The style system is an important aspect
> of configuring zsh. There are very useful settings that can only be changed
> that way, and it's important for users to know about it if they want to make
> their own changes.

Oh yeah, I've nothing against styles. I wanted (but failed) to make a
point that the basic config shouldn't attempt to provide the best
possible shell experience at the expense of config complexity. If 12
completion style lines give you only slightly better completion that 2
lines, it may be preferable to go with 2 lines. When the user's
complexity threshold is exceeded by the config, the whole thing
becomes opaque. A slightly worse but simpler config may result in
better long term user experience as the user will be able to customize
it.

Roman.

  parent reply	other threads:[~2020-01-04 15:47 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-02  3:17 Sebastian Gniazdowski
2020-01-02  4:28 ` Eric Cook
2020-01-02 11:03 ` Daniel Shahaf
2020-01-02 11:37   ` Sebastian Gniazdowski
2020-01-02 11:55     ` Sebastian Gniazdowski
2020-01-02 21:30     ` dana
2020-01-03  0:25       ` Sebastian Gniazdowski
2020-01-03  1:36         ` dana
2020-01-03  2:43           ` Sebastian Gniazdowski
2020-01-03  2:45           ` Bart Schaefer
2020-01-03  3:26             ` dana
2020-01-03  5:13               ` Sebastian Gniazdowski
2020-01-03 15:00               ` Peter Stephenson
2020-01-03 20:48                 ` Daniel Shahaf
2020-01-03 21:51                   ` Roman Perepelitsa
2020-01-03 22:06                     ` Daniel Shahaf
2020-01-03 22:26                       ` Bart Schaefer
2020-01-03 22:37                       ` Roman Perepelitsa
2020-01-04  0:42                         ` dana
2020-01-04  1:06                           ` Daniel Shahaf
2020-01-04 15:46                           ` Roman Perepelitsa [this message]
2020-01-04 16:27                             ` Daniel Shahaf
2020-01-04 16:41                               ` Roman Perepelitsa
2020-01-04 17:35                                 ` Daniel Shahaf
2020-01-04 17:42                                   ` Roman Perepelitsa
2020-01-04 17:11                             ` Bart Schaefer
2020-01-05 10:40                               ` Oliver Kiddle
2020-01-06 17:47                   ` Leah Neukirchen
2020-01-03 11:15             ` Oliver Kiddle
2020-01-04  5:16               ` Sebastian Gniazdowski
2020-01-04  6:00                 ` Sebastian Gniazdowski
2020-01-02 12:00   ` Roman Perepelitsa
2020-01-02 12:21     ` Sebastian Gniazdowski
2020-01-02 12:27       ` Roman Perepelitsa

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAN=4vMqm8kLXNjCSoqRnKFo+1tOkEXr9cHJc3CenLUoL9Fk_aw@mail.gmail.com' \
    --to=roman.perepelitsa@gmail.com \
    --cc=d.s@daniel.shahaf.name \
    --cc=dana@dana.is \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).