суббота, 8 февраля 2014 г.

Fixing Ctrl-Home, Ctrl-End, Shift-Home, and Shift-End shortcuts in Gnome Terminal in Ubuntu 13.04

Some time ago I decided that I needed a decent console text editor. This led me to create vim-for-human-beings. Of course, there were issues. One of those issues was caused by the fact that Gnome Terminal is based on VTE which has its own actions bound to Ctrl + Home, Ctrl + EndShift + Home, and Shift + End. Since I use these combinations to navigate to the beginning and to the end of the document and to select text to the beginning and to the end of the line, this VTE's behaviour was quite annoying. Being unable to work around the problem, I decided to patch VTE.

What I basically had to do was to follow the Classic instructions from this answer. I changed them for my particular case.

Note: The instructions below are based on Ubuntu 13.04, which I have at hand, but I suppose they can be applied, probably with some minor alterations, to other versions of the distro.

There are two libvte* packages in Ubuntu 13.04. So first of all, I had to find out which one Gnome Terminal depends on:
$ apt-cache depends gnome-terminal | grep libvte
The required version was libvte-2.90-9. I downloaded the source code:
$ apt-get source libvte-2.90-9
Then I modified it:
$ cd vte3-0.34.2 
$ vim src/vte.c
Here I had to find the unwanted shortcuts, they followed after this comment:
/* Keypad/motion keys. */
So I just removed everything up to the next comment:
/* Let Shift +/- tweak the font, like XTerm does. */
It turned out that removing these shortcuts was not enough because of this VTE's bug. So I applied the patch mentioned in the comments to the bug:
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -284,6 +284,8 @@ static const struct _vte_keymap_entry _vte_keymap_GDK_Home[] = {
  {cursor_all, keypad_all, fkey_vt220, 0, _VTE_CAP_CSI "1~", -1, X_NULL},
  {cursor_all, keypad_all, fkey_hp, 0, _VTE_CAP_ESC "h", -1, X_NULL},
  {cursor_all, keypad_all, fkey_nothpvt, 0, X_NULL, 0, "kh"},
+ {cursor_default, keypad_all, fkey_default, 0, _VTE_CAP_CSI "H", -1, X_NULL},
+ {cursor_app, keypad_all, fkey_default, 0, _VTE_CAP_SS3 "H", -1, X_NULL},
  {cursor_all, keypad_all, fkey_all, 0, X_NULL, 0, X_NULL},
 };

@@ -291,6 +293,8 @@ static const struct _vte_keymap_entry _vte_keymap_GDK_End[] = {
  {cursor_all, keypad_all, fkey_all, 0, X_NULL, 0, "@7"},
  {cursor_all, keypad_all, fkey_vt220, 0, _VTE_CAP_CSI "4~", -1, X_NULL},
  {cursor_all, keypad_all, fkey_notvt220, 0, X_NULL, 0, "@7"},
+ {cursor_default, keypad_all, fkey_default, 0, _VTE_CAP_CSI "F", -1, X_NULL},
+ {cursor_app, keypad_all, fkey_default, 0, _VTE_CAP_SS3 "F", -1, X_NULL},
  {cursor_all, keypad_all, fkey_all, 0, X_NULL, 0, X_NULL},
 };

@@ -507,6 +511,8 @@ static const struct _vte_keymap_entry _vte_keymap_GDK_KP_End[] = {
  {cursor_all, keypad_default, fkey_vt220, 0, "1", 1, X_NULL},
  {cursor_all, keypad_app, fkey_notvt220, 0, _VTE_CAP_CSI "4~", -1, X_NULL},
  {cursor_all, keypad_app, fkey_vt220, 0, _VTE_CAP_SS3 "q", -1, X_NULL},
+ {cursor_default, keypad_all, fkey_default, 0, _VTE_CAP_CSI "F", -1, X_NULL},
+ {cursor_app, keypad_all, fkey_default, 0, _VTE_CAP_SS3 "F", -1, X_NULL},
  {cursor_all, keypad_all, fkey_all, 0, X_NULL, 0, X_NULL},
 };

@@ -568,6 +574,8 @@ static const struct _vte_keymap_entry _vte_keymap_GDK_KP_Home[] = {
  {cursor_all, keypad_default, fkey_vt220, 0, "7", 1, X_NULL},
  {cursor_all, keypad_app, fkey_notvt220, 0, _VTE_CAP_CSI "1~", -1, X_NULL},
  {cursor_all, keypad_app, fkey_vt220, 0, _VTE_CAP_SS3 "w", -1, X_NULL},
+ {cursor_default, keypad_all, fkey_default, 0, _VTE_CAP_CSI "H", -1, X_NULL},
+ {cursor_app, keypad_all, fkey_default, 0, _VTE_CAP_SS3 "H", -1, X_NULL},
  {cursor_all, keypad_all, fkey_all, 0, X_NULL, 0, X_NULL},
 };

@@ -1279,6 +1287,8 @@ _vte_keymap_key_get_modifier_encoding_method(guint keyval)
  case GDK_KEY (Right):
  case GDK_KEY (Insert):
  case GDK_KEY (Delete):
+ case GDK_KEY (Home):
+ case GDK_KEY (End):
  case GDK_KEY (Page_Up):
  case GDK_KEY (Page_Down):
  case GDK_KEY (KP_Up):
@@ -1287,6 +1297,8 @@ _vte_keymap_key_get_modifier_encoding_method(guint keyval)
  case GDK_KEY (KP_Right):
  case GDK_KEY (KP_Insert):
  case GDK_KEY (KP_Delete):
+ case GDK_KEY (KP_Home):
+ case GDK_KEY (KP_End):
  case GDK_KEY (KP_Page_Up):
  case GDK_KEY (KP_Page_Down):
  case GDK_KEY (F1):
There were no conflicts.

Then I rebuilt the package:
$ sudo apt-get build-dep libvte-2.90-9
$ dch -i # here I updated the version to 
0.34.2-customized-0ubuntu3
$ debuild -us -uc -b
And installed it:
$ cd ..
$ sudo dpkg -i libvte-2.90-common_0.34.2-customized-0ubuntu3_all.deb
$ sudo dpkg -i libvte-2.90-9_0.34.2-customized-0ubuntu3_amd64.deb
Although it was enough to install these two packages to fix the problem, I installed all the others that were generated by the debuild command as well.

After restarting Gnome Terminal, Ctrl + HomeCtrl + EndShift + Home, and Shift + End started working as expected.

3 комментария: