Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: [PATCH] Bind quasi-default Home, End and Delete keys in built-in keymaps
- X-seq: zsh-workers 40174
- From: Teubel György <tgyurci@xxxxxxxxx>
- To: zsh-workers@xxxxxxx
- Subject: Re: [PATCH] Bind quasi-default Home, End and Delete keys in built-in keymaps
- Date: Tue, 13 Dec 2016 11:36:54 +0100
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=TKETJ59J8B0xhNci58EL1G6g4mmnKZDXYUR/sXhVC4c=; b=kxd7LKAFQOLA0KAJPs8hZelFKV3JDANFhQQiJUAKnDAiUz3x7PltK8cSd4i4eQ3fAe 6CSfXPn/E6syW6ycgFIrlQ2UD8aVZemMWh2992Ie/dIrs0bUG+woMWPpkfSnaq0i9gH7 +NZ/zP1Nh5PBI9v2cPbJ1ABBO8rR44FHPtVax0BSF17wKTmBJ66tTtcyBz7bZ9Rs4dx4 qe7BIfwOKLSqbfai/1YkRArhQPS7faUAzue/a+phMxOBofxGoYH7NTMOzseUi65TdHz7 CcVf3RJwIYUp5aqjWavLed4XOS02r6v1i7p5EaETcMsG8lMcauTpxdAAgT5IZ+4F0QQ3 9m1w==
- In-reply-to: <87a8c07h42.fsf@ft.bewatermyfriend.org>
- List-help: <mailto:zsh-workers-help@zsh.org>
- List-id: Zsh Workers List <zsh-workers.zsh.org>
- List-post: <mailto:zsh-workers@zsh.org>
- Mailing-list: contact zsh-workers-help@xxxxxxx; run by ezmlm
- References: <20161212153933.4619-1-tgyurci@gmail.com> <87a8c07h42.fsf@ft.bewatermyfriend.org>
On Tue, Dec 13, 2016 at 02:27:57AM +0100, Frank Terbeck wrote:
> Teubel György wrote:
> > Make Home, End and Delete keys work by default as expected by most users.
> [...]
> > +item(tt(beginning-of-line) (tt(^A) tt(ESC-[1~)) (unbound) (unbound))(
>
> Unfortunately, it's not that easy. Those special keys are not stable,
> even across a small sample of terminals and terminal emulators. You'd
> have to take a look at termcap or terminfo to get a reasonably well
> founded escape sequence for them, which also requires the terminal to be
> in smkx mode, while the line editor is active.
You are right, it should be done by querying termcap capabilities. Here is a
modified version of the patch. I used a tighter version of the add_cursor_key()
function. In addition, the Insert key is bound to 'vi-insert' in vi command mode.
> Zsh does have a terminfo module and it can be used to set up some well
> known special keys. But those are best added to a global configuration
> file, rather than being hard coded in C. This is what Debian does¹ for
> example.
I know that there is a terminfo (and a termcap) module. The difference is that
when it is in the default bindings (as the arrow keys are, for example), then these
keys work out of the box, without additional configuration. This increases user
experience a bit.
> Regards, Frank
---
Doc/Zsh/zle.yo | 14 +++++++-------
Src/Zle/zle_keymap.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
Src/init.c | 3 ++-
Src/zsh.h | 6 +++++-
4 files changed, 59 insertions(+), 11 deletions(-)
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index d68365b94..18a73b416 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -1231,12 +1231,12 @@ item(tt(vi-backward-word-end) (unbound) (tt(ge)) (unbound))(
Move to the end of the previous word, vi-style.
)
tindex(beginning-of-line)
-item(tt(beginning-of-line) (tt(^A)) (unbound) (unbound))(
+item(tt(beginning-of-line) (tt(^A) tt(HOME)) (unbound) (unbound))(
Move to the beginning of the line. If already at the beginning
of the line, move to the beginning of the previous line, if any.
)
tindex(vi-beginning-of-line)
-item(tt(vi-beginning-of-line))(
+item(tt(vi-beginning-of-line) (unbound) (tt(HOME)) (tt(HOME)))(
Move to the beginning of the line, without changing lines.
)
tindex(down-line)
@@ -1244,12 +1244,12 @@ item(tt(down-line) (unbound) (unbound) (unbound))(
Move down a line in the buffer.
)
tindex(end-of-line)
-item(tt(end-of-line) (tt(^E)) (unbound) (unbound))(
+item(tt(end-of-line) (tt(^E) tt(END)) (unbound) (unbound))(
Move to the end of the line. If already at the end
of the line, move to the end of the next line, if any.
)
tindex(vi-end-of-line)
-item(tt(vi-end-of-line) (unbound) (tt($)) (unbound))(
+item(tt(vi-end-of-line) (unbound) (tt($) tt(END)) (tt(END)))(
Move to the end of the line.
If an argument is given to this command, the cursor will be moved to
the end of the line (argument - 1) lines down.
@@ -1778,11 +1778,11 @@ from the cursor position to the endpoint of the movement.
If the command is tt(vi-delete), kill the current line.
)
tindex(delete-char)
-item(tt(delete-char))(
+item(tt(delete-char) (tt(DELETE)) (unbound) (unbound))(
Delete the character under the cursor.
)
tindex(vi-delete-char)
-item(tt(vi-delete-char) (unbound) (tt(x)) (unbound))(
+item(tt(vi-delete-char) (unbound) (tt(x) tt(DELETE)) (tt(DELETE)))(
Delete the character under the cursor,
without going past the end of the line.
)
@@ -1814,7 +1814,7 @@ item(tt(vi-indent) (unbound) (tt(>)) (unbound))(
Indent a number of lines.
)
tindex(vi-insert)
-item(tt(vi-insert) (unbound) (tt(i)) (unbound))(
+item(tt(vi-insert) (unbound) (tt(i) tt(INSERT)) (unbound))(
Enter insert mode.
)
tindex(vi-insert-bol)
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index 04eb70675..c6b6bdc0a 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -1280,6 +1280,38 @@ add_cursor_key(Keymap km, int tccode, Thingy thingy, int defchar)
}
}
+/* interrogate termcap for special keys and add binding to keymap */
+
+/**/
+static void
+bind_termcap_key(Keymap km, int tccode, Thingy thingy)
+{
+ char buf[2048];
+
+ /*
+ * Be careful not to try too hard with bindings for dubious or
+ * dysfunctional terminals.
+ */
+ if (tccan(tccode) && !(termflags & (TERM_NOUP|TERM_BAD|TERM_UNKNOWN))) {
+ /*
+ * We can use the real termcap sequence. We need to
+ * persuade termcap to output `move cursor 1 char' and capture it.
+ */
+ cursorptr = buf;
+ tputs(tcstr[tccode], 1, add_cursor_char);
+ *cursorptr = '\0';
+
+ /*
+ * Sanity checking. If the key is zero-length (unlikely,
+ * but this is termcap we're talking about), or it's a single
+ * character, then we don't bind it.
+ */
+ if (buf[0] && buf[1] && (buf[0] != Meta || buf[2])) {
+ bindkey(km, buf, refthingy(thingy), NULL);
+ }
+ }
+}
+
/* Create the default keymaps. For efficiency reasons, this function *
* assigns directly to the km->first array. It knows that there are no *
* prefix bindings in the way, and that it is using a simple keymap. */
@@ -1342,12 +1374,20 @@ default_bindings(void)
vimaps[1] = amap;
for (i = 0; i < 2; i++) {
kptr = vimaps[i];
- /* vi command and insert modes: arrow keys */
+ /* vi command and insert modes: arrow keys,
+ * home, end and delete */
add_cursor_key(kptr, TCUPCURSOR, t_uplineorhistory, 'A');
add_cursor_key(kptr, TCDOWNCURSOR, t_downlineorhistory, 'B');
add_cursor_key(kptr, TCLEFTCURSOR, t_vibackwardchar, 'D');
add_cursor_key(kptr, TCRIGHTCURSOR, t_viforwardchar, 'C');
+ bind_termcap_key(kptr, TCHOMEKEY, refthingy(t_vibeginningofline));
+ bind_termcap_key(kptr, TCENDKEY, refthingy(t_viendofline));
+ bind_termcap_key(kptr, TCDELETEKEY, refthingy(t_videletechar));
}
+
+ /* Insert key enters insert mode */
+ bind_termcap_key(amap, TCINSERTKEY, refthingy(t_viinsert));
+
vilmaps[0] = oppmap;
vilmaps[1] = vismap;
for (i = 0; i < 2; i++) {
@@ -1386,11 +1426,14 @@ default_bindings(void)
bindkey(amap, "guu", NULL, "gugu");
bindkey(amap, "gUU", NULL, "gUgU");
- /* emacs mode: arrow keys */
+ /* emacs mode: arrow keys, home, end and delete */
add_cursor_key(emap, TCUPCURSOR, t_uplineorhistory, 'A');
add_cursor_key(emap, TCDOWNCURSOR, t_downlineorhistory, 'B');
add_cursor_key(emap, TCLEFTCURSOR, t_backwardchar, 'D');
add_cursor_key(emap, TCRIGHTCURSOR, t_forwardchar, 'C');
+ bind_termcap_key(emap, TCHOMEKEY, refthingy(t_beginningofline));
+ bind_termcap_key(emap, TCENDKEY, refthingy(t_endofline));
+ bind_termcap_key(emap, TCDELETEKEY, refthingy(t_deletechar));
/* emacs mode: ^X sequences */
bindkey(emap, "\30*", refthingy(t_expandword), NULL);
diff --git a/Src/init.c b/Src/init.c
index c12043b88..7b632394e 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -670,7 +670,8 @@ static char *tccapnams[TC_COUNT] = {
"cl", "le", "LE", "nd", "RI", "up", "UP", "do",
"DO", "dc", "DC", "ic", "IC", "cd", "ce", "al", "dl", "ta",
"md", "so", "us", "me", "se", "ue", "ch",
- "ku", "kd", "kl", "kr", "sc", "rc", "bc", "AF", "AB"
+ "ku", "kd", "kl", "kr", "sc", "rc", "bc", "AF", "AB",
+ "kh", "@7", "kD", "kI"
};
/**/
diff --git a/Src/zsh.h b/Src/zsh.h
index f22d8b135..6f6544d09 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -2524,7 +2524,11 @@ struct ttyinfo {
#define TCBACKSPACE 31
#define TCFGCOLOUR 32
#define TCBGCOLOUR 33
-#define TC_COUNT 34
+#define TCHOMEKEY 34
+#define TCENDKEY 35
+#define TCDELETEKEY 36
+#define TCINSERTKEY 37
+#define TC_COUNT 38
#define tccan(X) (tclen[X])
--
2.11.0
Messages sorted by:
Reverse Date,
Date,
Thread,
Author