Package Details: htop-vim-git 1:3.3.0.20.g32cb3027-1

Git Clone URL: https://aur.archlinux.org/htop-vim-git.git (read-only, click to copy)
Package Base: htop-vim-git
Description: Interactive text-mode process viewer. Patched for vim keybindings
Upstream URL: https://github.com/htop-dev/htop
Licenses: GPL
Conflicts: htop, htop-git
Provides: htop
Submitter: KoffeinFlummi
Maintainer: KoffeinFlummi
Last Packager: KoffeinFlummi
Votes: 24
Popularity: 0.003161
First Submitted: 2015-08-06 05:38 (UTC)
Last Updated: 2024-01-29 09:26 (UTC)

Dependencies (6)

Required by (4)

Sources (2)

Latest Comments

1 2 3 4 5 6 Next › Last »

cipher699 commented on 2022-10-16 10:43 (UTC)


index 6e905ce9..3cac0734 100644
--- a/CategoriesPanel.c
+++ b/CategoriesPanel.c
@@ -103,6 +103,14 @@ static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
    HandlerResult result = IGNORED;

    int selected = Panel_getSelectedIndex(super);
+
+   switch (ch) {
+      case 'k': ch = KEY_UP; break;
+      case 'j': ch = KEY_DOWN; break;
+      case 'h': ch = KEY_LEFT; break;
+      case 'l': ch = KEY_RIGHT; break;
+   }
+
    switch (ch) {
       case EVENT_SET_SELECTED:
          result = HANDLED;
diff --git a/MainPanel.c b/MainPanel.c
index 44915dfd..47477886 100644
--- a/MainPanel.c
+++ b/MainPanel.c
@@ -51,7 +51,7 @@ static const char* MainPanel_getValue(Panel* this, int i) {
    return Process_getCommand(p);
 }

-static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
+HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
    MainPanel* this = (MainPanel*) super;

    HandlerResult result = IGNORED;
diff --git a/MainPanel.h b/MainPanel.h
index bd22acd0..069d0b34 100644
--- a/MainPanel.h
+++ b/MainPanel.h
@@ -47,4 +47,6 @@ void MainPanel_setState(MainPanel* this, State* state);

 void MainPanel_delete(Object* object);

+HandlerResult MainPanel_eventHandler(Panel* super, int ch);
+
 #endif
diff --git a/Panel.c b/Panel.c
index 4ea03f66..5c60d2bd 100644
--- a/Panel.c
+++ b/Panel.c
@@ -358,6 +358,7 @@ bool Panel_onKey(Panel* this, int key) {

    switch (key) {
    case KEY_DOWN:
+   case 'j':
    case KEY_CTRL('N'):
    #ifdef KEY_C_DOWN
    case KEY_C_DOWN:
@@ -366,6 +367,7 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_UP:
+   case 'k':
    case KEY_CTRL('P'):
    #ifdef KEY_C_UP
    case KEY_C_UP:
@@ -374,7 +376,7 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_LEFT:
-   case KEY_CTRL('B'):
+   case 'h':
       if (this->scrollH > 0) {
          this->scrollH -= MAXIMUM(CRT_scrollHAmount, 0);
          this->needsRedraw = true;
@@ -382,16 +384,27 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_RIGHT:
-   case KEY_CTRL('F'):
+   case 'l':
       this->scrollH += CRT_scrollHAmount;
       this->needsRedraw = true;
       break;

+   case KEY_CTRL('U'):
+      this->selected -= (this->h - 1) / 2;
+      this->needsRedraw = true;
+      break;
+   case KEY_CTRL('D'):
+      this->selected += (this->h - 1) / 2;
+      this->needsRedraw = true;
+      break;
+
    case KEY_PPAGE:
+   case KEY_CTRL('B'):
       PANEL_SCROLL(-(this->h - Panel_headerHeight(this)));
       break;

    case KEY_NPAGE:
+   case KEY_CTRL('F'):
       PANEL_SCROLL(+(this->h - Panel_headerHeight(this)));
       break;

@@ -404,10 +417,12 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_HOME:
+   case 'g':
       this->selected = 0;
       break;

    case KEY_END:
+   case 'G':
       this->selected = size - 1;
       break;

diff --git a/README b/README
index 55372b43..574ee1bb 100644
--- a/README
+++ b/README
@@ -21,6 +21,48 @@ The information displayed is configurable through a graphical setup and can be s

 Tasks related to processes (e.g. killing and renicing) can be done without entering their PIDs.

+Vim keybindings
+----------------
+
+These are the keybindings added in this fork of htop:
+
+```
+    g        to the top (gg in vim)
+
+  <C-b>      up 1 page
+
+  <C-u>      up 1/2 page
+
+    k
+
+h       l    one character
+
+    j
+
+  <C-d>      down 1/2 page
+
+  <C-f>      down 1 page
+
+    G        to the end
+
+--------------------------------------------------
+
+    o        Expand/collapse (like in NERDTree)
+```
+
+In order to accomodate these keybindings, the following changes
+were made to the original keybindings:
+
+* Ctrl+F and Ctrt+B can no longer be used to navigate horizontally
+* 'h' can no longer be used to access the help, leaving Ctrl+F1 & '?'
+* 'k' can no longer be used to kill processes, being replaced with 'x'
+* 'l' can no longer be used to list open files, being replaced with 'L'
+* 'x' can no longer be used to list file locks, being replaced with 'X'
+
+
+Comparison between `htop` and classic `top`
+-------------------------------------------
+
 Running `htop` requires `ncurses` libraries, typically named libncurses(w).

 `htop` is written in C.
diff --git a/ScreenManager.c b/ScreenManager.c
index e4b04bd3..735d7a23 100644
--- a/ScreenManager.c
+++ b/ScreenManager.c
@@ -17,6 +17,7 @@ in the source distribution for its full text.
 #include "CRT.h"
 #include "FunctionBar.h"
 #include "Macros.h"
+#include "MainPanel.h"
 #include "Object.h"
 #include "Platform.h"
 #include "ProcessList.h"
@@ -294,14 +295,16 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey, con
          redraw = false;
          continue;
       }
-      switch (ch) {
-         case KEY_ALT('H'): ch = KEY_LEFT; break;
-         case KEY_ALT('J'): ch = KEY_DOWN; break;
-         case KEY_ALT('K'): ch = KEY_UP; break;
-         case KEY_ALT('L'): ch = KEY_RIGHT; break;
-      }
       redraw = true;
       if (Panel_eventHandlerFn(panelFocus)) {
+         if (Panel_eventHandlerFn(panelFocus) != MainPanel_eventHandler) {
+            switch (ch) {
+               case 'h': case KEY_ALT('H'): ch = KEY_LEFT; break;
+               case 'j': case KEY_ALT('J'): ch = KEY_DOWN; break;
+               case 'k': case KEY_ALT('K'): ch = KEY_UP; break;
+               case 'l': case KEY_ALT('L'): ch = KEY_RIGHT; break;
+            }
+         }
          result = Panel_eventHandler(panelFocus, ch);
       }
       if (result & SYNTH_KEY) {
@@ -335,7 +338,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey, con
          continue;
       }
       case KEY_LEFT:
-      case KEY_CTRL('B'):
+      case 'h':
          if (this->panelCount < 2) {
             goto defaultHandler;
          }
@@ -356,7 +359,7 @@ tryLeft:

          break;
       case KEY_RIGHT:
-      case KEY_CTRL('F'):
+      case 'l':
       case 9:
          if (this->panelCount < 2) {
             goto defaultHandler;
diff --git a/Action.c b/Action.c
index 1007be2f..e34959f9 100644
--- a/Action.c
+++ b/Action.c
@@ -515,7 +515,7 @@ static const struct {
    const char* info;
 } helpLeft[] = {
    { .key = "    Tab: ",  .roInactive = false, .info = "switch to next screen tab" },
-   { .key = " Arrows: ",  .roInactive = false, .info = "scroll process list" },
+   { .key = "   hjkl: ",  .roInactive = false, .info = "scroll process list" },
    { .key = " Digits: ",  .roInactive = false, .info = "incremental PID search" },
    { .key = "   F3 /: ",  .roInactive = false, .info = "incremental name search" },
    { .key = "   F4 \\: ", .roInactive = false, .info = "incremental name filtering" },
@@ -543,7 +543,7 @@ static const struct {
    { .key = "  Space: ", .roInactive = false, .info = "tag process" },
    { .key = "      c: ", .roInactive = false, .info = "tag process and its children" },
    { .key = "      U: ", .roInactive = false, .info = "untag all processes" },
-   { .key = "   F9 k: ", .roInactive = true,  .info = "kill process/tagged processes" },
+   { .key = "   F9 x: ", .roInactive = true,  .info = "kill process/tagged processes" },
    { .key = "   F7 ]: ", .roInactive = true,  .info = "higher priority (root only)" },
    { .key = "   F8 [: ", .roInactive = true,  .info = "lower priority (+ nice)" },
 #if (defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY))
@@ -551,12 +551,12 @@ static const struct {
 #endif
    { .key = "      e: ", .roInactive = false, .info = "show process environment" },
    { .key = "      i: ", .roInactive = true,  .info = "set IO priority" },
-   { .key = "      l: ", .roInactive = true,  .info = "list open files with lsof" },
-   { .key = "      x: ", .roInactive = false, .info = "list file locks of process" },
+   { .key = "      L: ", .roInactive = true,  .info = "list open files with lsof" },
+   { .key = "      X: ", .roInactive = false, .info = "list file locks of process" },
    { .key = "      s: ", .roInactive = true,  .info = "trace syscalls with strace" },
    { .key = "      w: ", .roInactive = false, .info = "wrap process command in multiple lines" },
    { .key = " F2 C S: ", .roInactive = false, .info = "setup" },
-   { .key = " F1 h ?: ", .roInactive = false, .info = "show this help screen" },
+   { .key = "   F1 ?: ", .roInactive = false, .info = "show this help screen" },
    { .key = "  F10 q: ", .roInactive = false, .info = "quit" },
    { .key = NULL, .info = NULL }
 };
@@ -755,6 +755,7 @@ void Action_setBindings(Htop_Action* keys) {
    keys['H'] = actionToggleUserlandThreads;
    keys['I'] = actionInvertSortOrder;
    keys['K'] = actionToggleKernelThreads;
+   keys['L'] = actionLsof;
    keys['M'] = actionSortByMemory;
    keys['N'] = actionSortByPID;
    keys['O'] = actionToggleRunningInContainer;
@@ -762,6 +763,7 @@ void Action_setBindings(Htop_Action* keys) {
    keys['S'] = actionSetup;
    keys['T'] = actionSortByTime;
    keys['U'] = actionUntagAll;
+   keys['X'] = actionShowLocks;
    keys['Z'] = actionTogglePauseProcessUpdate;
    keys['['] = actionLowerPriority;
    keys['\014'] = actionRedraw; // Ctrl+L
@@ -771,9 +773,6 @@ void Action_setBindings(Htop_Action* keys) {
    keys['a'] = actionSetAffinity;
    keys['c'] = actionTagAllChildren;
    keys['e'] = actionShowEnvScreen;
-   keys['h'] = actionHelp;
-   keys['k'] = actionKill;
-   keys['l'] = actionLsof;
    keys['m'] = actionToggleMergedCommand;
    keys['p'] = actionToggleProgramPath;
    keys['q'] = actionQuit;
@@ -781,7 +780,7 @@ void Action_setBindings(Htop_Action* keys) {
    keys['t'] = actionToggleTreeView;
    keys['u'] = actionFilterByUser;
    keys['w'] = actionShowCommandScreen;
-   keys['x'] = actionShowLocks;
+   keys['x'] = actionKill;
    keys[KEY_F(1)] = actionHelp;
    keys[KEY_F(2)] = actionSetup;
    keys[KEY_F(3)] = actionIncSearch;
@@ -793,6 +792,7 @@ void Action_setBindings(Htop_Action* keys) {
    keys[KEY_F(9)] = actionKill;
    keys[KEY_F(10)] = actionQuit;
    keys[KEY_F(18)] = actionExpandCollapseOrSortColumn;
+   keys['o'] = actionExpandCollapseOrSortColumn;
    keys[KEY_RECLICK] = actionExpandOrCollapse;
    keys[KEY_SHIFT_TAB] = actionPrevScreen;
    keys['\t'] = actionNextScreen;

cipher699 commented on 2022-09-19 16:30 (UTC)



diff --git a/CategoriesPanel.c b/CategoriesPanel.c
index 6e905ce9..3cac0734 100644
--- a/CategoriesPanel.c
+++ b/CategoriesPanel.c
@@ -103,6 +103,14 @@ static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
    HandlerResult result = IGNORED;

    int selected = Panel_getSelectedIndex(super);
+
+   switch (ch) {
+      case 'k': ch = KEY_UP; break;
+      case 'j': ch = KEY_DOWN; break;
+      case 'h': ch = KEY_LEFT; break;
+      case 'l': ch = KEY_RIGHT; break;
+   }
+
    switch (ch) {
       case EVENT_SET_SELECTED:
          result = HANDLED;
diff --git a/MainPanel.c b/MainPanel.c
index 44915dfd..47477886 100644
--- a/MainPanel.c
+++ b/MainPanel.c
@@ -51,7 +51,7 @@ static const char* MainPanel_getValue(Panel* this, int i) {
    return Process_getCommand(p);
 }

-static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
+HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
    MainPanel* this = (MainPanel*) super;

    HandlerResult result = IGNORED;
diff --git a/MainPanel.h b/MainPanel.h
index bd22acd0..069d0b34 100644
--- a/MainPanel.h
+++ b/MainPanel.h
@@ -47,4 +47,6 @@ void MainPanel_setState(MainPanel* this, State* state);

 void MainPanel_delete(Object* object);

+HandlerResult MainPanel_eventHandler(Panel* super, int ch);
+
 #endif
diff --git a/Panel.c b/Panel.c
index 4ea03f66..5c60d2bd 100644
--- a/Panel.c
+++ b/Panel.c
@@ -358,6 +358,7 @@ bool Panel_onKey(Panel* this, int key) {

    switch (key) {
    case KEY_DOWN:
+   case 'j':
    case KEY_CTRL('N'):
    #ifdef KEY_C_DOWN
    case KEY_C_DOWN:
@@ -366,6 +367,7 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_UP:
+   case 'k':
    case KEY_CTRL('P'):
    #ifdef KEY_C_UP
    case KEY_C_UP:
@@ -374,7 +376,7 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_LEFT:
-   case KEY_CTRL('B'):
+   case 'h':
       if (this->scrollH > 0) {
          this->scrollH -= MAXIMUM(CRT_scrollHAmount, 0);
          this->needsRedraw = true;
@@ -382,16 +384,27 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_RIGHT:
-   case KEY_CTRL('F'):
+   case 'l':
       this->scrollH += CRT_scrollHAmount;
       this->needsRedraw = true;
       break;

+   case KEY_CTRL('U'):
+      this->selected -= (this->h - 1) / 2;
+      this->needsRedraw = true;
+      break;
+   case KEY_CTRL('D'):
+      this->selected += (this->h - 1) / 2;
+      this->needsRedraw = true;
+      break;
+
    case KEY_PPAGE:
+   case KEY_CTRL('B'):
       PANEL_SCROLL(-(this->h - Panel_headerHeight(this)));
       break;

    case KEY_NPAGE:
+   case KEY_CTRL('F'):
       PANEL_SCROLL(+(this->h - Panel_headerHeight(this)));
       break;

@@ -404,10 +417,12 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_HOME:
+   case 'g':
       this->selected = 0;
       break;

    case KEY_END:
+   case 'G':
       this->selected = size - 1;
       break;

diff --git a/README b/README
index 55372b43..574ee1bb 100644
--- a/README
+++ b/README
@@ -21,6 +21,48 @@ The information displayed is configurable through a graphical setup and can be s

 Tasks related to processes (e.g. killing and renicing) can be done without entering their PIDs.

+Vim keybindings
+----------------
+
+These are the keybindings added in this fork of htop:
+
+```
+    g        to the top (gg in vim)
+
+  <C-b>      up 1 page
+
+  <C-u>      up 1/2 page
+
+    k
+
+h       l    one character
+
+    j
+
+  <C-d>      down 1/2 page
+
+  <C-f>      down 1 page
+
+    G        to the end
+
+--------------------------------------------------
+
+    o        Expand/collapse (like in NERDTree)
+```
+
+In order to accomodate these keybindings, the following changes
+were made to the original keybindings:
+
+* Ctrl+F and Ctrt+B can no longer be used to navigate horizontally
+* 'h' can no longer be used to access the help, leaving Ctrl+F1 & '?'
+* 'k' can no longer be used to kill processes, being replaced with 'x'
+* 'l' can no longer be used to list open files, being replaced with 'L'
+* 'x' can no longer be used to list file locks, being replaced with 'X'
+
+
+Comparison between `htop` and classic `top`
+-------------------------------------------
+
 Running `htop` requires `ncurses` libraries, typically named libncurses(w).

 `htop` is written in C.
diff --git a/ScreenManager.c b/ScreenManager.c
index e4b04bd3..735d7a23 100644
--- a/ScreenManager.c
+++ b/ScreenManager.c
@@ -17,6 +17,7 @@ in the source distribution for its full text.
 #include "CRT.h"
 #include "FunctionBar.h"
 #include "Macros.h"
+#include "MainPanel.h"
 #include "Object.h"
 #include "Platform.h"
 #include "ProcessList.h"
@@ -294,14 +295,16 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey, con
          redraw = false;
          continue;
       }
-      switch (ch) {
-         case KEY_ALT('H'): ch = KEY_LEFT; break;
-         case KEY_ALT('J'): ch = KEY_DOWN; break;
-         case KEY_ALT('K'): ch = KEY_UP; break;
-         case KEY_ALT('L'): ch = KEY_RIGHT; break;
-      }
       redraw = true;
       if (Panel_eventHandlerFn(panelFocus)) {
+         if (Panel_eventHandlerFn(panelFocus) != MainPanel_eventHandler) {
+            switch (ch) {
+               case 'h': case KEY_ALT('H'): ch = KEY_LEFT; break;
+               case 'j': case KEY_ALT('J'): ch = KEY_DOWN; break;
+               case 'k': case KEY_ALT('K'): ch = KEY_UP; break;
+               case 'l': case KEY_ALT('L'): ch = KEY_RIGHT; break;
+            }
+         }
          result = Panel_eventHandler(panelFocus, ch);
       }
       if (result & SYNTH_KEY) {
@@ -335,7 +338,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey, con
          continue;
       }
       case KEY_LEFT:
-      case KEY_CTRL('B'):
+      case 'h':
          if (this->panelCount < 2) {
             goto defaultHandler;
          }
@@ -356,7 +359,7 @@ tryLeft:

          break;
       case KEY_RIGHT:
-      case KEY_CTRL('F'):
+      case 'l':
       case 9:
          if (this->panelCount < 2) {
             goto defaultHandler;
diff --git a/Action.c b/Action.c
index 1007be2f..e34959f9 100644
--- a/Action.c
+++ b/Action.c
@@ -515,7 +515,7 @@ static const struct {
    const char* info;
 } helpLeft[] = {
    { .key = "    Tab: ",  .roInactive = false, .info = "switch to next screen tab" },
-   { .key = " Arrows: ",  .roInactive = false, .info = "scroll process list" },
+   { .key = "   hjkl: ",  .roInactive = false, .info = "scroll process list" },
    { .key = " Digits: ",  .roInactive = false, .info = "incremental PID search" },
    { .key = "   F3 /: ",  .roInactive = false, .info = "incremental name search" },
    { .key = "   F4 \\: ", .roInactive = false, .info = "incremental name filtering" },
@@ -543,7 +543,7 @@ static const struct {
    { .key = "  Space: ", .roInactive = false, .info = "tag process" },
    { .key = "      c: ", .roInactive = false, .info = "tag process and its children" },
    { .key = "      U: ", .roInactive = false, .info = "untag all processes" },
-   { .key = "   F9 k: ", .roInactive = true,  .info = "kill process/tagged processes" },
+   { .key = "   F9 x: ", .roInactive = true,  .info = "kill process/tagged processes" },
    { .key = "   F7 ]: ", .roInactive = true,  .info = "higher priority (root only)" },
    { .key = "   F8 [: ", .roInactive = true,  .info = "lower priority (+ nice)" },
 #if (defined(HAVE_LIBHWLOC) || defined(HAVE_AFFINITY))
@@ -551,12 +551,12 @@ static const struct {
 #endif
    { .key = "      e: ", .roInactive = false, .info = "show process environment" },
    { .key = "      i: ", .roInactive = true,  .info = "set IO priority" },
-   { .key = "      l: ", .roInactive = true,  .info = "list open files with lsof" },
-   { .key = "      x: ", .roInactive = false, .info = "list file locks of process" },
+   { .key = "      L: ", .roInactive = true,  .info = "list open files with lsof" },
+   { .key = "      X: ", .roInactive = false, .info = "list file locks of process" },
    { .key = "      s: ", .roInactive = true,  .info = "trace syscalls with strace" },
    { .key = "      w: ", .roInactive = false, .info = "wrap process command in multiple lines" },
    { .key = " F2 C S: ", .roInactive = false, .info = "setup" },
-   { .key = " F1 h ?: ", .roInactive = false, .info = "show this help screen" },
+   { .key = "   F1 ?: ", .roInactive = false, .info = "show this help screen" },
    { .key = "  F10 q: ", .roInactive = false, .info = "quit" },
    { .key = NULL, .info = NULL }
 };
@@ -755,6 +755,7 @@ void Action_setBindings(Htop_Action* keys) {
    keys['H'] = actionToggleUserlandThreads;
    keys['I'] = actionInvertSortOrder;
    keys['K'] = actionToggleKernelThreads;
+   keys['L'] = actionLsof;
    keys['M'] = actionSortByMemory;
    keys['N'] = actionSortByPID;
    keys['O'] = actionToggleRunningInContainer;
@@ -762,6 +763,7 @@ void Action_setBindings(Htop_Action* keys) {
    keys['S'] = actionSetup;
    keys['T'] = actionSortByTime;
    keys['U'] = actionUntagAll;
+   keys['X'] = actionShowLocks;
    keys['Z'] = actionTogglePauseProcessUpdate;
    keys['['] = actionLowerPriority;
    keys['\014'] = actionRedraw; // Ctrl+L
@@ -771,9 +773,6 @@ void Action_setBindings(Htop_Action* keys) {
    keys['a'] = actionSetAffinity;
    keys['c'] = actionTagAllChildren;
    keys['e'] = actionShowEnvScreen;
-   keys['h'] = actionHelp;
-   keys['k'] = actionKill;
-   keys['l'] = actionLsof;
    keys['m'] = actionToggleMergedCommand;
    keys['p'] = actionToggleProgramPath;
    keys['q'] = actionQuit;
@@ -781,7 +780,7 @@ void Action_setBindings(Htop_Action* keys) {
    keys['t'] = actionToggleTreeView;
    keys['u'] = actionFilterByUser;
    keys['w'] = actionShowCommandScreen;
-   keys['x'] = actionShowLocks;
+   keys['x'] = actionKill;
    keys[KEY_F(1)] = actionHelp;
    keys[KEY_F(2)] = actionSetup;
    keys[KEY_F(3)] = actionIncSearch;
@@ -793,6 +792,7 @@ void Action_setBindings(Htop_Action* keys) {
    keys[KEY_F(9)] = actionKill;
    keys[KEY_F(10)] = actionQuit;
    keys[KEY_F(18)] = actionExpandCollapseOrSortColumn;
+   keys['o'] = actionExpandCollapseOrSortColumn;
    keys[KEY_RECLICK] = actionExpandOrCollapse;
    keys[KEY_SHIFT_TAB] = actionPrevScreen;
    keys['\t'] = actionNextScreen;







KoffeinFlummi commented on 2022-05-24 12:35 (UTC)

Patch should apply again.

jfamousket commented on 2022-01-03 13:24 (UTC)

vim-keybindings.patch

diff --git a/Action.c b/Action.c
index d6fd737..a9bd9cf 100644
--- a/Action.c
+++ b/Action.c
@@ -452,7 +452,7 @@ static const struct {
    bool roInactive;
    const char* info;
 } helpLeft[] = {
-   { .key = " Arrows: ",  .roInactive = false, .info = "scroll process list" },
+   { .key = "   hjkl: ",  .roInactive = false, .info = "scroll process list" },
    { .key = " Digits: ",  .roInactive = false, .info = "incremental PID search" },
    { .key = "   F3 /: ",  .roInactive = false, .info = "incremental name search" },
    { .key = "   F4 \\: ", .roInactive = false, .info = "incremental name filtering" },
@@ -479,7 +479,7 @@ static const struct {
    { .key = "  Space: ", .roInactive = false, .info = "tag process" },
    { .key = "      c: ", .roInactive = false, .info = "tag process and its children" },
    { .key = "      U: ", .roInactive = false, .info = "untag all processes" },
-   { .key = "   F9 k: ", .roInactive = true,  .info = "kill process/tagged processes" },
+   { .key = "   F9 x: ", .roInactive = true,  .info = "kill process/tagged processes" },
    { .key = "   F7 ]: ", .roInactive = true,  .info = "higher priority (root only)" },
    { .key = "   F8 [: ", .roInactive = false, .info = "lower priority (+ nice)" },
 #if (defined(HAVE_LIBHWLOC) || defined(HAVE_LINUX_AFFINITY))
@@ -487,12 +487,12 @@ static const struct {
 #endif
    { .key = "      e: ", .roInactive = false, .info = "show process environment" },
    { .key = "      i: ", .roInactive = true,  .info = "set IO priority" },
-   { .key = "      l: ", .roInactive = true,  .info = "list open files with lsof" },
-   { .key = "      x: ", .roInactive = false, .info = "list file locks of process" },
+   { .key = "      L: ", .roInactive = true,  .info = "list open files with lsof" },
+   { .key = "      X: ", .roInactive = false, .info = "list file locks of process" },
    { .key = "      s: ", .roInactive = true,  .info = "trace syscalls with strace" },
    { .key = "      w: ", .roInactive = false, .info = "wrap process command in multiple lines" },
    { .key = " F2 C S: ", .roInactive = false, .info = "setup" },
-   { .key = " F1 h ?: ", .roInactive = false, .info = "show this help screen" },
+   { .key = "   F1 ?: ", .roInactive = false, .info = "show this help screen" },
    { .key = "  F10 q: ", .roInactive = false, .info = "quit" },
    { .key = NULL, .info = NULL }
 };
@@ -666,12 +666,14 @@ void Action_setBindings(Htop_Action* keys) {
    keys['H'] = actionToggleUserlandThreads;
    keys['I'] = actionInvertSortOrder;
    keys['K'] = actionToggleKernelThreads;
+   keys['L'] = actionLsof;
    keys['M'] = actionSortByMemory;
    keys['N'] = actionSortByPID;
    keys['P'] = actionSortByCPU;
    keys['S'] = actionSetup;
    keys['T'] = actionSortByTime;
    keys['U'] = actionUntagAll;
+   keys['X'] = actionShowLocks;
    keys['Z'] = actionTogglePauseProcessUpdate;
    keys['['] = actionLowerPriority;
    keys['\014'] = actionRedraw; // Ctrl+L
@@ -681,9 +683,6 @@ void Action_setBindings(Htop_Action* keys) {
    keys['a'] = actionSetAffinity;
    keys['c'] = actionTagAllChildren;
    keys['e'] = actionShowEnvScreen;
-   keys['h'] = actionHelp;
-   keys['k'] = actionKill;
-   keys['l'] = actionLsof;
    keys['m'] = actionToggleMergedCommand;
    keys['p'] = actionToggleProgramPath;
    keys['q'] = actionQuit;
@@ -691,7 +690,7 @@ void Action_setBindings(Htop_Action* keys) {
    keys['t'] = actionToggleTreeView;
    keys['u'] = actionFilterByUser;
    keys['w'] = actionShowCommandScreen;
-   keys['x'] = actionShowLocks;
+   keys['x'] = actionKill;
    keys[KEY_F(1)] = actionHelp;
    keys[KEY_F(2)] = actionSetup;
    keys[KEY_F(3)] = actionIncSearch;
@@ -703,5 +702,6 @@ void Action_setBindings(Htop_Action* keys) {
    keys[KEY_F(9)] = actionKill;
    keys[KEY_F(10)] = actionQuit;
    keys[KEY_F(18)] = actionExpandCollapseOrSortColumn;
+   keys['o'] = actionExpandCollapseOrSortColumn;
    keys[KEY_RECLICK] = actionExpandOrCollapse;
 }
diff --git a/CategoriesPanel.c b/CategoriesPanel.c
index 4ee1ad4..43930da 100644
--- a/CategoriesPanel.c
+++ b/CategoriesPanel.c
@@ -67,6 +67,14 @@ static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
    HandlerResult result = IGNORED;

    int selected = Panel_getSelectedIndex(super);
+
+   switch (ch) {
+      case 'k': ch = KEY_UP; break;
+      case 'j': ch = KEY_DOWN; break;
+      case 'h': ch = KEY_LEFT; break;
+      case 'l': ch = KEY_RIGHT; break;
+   }
+
    switch (ch) {
       case EVENT_SET_SELECTED:
          result = HANDLED;
diff --git a/MainPanel.c b/MainPanel.c
index 5a75af3..48e6345 100644
--- a/MainPanel.c
+++ b/MainPanel.c
@@ -50,7 +50,7 @@ static const char* MainPanel_getValue(Panel* this, int i) {
    return Process_getCommand(p);
 }

-static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
+HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
    MainPanel* this = (MainPanel*) super;

    HandlerResult result = IGNORED;
diff --git a/MainPanel.h b/MainPanel.h
index 04f347d..6c8fd32 100644
--- a/MainPanel.h
+++ b/MainPanel.h
@@ -46,4 +46,6 @@ void MainPanel_setState(MainPanel* this, State* state);

 void MainPanel_delete(Object* object);

+HandlerResult MainPanel_eventHandler(Panel* super, int ch);
+
 #endif
diff --git a/Panel.c b/Panel.c
index 69933ae..98eb588 100644
--- a/Panel.c
+++ b/Panel.c
@@ -351,6 +351,7 @@ bool Panel_onKey(Panel* this, int key) {

    switch (key) {
    case KEY_DOWN:
+   case 'j':
    case KEY_CTRL('N'):
    #ifdef KEY_C_DOWN
    case KEY_C_DOWN:
@@ -359,6 +360,7 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_UP:
+   case 'k':
    case KEY_CTRL('P'):
    #ifdef KEY_C_UP
    case KEY_C_UP:
@@ -367,7 +369,7 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_LEFT:
-   case KEY_CTRL('B'):
+   case 'h':
       if (this->scrollH > 0) {
          this->scrollH -= MAXIMUM(CRT_scrollHAmount, 0);
          this->needsRedraw = true;
@@ -375,16 +377,27 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_RIGHT:
-   case KEY_CTRL('F'):
+   case 'l':
       this->scrollH += CRT_scrollHAmount;
       this->needsRedraw = true;
       break;

+   case KEY_CTRL('U'):
+      this->selected -= (this->h - 1) / 2;
+      this->needsRedraw = true;
+      break;
+   case KEY_CTRL('D'):
+      this->selected += (this->h - 1) / 2;
+      this->needsRedraw = true;
+      break;
+
    case KEY_PPAGE:
+   case KEY_CTRL('B'):
       PANEL_SCROLL(-(this->h - Panel_headerHeight(this)));
       break;

    case KEY_NPAGE:
+   case KEY_CTRL('F'):
       PANEL_SCROLL(+(this->h - Panel_headerHeight(this)));
       break;

@@ -397,10 +410,12 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_HOME:
+   case 'g':
       this->selected = 0;
       break;

    case KEY_END:
+   case 'G':
       this->selected = size - 1;
       break;

diff --git a/README b/README
index a9cb1df..e8723ec 100644
--- a/README
+++ b/README
@@ -21,6 +21,48 @@

 Tasks related to processes (e.g. killing and renicing) can be done without entering their PIDs.

+Vim keybindings
+----------------
+
+These are the keybindings added in this fork of htop:
+
+```
+    g        to the top (gg in vim)
+
+  <C-b>      up 1 page
+
+  <C-u>      up 1/2 page
+
+    k
+
+h       l    one character
+
+    j
+
+  <C-d>      down 1/2 page
+
+  <C-f>      down 1 page
+
+    G        to the end
+
+--------------------------------------------------
+
+    o        Expand/collapse (like in NERDTree)
+```
+
+In order to accomodate these keybindings, the following changes
+were made to the original keybindings:
+
+* Ctrl+F and Ctrt+B can no longer be used to navigate horizontally
+* 'h' can no longer be used to access the help, leaving Ctrl+F1 & '?'
+* 'k' can no longer be used to kill processes, being replaced with 'x'
+* 'l' can no longer be used to list open files, being replaced with 'L'
+* 'x' can no longer be used to list file locks, being replaced with 'X'
+
+
+Comparison between `htop` and classic `top`
+-------------------------------------------
+
 Running `htop` requires `ncurses` libraries, typically named libncurses(w).

 `htop` is written in C.
diff --git a/ScreenManager.c b/ScreenManager.c
index 6e7551f..27afda3 100644
--- a/ScreenManager.c
+++ b/ScreenManager.c
@@ -16,6 +16,7 @@

 #include "CRT.h"
 #include "FunctionBar.h"
+#include "MainPanel.h"
 #include "Macros.h"
 #include "Object.h"
 #include "Platform.h"
@@ -222,14 +223,16 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
          redraw = false;
          continue;
       }
-      switch (ch) {
-         case KEY_ALT('H'): ch = KEY_LEFT; break;
-         case KEY_ALT('J'): ch = KEY_DOWN; break;
-         case KEY_ALT('K'): ch = KEY_UP; break;
-         case KEY_ALT('L'): ch = KEY_RIGHT; break;
-      }
       redraw = true;
       if (Panel_eventHandlerFn(panelFocus)) {
+         if (Panel_eventHandlerFn(panelFocus) != MainPanel_eventHandler) {
+            switch (ch) {
+               case 'h': case KEY_ALT('H'): ch = KEY_LEFT; break;
+               case 'j': case KEY_ALT('J'): ch = KEY_DOWN; break;
+               case 'k': case KEY_ALT('K'): ch = KEY_UP; break;
+               case 'l': case KEY_ALT('L'): ch = KEY_RIGHT; break;
+            }
+         }
          result = Panel_eventHandler(panelFocus, ch);
       }
       if (result & SYNTH_KEY) {
@@ -259,7 +262,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
          continue;
       }
       case KEY_LEFT:
-      case KEY_CTRL('B'):
+      case 'h':
          if (this->panelCount < 2) {
             goto defaultHandler;
          }
@@ -280,7 +283,7 @@ tryLeft:

          break;
       case KEY_RIGHT:
-      case KEY_CTRL('F'):
+      case 'l':
       case 9:
          if (this->panelCount < 2) {
             goto defaultHandler;

KoffeinFlummi commented on 2021-10-11 22:12 (UTC)

Should be fixed.

kronikpillow commented on 2021-10-11 10:20 (UTC)

doesn't build

jfamousket commented on 2021-09-21 10:49 (UTC)

vim-keybindings.patch

diff --git a/Action.c b/Action.c
index d6fd737..a9bd9cf 100644
--- a/Action.c
+++ b/Action.c
@@ -452,7 +452,7 @@ static const struct {
    bool roInactive;
    const char* info;
 } helpLeft[] = {
-   { .key = " Arrows: ",  .roInactive = false, .info = "scroll process list" },
+   { .key = "   hjkl: ",  .roInactive = false, .info = "scroll process list" },
    { .key = " Digits: ",  .roInactive = false, .info = "incremental PID search" },
    { .key = "   F3 /: ",  .roInactive = false, .info = "incremental name search" },
    { .key = "   F4 \\: ", .roInactive = false, .info = "incremental name filtering" },
@@ -479,7 +479,7 @@ static const struct {
    { .key = "  Space: ", .roInactive = false, .info = "tag process" },
    { .key = "      c: ", .roInactive = false, .info = "tag process and its children" },
    { .key = "      U: ", .roInactive = false, .info = "untag all processes" },
-   { .key = "   F9 k: ", .roInactive = true,  .info = "kill process/tagged processes" },
+   { .key = "   F9 x: ", .roInactive = true,  .info = "kill process/tagged processes" },
    { .key = "   F7 ]: ", .roInactive = true,  .info = "higher priority (root only)" },
    { .key = "   F8 [: ", .roInactive = false, .info = "lower priority (+ nice)" },
 #if (defined(HAVE_LIBHWLOC) || defined(HAVE_LINUX_AFFINITY))
@@ -487,12 +487,12 @@ static const struct {
 #endif
    { .key = "      e: ", .roInactive = false, .info = "show process environment" },
    { .key = "      i: ", .roInactive = true,  .info = "set IO priority" },
-   { .key = "      l: ", .roInactive = true,  .info = "list open files with lsof" },
-   { .key = "      x: ", .roInactive = false, .info = "list file locks of process" },
+   { .key = "      L: ", .roInactive = true,  .info = "list open files with lsof" },
+   { .key = "      X: ", .roInactive = false, .info = "list file locks of process" },
    { .key = "      s: ", .roInactive = true,  .info = "trace syscalls with strace" },
    { .key = "      w: ", .roInactive = false, .info = "wrap process command in multiple lines" },
    { .key = " F2 C S: ", .roInactive = false, .info = "setup" },
-   { .key = " F1 h ?: ", .roInactive = false, .info = "show this help screen" },
+   { .key = "   F1 ?: ", .roInactive = false, .info = "show this help screen" },
    { .key = "  F10 q: ", .roInactive = false, .info = "quit" },
    { .key = NULL, .info = NULL }
 };
@@ -666,12 +666,14 @@ void Action_setBindings(Htop_Action* keys) {
    keys['H'] = actionToggleUserlandThreads;
    keys['I'] = actionInvertSortOrder;
    keys['K'] = actionToggleKernelThreads;
+   keys['L'] = actionLsof;
    keys['M'] = actionSortByMemory;
    keys['N'] = actionSortByPID;
    keys['P'] = actionSortByCPU;
    keys['S'] = actionSetup;
    keys['T'] = actionSortByTime;
    keys['U'] = actionUntagAll;
+   keys['X'] = actionShowLocks;
    keys['Z'] = actionTogglePauseProcessUpdate;
    keys['['] = actionLowerPriority;
    keys['\014'] = actionRedraw; // Ctrl+L
@@ -681,9 +683,6 @@ void Action_setBindings(Htop_Action* keys) {
    keys['a'] = actionSetAffinity;
    keys['c'] = actionTagAllChildren;
    keys['e'] = actionShowEnvScreen;
-   keys['h'] = actionHelp;
-   keys['k'] = actionKill;
-   keys['l'] = actionLsof;
    keys['m'] = actionToggleMergedCommand;
    keys['p'] = actionToggleProgramPath;
    keys['q'] = actionQuit;
@@ -691,7 +690,7 @@ void Action_setBindings(Htop_Action* keys) {
    keys['t'] = actionToggleTreeView;
    keys['u'] = actionFilterByUser;
    keys['w'] = actionShowCommandScreen;
-   keys['x'] = actionShowLocks;
+   keys['x'] = actionKill;
    keys[KEY_F(1)] = actionHelp;
    keys[KEY_F(2)] = actionSetup;
    keys[KEY_F(3)] = actionIncSearch;
@@ -703,5 +702,6 @@ void Action_setBindings(Htop_Action* keys) {
    keys[KEY_F(9)] = actionKill;
    keys[KEY_F(10)] = actionQuit;
    keys[KEY_F(18)] = actionExpandCollapseOrSortColumn;
+   keys['o'] = actionExpandCollapseOrSortColumn;
    keys[KEY_RECLICK] = actionExpandOrCollapse;
 }
diff --git a/CategoriesPanel.c b/CategoriesPanel.c
index 4ee1ad4..43930da 100644
--- a/CategoriesPanel.c
+++ b/CategoriesPanel.c
@@ -67,6 +67,14 @@ static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
    HandlerResult result = IGNORED;

    int selected = Panel_getSelectedIndex(super);
+
+   switch (ch) {
+      case 'k': ch = KEY_UP; break;
+      case 'j': ch = KEY_DOWN; break;
+      case 'h': ch = KEY_LEFT; break;
+      case 'l': ch = KEY_RIGHT; break;
+   }
+
    switch (ch) {
       case EVENT_SET_SELECTED:
          result = HANDLED;
diff --git a/MainPanel.c b/MainPanel.c
index 5a75af3..48e6345 100644
--- a/MainPanel.c
+++ b/MainPanel.c
@@ -50,7 +50,7 @@ static const char* MainPanel_getValue(Panel* this, int i) {
    return Process_getCommand(p);
 }

-static HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
+HandlerResult MainPanel_eventHandler(Panel* super, int ch) {
    MainPanel* this = (MainPanel*) super;

    HandlerResult result = IGNORED;
diff --git a/MainPanel.h b/MainPanel.h
index 04f347d..6c8fd32 100644
--- a/MainPanel.h
+++ b/MainPanel.h
@@ -46,4 +46,6 @@ void MainPanel_setState(MainPanel* this, State* state);

 void MainPanel_delete(Object* object);

+HandlerResult MainPanel_eventHandler(Panel* super, int ch);
+
 #endif
diff --git a/Panel.c b/Panel.c
index 69933ae..98eb588 100644
--- a/Panel.c
+++ b/Panel.c
@@ -351,6 +351,7 @@ bool Panel_onKey(Panel* this, int key) {

    switch (key) {
    case KEY_DOWN:
+   case 'j':
    case KEY_CTRL('N'):
    #ifdef KEY_C_DOWN
    case KEY_C_DOWN:
@@ -359,6 +360,7 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_UP:
+   case 'k':
    case KEY_CTRL('P'):
    #ifdef KEY_C_UP
    case KEY_C_UP:
@@ -367,7 +369,7 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_LEFT:
-   case KEY_CTRL('B'):
+   case 'h':
       if (this->scrollH > 0) {
          this->scrollH -= MAXIMUM(CRT_scrollHAmount, 0);
          this->needsRedraw = true;
@@ -375,16 +377,27 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_RIGHT:
-   case KEY_CTRL('F'):
+   case 'l':
       this->scrollH += CRT_scrollHAmount;
       this->needsRedraw = true;
       break;

+   case KEY_CTRL('U'):
+      this->selected -= (this->h - 1) / 2;
+      this->needsRedraw = true;
+      break;
+   case KEY_CTRL('D'):
+      this->selected += (this->h - 1) / 2;
+      this->needsRedraw = true;
+      break;
+
    case KEY_PPAGE:
+   case KEY_CTRL('B'):
       PANEL_SCROLL(-(this->h - Panel_headerHeight(this)));
       break;

    case KEY_NPAGE:
+   case KEY_CTRL('F'):
       PANEL_SCROLL(+(this->h - Panel_headerHeight(this)));
       break;

@@ -397,10 +410,12 @@ bool Panel_onKey(Panel* this, int key) {
       break;

    case KEY_HOME:
+   case 'g':
       this->selected = 0;
       break;

    case KEY_END:
+   case 'G':
       this->selected = size - 1;
       break;

diff --git a/README b/README
index a9cb1df..e8723ec 100644
--- a/README
+++ b/README
@@ -21,6 +21,48 @@

 Tasks related to processes (e.g. killing and renicing) can be done without entering their PIDs.

+Vim keybindings
+----------------
+
+These are the keybindings added in this fork of htop:
+
+```
+    g        to the top (gg in vim)
+
+  <C-b>      up 1 page
+
+  <C-u>      up 1/2 page
+
+    k
+
+h       l    one character
+
+    j
+
+  <C-d>      down 1/2 page
+
+  <C-f>      down 1 page
+
+    G        to the end
+
+--------------------------------------------------
+
+    o        Expand/collapse (like in NERDTree)
+```
+
+In order to accomodate these keybindings, the following changes
+were made to the original keybindings:
+
+* Ctrl+F and Ctrt+B can no longer be used to navigate horizontally
+* 'h' can no longer be used to access the help, leaving Ctrl+F1 & '?'
+* 'k' can no longer be used to kill processes, being replaced with 'x'
+* 'l' can no longer be used to list open files, being replaced with 'L'
+* 'x' can no longer be used to list file locks, being replaced with 'X'
+
+
+Comparison between `htop` and classic `top`
+-------------------------------------------
+
 Running `htop` requires `ncurses` libraries, typically named libncurses(w).

 `htop` is written in C.
diff --git a/ScreenManager.c b/ScreenManager.c
index 6e7551f..27afda3 100644
--- a/ScreenManager.c
+++ b/ScreenManager.c
@@ -14,6 +14,7 @@ in the source distribution for its full text.

 #include "CRT.h"
 #include "FunctionBar.h"
+#include "MainPanel.h"
 #include "Object.h"
 #include "Platform.h"
 #include "ProcessList.h"
@@ -222,14 +223,16 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
          redraw = false;
          continue;
       }
-      switch (ch) {
-         case KEY_ALT('H'): ch = KEY_LEFT; break;
-         case KEY_ALT('J'): ch = KEY_DOWN; break;
-         case KEY_ALT('K'): ch = KEY_UP; break;
-         case KEY_ALT('L'): ch = KEY_RIGHT; break;
-      }
       redraw = true;
       if (Panel_eventHandlerFn(panelFocus)) {
+         if (Panel_eventHandlerFn(panelFocus) != MainPanel_eventHandler) {
+            switch (ch) {
+               case 'h': case KEY_ALT('H'): ch = KEY_LEFT; break;
+               case 'j': case KEY_ALT('J'): ch = KEY_DOWN; break;
+               case 'k': case KEY_ALT('K'): ch = KEY_UP; break;
+               case 'l': case KEY_ALT('L'): ch = KEY_RIGHT; break;
+            }
+         }
          result = Panel_eventHandler(panelFocus, ch);
       }
       if (result & SYNTH_KEY) {
@@ -259,7 +262,7 @@ void ScreenManager_run(ScreenManager* this, Panel** lastFocus, int* lastKey) {
          continue;
       }
       case KEY_LEFT:
-      case KEY_CTRL('B'):
+      case 'h':
          if (this->panelCount < 2) {
             goto defaultHandler;
          }
@@ -280,7 +283,7 @@ tryLeft:

          break;
       case KEY_RIGHT:
-      case KEY_CTRL('F'):
+      case 'l':
       case 9:
          if (this->panelCount < 2) {
             goto defaultHandler;

KoffeinFlummi commented on 2021-05-01 12:13 (UTC)

Should be fixed, sorry for the delay.