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

Re: History Up key



Andrej Borsenkow wrote:
>I believe, change was deliberate, but I forgot the reasons ... it was really
>long time - I think over three years.

It changed early in the 3.1 series.  It was part of the overhaul of the
key binding system.  Until 3.0, the vi insert and command mode keymaps
were only separate for single-character bindings; multi-character
bindings were shared.  Actually, multi-character bindings were broken,
because they were tied into the single-character keybinding tables in
a messy way and the bindkey code didn't take account of the multiple
tables when updating them.

I was a little disappointed, at the time, at the conservative decision
not to retrofit the new keymaps into 3.0, thus leaving stable-version
users with a broken mechanism for all this time.  Of course, the people
most likely to be inventing new multi-character bindings are Emacs-mode
users, and they don't have a problem because they only use the one keymap.
Indeed, I don't recall us ever receiving a bug report relating to the
multi-character keybinding mechanism.

The separation of keymaps for multi-character keybindings brought up,
for the first time, the question of how arrow keys should behave in vi
insert mode.  For a combination of reasons, which I shall outline here,
I decided that arrow keys should not be treated specially, and that is
the behaviour of zsh prior to this week's proposed patches.

My decision to not treat arrow keys specially was influenced by two
classes of issue: firstly utility, and secondly correctness of emulation.
The correctness of emulation issue was simply that my policy has been
that zsh's vi mode should emulate vi as closely as feasible, and, as
I'm a vi purist, that means the historical vi.  (Although I'd be open
to changing the undo/redo semantics to match nvi's behaviour; anyone
fancy writing nvi-undo-change and nvi-repeat-change?)

Moving around during an insertion is, of course, a meaningless idea
in vi; every vi clone that does it actually does a horrible kludge.
ZLE's architecture is such that it's more sensible -- it's the structure
of vi insertions that is done in a kludgy way -- but accurate cloning
still suggests that vi mode should stick to what's sensible in vi.

The utility issue is essentially the result of all the trouble I've
had with vi clones that try to handle arrow keys during insertion.
There are three main problems:

1.  On many terminals, arrow keys aren't proper keys -- they send a
    sequence of characters starting with <esc>.  The problem is that <esc>
    *is* a proper key, and it's a valid thing to type during insertion --
    it delimits the end of the insertion.  This means that, for example,
    on the terminal I'm using now, vi and zsh (and any other program)
    can't tell the difference between me typing <up-arrow> and me typing
    <esc>OA (or <esc>[A depending on context, but that's another story).
    When I'm inserting, <esc>OA is a perfectly meaningful thing to type.
    So there's ambiguity, and attempts to reconstruct the original intent
    (which keys I pressed) sometimes go wrong.

1a. Incidentally, one of the main (flawed) techniques used to try to
    determine whether an arrow key is actually being pressed is to pause
    after reading <esc> and only interpret <esc>OA (or whatever) as an
    arrow key if the characters come quickly enough.  I find the pause
    when I'm typing <esc> annoying.

2.  On some terminals, arrow keys don't send escape sequences, but instead
    send single control characters.  For example, my favourite type of
    glass tty, the ADM3e, send ^H for <left-arrow>, ^J for <down-arrow>,
    ^K for <up-arrow> and ^L for <right-arrow>.  This kind of aliasing
    isn't a problem for <esc> -- that alias is well-established so
    everything knows to treat ^[ as <esc>.  But anything that tries to
    handle arrow keys on this kind of terminal ends up breaking various
    control characters (unless there's no way you'd want to use those
    control characters at the time).  Particularly problematic is that
    <left-arrow> often ends up being aliased with <backspace>.

3.  Another problem with programs that adapt to the key sequences that
    terminfo reports is that it becomes difficult to programmatically
    turn off the automatic key bindings for arrow keys, which I usually
    want to do where possible because of the problems already noted.
    It's difficult to remove a key binding that isn't always on the
    same keys.

All of this suggests that:

A.  It would be a bad idea to have arrow keys bound by default in vi
    insert mode.  Emacs mode and vi command mode don't have the same
    problems, because <esc> itself isn't bound to anything in those
    keymaps.

B.  Adapting the arrow key sequences to the local terminal is problematic.
    Binding things like ^H as arrow key sequences will cause big problems,
    so at minimum terminals where arrow keys don't send escape sequences
    should be treated as having no arrow keys.  With that heuristic in
    place, the only problem with adaption is the issue of programmatically
    knowing where those bindings are.

C.  The documentation should contain advice on how to turn *on* key
    bindings for arrow keys in vi insert mode.  This avoids the issue
    of difficulty in turning off the bindings.

-zefram



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