View | Details | Raw Unified | Return to bug 256258 | Differences between
and this patch

Collapse All | Expand All

(-)b/sysutils/htop/Makefile (+3 lines)
Lines 14-19 LICENSE_FILE= ${WRKSRC}/COPYING Link Here
14
USES=		autoreconf compiler:c11 libtool localbase ncurses pkgconfig \
14
USES=		autoreconf compiler:c11 libtool localbase ncurses pkgconfig \
15
		python:build shebangfix
15
		python:build shebangfix
16
16
17
BUILD_DEPENDS+=	libgnuregex>=6.0:devel/libgnuregex
18
RUN_DEPENDS+=	${BUILD_DEPENDS}
19
17
USE_GITHUB=	yes
20
USE_GITHUB=	yes
18
GH_ACCOUNT=	htop-dev
21
GH_ACCOUNT=	htop-dev
19
22
(-)b/sysutils/htop/files/patch-Action.c (+14 lines)
Added Link Here
1
--- Action.c.orig	2021-01-11 17:18:21 UTC
2
+++ Action.c
3
@@ -236,9 +236,8 @@ static Htop_Reaction actionToggleTreeView(State* st) {
4
 }
5
 
6
 static Htop_Reaction actionIncFilter(State* st) {
7
-   IncSet* inc = ((MainPanel*)st->panel)->inc;
8
-   IncSet_activate(inc, INC_FILTER, st->panel);
9
-   st->pl->incFilter = IncSet_filter(inc);
10
+   st->pl->incSet = ((MainPanel*)st->panel)->inc;
11
+   IncSet_activate(st->pl->incSet, INC_FILTER, st->panel);
12
    return HTOP_REFRESH | HTOP_KEEP_FOLLOWING;
13
 }
14
 
(-)b/sysutils/htop/files/patch-IncSet.c (+176 lines)
Added Link Here
1
--- IncSet.c.orig	2021-01-11 17:18:21 UTC
2
+++ IncSet.c
3
@@ -12,6 +12,7 @@ in the source distribution for its full text.
4
 #include <ctype.h>
5
 #include <string.h>
6
 #include <stdlib.h>
7
+#include <gnu/regex.h>
8
 
9
 #include "CRT.h"
10
 #include "ListItem.h"
11
@@ -39,9 +40,11 @@ static inline void IncMode_initSearch(IncMode* search)
12
    search->isFilter = false;
13
 }
14
 
15
-static const char* const filterFunctions[] = {"Done  ", "Clear ", " Filter: ", NULL};
16
-static const char* const filterKeys[] = {"Enter", "Esc", "  "};
17
-static const int filterEvents[] = {13, 27, ERR};
18
+static const char* const filterFunctions[] = {"Done  ", "Clear ", "!Regexp ", "Filter Out ", " Filter: ", NULL};
19
+static const char* const filterKeys[] = {"Enter", "Esc",  "F5", "F6", "  "};
20
+static const char* regexLabels[] = {"Regexp  ", "!Regexp "};
21
+static const char* excludeLabels[] = {"Filter Out ", "Filter In  "};
22
+static const int filterEvents[] = {13, 27,  KEY_F(5), KEY_F(6), ERR};
23
 
