From 7c43e02591de9b6e14744e3eaffed25ad092756e Mon Sep 17 00:00:00 2001 From: Daniel Lange Date: Fri, 25 Mar 2022 16:24:24 +0100 Subject: Improve String_contains_i to allow for multiple terms This enables: * Multiple filters in the main panel and strace etc. views * Multiple search terms The search terms are separated by "|" and are still fixed strings matched case-insensitive. Added a multi flag at request of BenBE. --- IncSet.c | 6 +++--- InfoScreen.c | 4 ++-- ProcessList.c | 2 +- XUtils.c | 18 ++++++++++++++++-- XUtils.h | 2 +- generic/uname.c | 2 +- htop.1.in | 5 ++++- 7 files changed, 28 insertions(+), 11 deletions(-) diff --git a/IncSet.c b/IncSet.c index 22c5b259..71edf1ce 100644 --- a/IncSet.c +++ b/IncSet.c @@ -85,7 +85,7 @@ static void updateWeakPanel(const IncSet* this, Panel* panel, Vector* lines) { const char* incFilter = this->modes[INC_FILTER].buffer; for (int i = 0; i < Vector_size(lines); i++) { ListItem* line = (ListItem*)Vector_get(lines, i); - if (String_contains_i(line->value, incFilter)) { + if (String_contains_i(line->value, incFilter, true)) { Panel_add(panel, (Object*)line); if (selected == (Object*)line) { Panel_setSelected(panel, n); @@ -108,7 +108,7 @@ static void updateWeakPanel(const IncSet* this, Panel* panel, Vector* lines) { static bool search(const IncSet* this, Panel* panel, IncMode_GetPanelValue getPanelValue) { int size = Panel_size(panel); for (int i = 0; i < size; i++) { - if (String_contains_i(getPanelValue(panel, i), this->active->buffer)) { + if (String_contains_i(getPanelValue(panel, i), this->active->buffer, true)) { Panel_setSelected(panel, i); return true; } @@ -148,7 +148,7 @@ static bool IncMode_find(const IncMode* mode, Panel* panel, IncMode_GetPanelValu return false; } - if (String_contains_i(getPanelValue(panel, i), mode->buffer)) { + if (String_contains_i(getPanelValue(panel, i), mode->buffer, true)) { Panel_setSelected(panel, i); return true; } diff --git a/InfoScreen.c b/InfoScreen.c index eea09aa2..105d9c34 100644 --- a/InfoScreen.c +++ b/InfoScreen.c @@ -63,7 +63,7 @@ void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...) { void InfoScreen_addLine(InfoScreen* this, const char* line) { Vector_add(this->lines, (Object*) ListItem_new(line, 0)); const char* incFilter = IncSet_filter(this->inc); - if (!incFilter || String_contains_i(line, incFilter)) { + if (!incFilter || String_contains_i(line, incFilter, true)) { Panel_add(this->display, Vector_get(this->lines, Vector_size(this->lines) - 1)); } } @@ -72,7 +72,7 @@ void InfoScreen_appendLine(InfoScreen* this, const char* line) { ListItem* last = (ListItem*)Vector_get(this->lines, Vector_size(this->lines) - 1); ListItem_append(last, line); const char* incFilter = IncSet_filter(this->inc); - if (incFilter && Panel_get(this->display, Panel_size(this->display) - 1) != (Object*)last && String_contains_i(line, incFilter)) { + if (incFilter && Panel_get(this->display, Panel_size(this->display) - 1) != (Object*)last && String_contains_i(line, incFilter, true)) { Panel_add(this->display, (Object*)last); } } diff --git a/ProcessList.c b/ProcessList.c index f3e184e8..2e5ad7cd 100644 --- a/ProcessList.c +++ b/ProcessList.c @@ -394,7 +394,7 @@ void ProcessList_rebuildPanel(ProcessList* this) { if ( (!p->show) || (this->userId != (uid_t) -1 && (p->st_uid != this->userId)) - || (incFilter && !(String_contains_i(Process_getCommand(p), incFilter))) + || (incFilter && !(String_contains_i(Process_getCommand(p), incFilter, true))) || (this->pidMatchList && !Hashtable_get(this->pidMatchList, p->tgid)) ) continue; diff --git a/XUtils.c b/XUtils.c index 827fa950..b34a8a73 100644 --- a/XUtils.c +++ b/XUtils.c @@ -94,8 +94,22 @@ void* xReallocArrayZero(void* ptr, size_t prevmemb, size_t newmemb, size_t size) return ret; } -inline bool String_contains_i(const char* s1, const char* s2) { - return strcasestr(s1, s2) != NULL; +inline bool String_contains_i(const char* s1, const char* s2, bool multi) { + // we have a multi-string search term, handle as special case for performance reasons + if (multi && strstr(s2, "|")) { + size_t nNeedles; + char** needles = String_split(s2, '|', &nNeedles); + for (size_t i = 0; i < nNeedles; i++) { + if (strcasestr(s1, needles[i]) != NULL) { + String_freeArray(needles); + return true; + } + } + String_freeArray(needles); + return false; + } else { + return strcasestr(s1, s2) != NULL; + } } char* String_cat(const char* s1, const char* s2) { diff --git a/XUtils.h b/XUtils.h index 6c096df4..2522a71f 100644 --- a/XUtils.h +++ b/XUtils.h @@ -40,7 +40,7 @@ static inline bool String_startsWith(const char* s, const char* match) { return strncmp(s, match, strlen(match)) == 0; } -bool String_contains_i(const char* s1, const char* s2); +bool String_contains_i(const char* s1, const char* s2, bool multi); static inline bool String_eq(const char* s1, const char* s2) { return strcmp(s1, s2) == 0; diff --git a/generic/uname.c b/generic/uname.c index 21f9a3cc..2a734dc1 100644 --- a/generic/uname.c +++ b/generic/uname.c @@ -85,7 +85,7 @@ char* Generic_uname(void) { if (uname_result == 0) { size_t written = xSnprintf(savedString, sizeof(savedString), "%s %s [%s]", uname_info.sysname, uname_info.release, uname_info.machine); - if (!String_contains_i(savedString, distro) && sizeof(savedString) > written) + if (!String_contains_i(savedString, distro, false) && sizeof(savedString) > written) snprintf(savedString + written, sizeof(savedString) - written, " @ %s", distro); } else { snprintf(savedString, sizeof(savedString), "%s", distro); diff --git a/htop.1.in b/htop.1.in index b51789a2..c298e7cb 100644 --- a/htop.1.in +++ b/htop.1.in @@ -50,7 +50,8 @@ Start in monochrome mode .TP \fB\-F \-\-filter=FILTER -Filter processes by command +Filter processes by terms matching the commands. The terms are matched +case-insensitive and as fixed strings (not regexs). You can separate multiple terms with "|". .TP \fB\-h \-\-help Display a help message and exit @@ -175,6 +176,8 @@ bindings take precedence. Incremental process filtering: type in part of a process command line and only processes whose names match will be shown. To cancel filtering, enter the Filter option again and press Esc. +The matching is done case-insensitive. Terms are fixed strings (no regex). +You can separate multiple terms with "|". .TP .B F5, t Tree view: organize processes by parenthood, and layout the relations -- cgit v1.2.3