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.000004
First Submitted: 2015-08-06 05:38 (UTC)
Last Updated: 2024-01-29 09:26 (UTC)

Dependencies (6)

Required by (5)

Sources (2)

Latest Comments

1 2 3 4 5 6 Next › Last »

cipher699 commented on 2025-01-29 13:07 (UTC)

The '/' search breaks due to these keybinds. I am thinking of how to fixing it.

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;