24
 static inline void IncMode_initFilter(IncMode* filter) {
25
    memset(filter, 0, sizeof(IncMode));
26
@@ -61,24 +64,79 @@ IncSet* IncSet_new(FunctionBar* bar) {
27
    this->defaultBar = bar;
28
    this->filtering = false;
29
    this->found = false;
30
+   this->rawFilter = NULL;
31
+   this->regex = true;
32
+   this->exclude = false;
33
+   this->regexAlloc = false;
34
    return this;
35
 }
36
 
37
+static void freeFilter(IncSet* this);
38
+
39
 void IncSet_delete(IncSet* this) {
40
    IncMode_done(&(this->modes[0]));
41
    IncMode_done(&(this->modes[1]));
42
+   freeFilter(this);
43
    free(this);
44
 }
45
 
46
+
47
+static void updateBarLabels(IncSet* this) {
48
+   if (this->active == &(this->modes[INC_FILTER])) {
49
+      IncMode* filterMode = &(this->modes[INC_FILTER]);
50
+      FunctionBar_setLabel(filterMode->bar, KEY_F(5), regexLabels[this->regex ? 1 : 0]);
51
+      FunctionBar_setLabel(filterMode->bar, KEY_F(6), excludeLabels[this->exclude ? 1 : 0]);
52
+   }
53
+}
54
+
55
+static bool testWithFilter(IncSet* this, const char* testSubject) {
56
+   if (!this || !this->filtering) {
57
+      return true;
58
+   }
59
+   if (this->regexAlloc) {
60
+      return regexec(&this->regexFilter, testSubject, 0, NULL, 0) ? this->exclude : !this->exclude;
61
+   }
62
+   return  String_contains_i(testSubject, this->rawFilter ? this->rawFilter : "" ) ? !this->exclude : this->exclude;
63
+}
64
+
65
+bool IncSet_filterTest(IncSet* this, const char* str) {
66
+      return !this || !this->filtering || testWithFilter(this, str);
67
+}
68
+
69
+static void freeFilter(IncSet* this) {
70
+   if (this->regexAlloc) {
71
+      regfree(&this->regexFilter);
72
+      this->regexAlloc = false;
73
+   }
74
+   if (this->rawFilter) {
75
+      free(this->rawFilter);
76
+      this->rawFilter = NULL;
77
+   }
78
+}
79
+
80
+static void compileFilter(IncSet* this, const char* filterStr) {
81
+   if (this->rawFilter) {
82
+      freeFilter(this);
83
+   }
84
+   if (filterStr) {
85
+      this->rawFilter = xStrdup(filterStr);
86
+      if (this->regex) {
87
+         int result = regcomp(&this->regexFilter, this->rawFilter, REG_EXTENDED|REG_NOSUB|REG_ICASE);
88
+         if (!result) {
89
+            this->regexAlloc = true;
90
+         }
91
+      }
92
+   }
93
+}
94
+
95
 static void updateWeakPanel(IncSet* this, Panel* panel, Vector* lines) {
96
    Object* selected = Panel_getSelected(panel);
97
    Panel_prune(panel);
98
    if (this->filtering) {
99
       int n = 0;
100
-      const char* incFilter = this->modes[INC_FILTER].buffer;
101
       for (int i = 0; i < Vector_size(lines); i++) {
102
          ListItem* line = (ListItem*)Vector_get(lines, i);
103
-         if (String_contains_i(line->value, incFilter)) {
104
+         if (testWithFilter(this, line->value)) {
105
             Panel_add(panel, (Object*)line);
106
             if (selected == (Object*)line) {
107
                Panel_setSelected(panel, n);
108
@@ -98,10 +156,10 @@ static void updateWeakPanel(IncSet* this, Panel* panel
109
    }
110
 }
111
 
112
-static bool search(IncMode* mode, Panel* panel, IncMode_GetPanelValue getPanelValue) {
113
+static bool search(IncSet* this, Panel* panel, IncMode_GetPanelValue getPanelValue) {
114
    int size = Panel_size(panel);
115
    for (int i = 0; i < size; i++) {
116
-      if (String_contains_i(getPanelValue(panel, i), mode->buffer)) {
117
+      if (testWithFilter(this, getPanelValue(panel, i))) {
118
          Panel_setSelected(panel, i);
119
          return true;
120
       }
121
@@ -147,6 +205,18 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* pan
122
 
123
       IncMode_find(mode, panel, getPanelValue, ch == KEY_F(3) ? 1 : -1);
124
       doSearch = false;
125
+   } else if (ch == KEY_F(5)) {
126
+      if (mode->isFilter) {
127
+         filterChanged = true;
128
+         this->regex = !this->regex;
129
+         updateBarLabels(this);
130
+      }
131
+   } else if (ch == KEY_F(6)) {
132
+      if (mode->isFilter) {
133
+         filterChanged = true;
134
+         this->exclude = !this->exclude;
135
+         updateBarLabels(this);
136
+      }
137
    } else if (0 < ch && ch < 255 && isprint((unsigned char)ch)) {
138
       if (mode->index < INCMODE_MAX) {
139
          mode->buffer[mode->index] = ch;
140
@@ -167,6 +237,7 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* pan
141
             filterChanged = true;
142
             if (mode->index == 0) {
143
                this->filtering = false;
144
+               freeFilter(this);
145
                IncMode_reset(mode);
146
             }
147
          }
148
@@ -180,6 +251,7 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* pan
149
          filterChanged = true;
150
          if (ch == 27) {
151
             this->filtering = false;
152
+            freeFilter(this);
153
             IncMode_reset(mode);
154
          }
155
       } else {
156
@@ -191,8 +263,11 @@ bool IncSet_handleKey(IncSet* this, int ch, Panel* pan
157
       Panel_setDefaultBar(panel);
158
       doSearch = false;
159
    }
160
+   if (filterChanged) {
161
+      compileFilter(this, mode->buffer);
162
+   }
163
    if (doSearch) {
164
-      this->found = search(mode, panel, getPanelValue);
165
+      this->found = search(this, panel, getPanelValue);
166
    }
167
    if (filterChanged && lines) {
168
       updateWeakPanel(this, panel, lines);
169
@@ -207,6 +282,7 @@ const char* IncSet_getListItemValue(Panel* panel, int 
170
 
171
 void IncSet_activate(IncSet* this, IncType type, Panel* panel) {
172
    this->active = &(this->modes[type]);
173
+   updateBarLabels(this);
174
    panel->currentBar = this->active->bar;
175
 }
176
 
(-)b/sysutils/htop/files/patch-IncSet.h (+31 lines)
Added Link Here
1
--- IncSet.h.orig	2021-01-11 17:18:21 UTC
2
+++ IncSet.h
3
@@ -9,6 +9,7 @@ in the source distribution for its full text.
4
 
5
 #include <stdbool.h>
6
 #include <stddef.h>
7
+#include <gnu/regex.h>
8
 
9
 #include "FunctionBar.h"
10
 #include "Panel.h"
11
@@ -34,6 +35,11 @@ typedef struct IncSet_ {
12
    FunctionBar* defaultBar;
13
    bool filtering;
14
    bool found;
15
+   bool regex;
16
+   bool exclude;
17
+   bool regexAlloc;
18
+   char* rawFilter;
19
+   regex_t regexFilter;
20
 } IncSet;
21
 
22
 static inline const char* IncSet_filter(const IncSet* this) {
23
@@ -47,6 +53,8 @@ void IncSet_reset(IncSet* this, IncType type);
24
 IncSet* IncSet_new(FunctionBar* bar);
25
 
26
 void IncSet_delete(IncSet* this);
27
+
28
+bool IncSet_filterTest(IncSet* this, const char* str);
29
 
30
 bool IncSet_handleKey(IncSet* this, int ch, Panel* panel, IncMode_GetPanelValue getPanelValue, Vector* lines);
31
 
(-)b/sysutils/htop/files/patch-InfoScreen.c (+21 lines)
Added Link Here
1
--- InfoScreen.c.orig	2020-12-22 06:39:42 UTC
2
+++ InfoScreen.c
3
@@ -63,8 +63,7 @@ void InfoScreen_drawTitled(InfoScreen* this, const cha
4
 
5
 void InfoScreen_addLine(InfoScreen* this, const char* line) {
6
    Vector_add(this->lines, (Object*) ListItem_new(line, 0));
7
-   const char* incFilter = IncSet_filter(this->inc);
8
-   if (!incFilter || String_contains_i(line, incFilter)) {
9
+   if (IncSet_filterTest(this->inc, line)) {
10
       Panel_add(this->display, Vector_get(this->lines, Vector_size(this->lines) - 1));
11
    }
12
 }
13
@@ -73,7 +72,7 @@ void InfoScreen_appendLine(InfoScreen* this, const cha
14
    ListItem* last = (ListItem*)Vector_get(this->lines, Vector_size(this->lines) - 1);
15
    ListItem_append(last, line);
16
    const char* incFilter = IncSet_filter(this->inc);
17
-   if (incFilter && Panel_get(this->display, Panel_size(this->display) - 1) != (Object*)last && String_contains_i(line, incFilter)) {
18
+   if (incFilter && Panel_get(this->display, Panel_size(this->display) - 1) != (Object*)last && IncSet_filterTest(this->inc, line)) {
19
       Panel_add(this->display, (Object*)last);
20
    }
21
 }
(-)b/sysutils/htop/files/patch-MainPanel.c (+11 lines)
Added Link Here
1
--- MainPanel.c.orig	2020-12-22 06:39:42 UTC
2
+++ MainPanel.c
3
@@ -74,7 +74,7 @@ static HandlerResult MainPanel_eventHandler(Panel* sup
4
    } else if (ch != ERR && this->inc->active) {
5
       bool filterChanged = IncSet_handleKey(this->inc, ch, super, (IncMode_GetPanelValue) MainPanel_getValue, NULL);
6
       if (filterChanged) {
7
-         this->state->pl->incFilter = IncSet_filter(this->inc);
8
+         this->state->pl->incSet = this->inc;
9
          reaction = HTOP_REFRESH | HTOP_REDRAW_BAR;
10
       }
11
       if (this->inc->found) {
(-)b/sysutils/htop/files/patch-ProcessList.c (+28 lines)
Added Link Here
1
--- ProcessList.c.orig	2020-12-22 06:39:42 UTC
2
+++ ProcessList.c
3
@@ -6,6 +6,7 @@ in the source distribution for its full text.
4
 */
5
 
6
 #include "ProcessList.h"
7
+#include "IncSet.h"
8
 
9
 #include <assert.h>
10
 #include <stdlib.h>
11
@@ -483,8 +484,6 @@ void ProcessList_expandTree(ProcessList* this) {
12
 }
13
 
14
 void ProcessList_rebuildPanel(ProcessList* this) {
15
-   const char* incFilter = this->incFilter;
16
-
17
    int currPos = Panel_getSelectedIndex(this->panel);
18
    pid_t currPid = this->following != -1 ? this->following : 0;
19
    int currScrollV = this->panel->scrollV;
20
@@ -497,7 +496,7 @@ void ProcessList_rebuildPanel(ProcessList* this) {
21
 
22
       if ( (!p->show)
23
          || (this->userId != (uid_t) -1 && (p->st_uid != this->userId))
24
-         || (incFilter && !(String_contains_i(Process_getCommand(p), incFilter)))
25
+         || !IncSet_filterTest(this->incSet, p->comm)
26
          || (this->pidMatchList && !Hashtable_get(this->pidMatchList, p->tgid)) )
27
          continue;
28
 
(-)b/sysutils/htop/files/patch-ProcessList.h (+19 lines)
Added Link Here
1
--- ProcessList.h.orig	2020-12-22 06:39:42 UTC
2
+++ ProcessList.h
3
@@ -18,6 +18,7 @@ in the source distribution for its full text.
4
 #include "Process.h"
5
 #include "RichString.h"
6
 #include "Settings.h"
7
+#include "IncSet.h"
8
 #include "UsersTable.h"
9
 #include "Vector.h"
10
 
11
@@ -48,7 +49,7 @@ typedef struct ProcessList_ {
12
    Panel* panel;
13
    int following;
14
    uid_t userId;
15
-   const char* incFilter;
16
+   IncSet* incSet;
17
    Hashtable* pidMatchList;
18
 
19
    #ifdef HAVE_LIBHWLOC
(-)b/sysutils/htop/files/patch-htop.1.in (+14 lines)
Added Link Here
1
--- htop.1.in.orig	2020-12-22 06:39:42 UTC
2
+++ htop.1.in
3
@@ -143,7 +143,10 @@ bindings take precedence.
4
 .B F4, \\\\
5
 Incremental process filtering: type in part of a process command line and
6
 only processes whose names match will be shown. To cancel filtering,
7
-enter the Filter option again and press Esc.
8
+enter the Filter option again and press Esc. F5 will toggle between a
9
+GNU Regular Expression and plain string match, both kinds are
10
+case insensitive. F6 will toggle between showing processes whose names do
11
+match and don't match.
12
 .TP
13
 .B F5, t
14
 Tree view: organize processes by parenthood, and layout the relations
(-)b/sysutils/htop/files/patch-htop.c (+11 lines)
Added Link Here
1
--- htop.c.orig	2020-12-22 06:39:42 UTC
2
+++ htop.c
3
@@ -254,7 +254,7 @@ static void setCommFilter(State* state, char** commFil
4
    buffer[maxlen] = 0;
5
    inc->modes[INC_FILTER].index = strlen(buffer);
6
    inc->filtering = true;
7
-   pl->incFilter = IncSet_filter(inc);
8
+   pl->incSet = ((MainPanel*)state->panel)->inc;
9
 
10
    free(*commFilter);
11
    *commFilter = NULL;

Return to bug 256258