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.
This commit is contained in:
Daniel Lange 2022-03-25 16:24:24 +01:00
parent a2ca7583a9
commit 7c43e02591
7 changed files with 28 additions and 11 deletions

View File

@ -85,7 +85,7 @@ static void updateWeakPanel(const IncSet* this, Panel* panel, Vector* lines) {
const char* incFilter = this->modes[INC_FILTER].buffer; const char* incFilter = this->modes[INC_FILTER].buffer;
for (int i = 0; i < Vector_size(lines); i++) { for (int i = 0; i < Vector_size(lines); i++) {
ListItem* line = (ListItem*)Vector_get(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); Panel_add(panel, (Object*)line);
if (selected == (Object*)line) { if (selected == (Object*)line) {
Panel_setSelected(panel, n); 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) { static bool search(const IncSet* this, Panel* panel, IncMode_GetPanelValue getPanelValue) {
int size = Panel_size(panel); int size = Panel_size(panel);
for (int i = 0; i < size; i++) { 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); Panel_setSelected(panel, i);
return true; return true;
} }
@ -148,7 +148,7 @@ static bool IncMode_find(const IncMode* mode, Panel* panel, IncMode_GetPanelValu
return false; 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); Panel_setSelected(panel, i);
return true; return true;
} }

View File

@ -63,7 +63,7 @@ void InfoScreen_drawTitled(InfoScreen* this, const char* fmt, ...) {
void InfoScreen_addLine(InfoScreen* this, const char* line) { void InfoScreen_addLine(InfoScreen* this, const char* line) {
Vector_add(this->lines, (Object*) ListItem_new(line, 0)); Vector_add(this->lines, (Object*) ListItem_new(line, 0));
const char* incFilter = IncSet_filter(this->inc); 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)); 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* last = (ListItem*)Vector_get(this->lines, Vector_size(this->lines) - 1);
ListItem_append(last, line); ListItem_append(last, line);
const char* incFilter = IncSet_filter(this->inc); 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); Panel_add(this->display, (Object*)last);
} }
} }

View File

@ -394,7 +394,7 @@ void ProcessList_rebuildPanel(ProcessList* this) {
if ( (!p->show) if ( (!p->show)
|| (this->userId != (uid_t) -1 && (p->st_uid != this->userId)) || (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)) ) || (this->pidMatchList && !Hashtable_get(this->pidMatchList, p->tgid)) )
continue; continue;

View File

@ -94,9 +94,23 @@ void* xReallocArrayZero(void* ptr, size_t prevmemb, size_t newmemb, size_t size)
return ret; return ret;
} }
inline bool String_contains_i(const char* s1, const char* s2) { 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; return strcasestr(s1, s2) != NULL;
} }
}
char* String_cat(const char* s1, const char* s2) { char* String_cat(const char* s1, const char* s2) {
const size_t l1 = strlen(s1); const size_t l1 = strlen(s1);

View File

@ -40,7 +40,7 @@ static inline bool String_startsWith(const char* s, const char* match) {
return strncmp(s, match, strlen(match)) == 0; 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) { static inline bool String_eq(const char* s1, const char* s2) {
return strcmp(s1, s2) == 0; return strcmp(s1, s2) == 0;

View File

@ -85,7 +85,7 @@ char* Generic_uname(void) {
if (uname_result == 0) { if (uname_result == 0) {
size_t written = xSnprintf(savedString, sizeof(savedString), "%s %s [%s]", uname_info.sysname, uname_info.release, uname_info.machine); 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); snprintf(savedString + written, sizeof(savedString) - written, " @ %s", distro);
} else { } else {
snprintf(savedString, sizeof(savedString), "%s", distro); snprintf(savedString, sizeof(savedString), "%s", distro);

View File

@ -50,7 +50,8 @@ Start
in monochrome mode in monochrome mode
.TP .TP
\fB\-F \-\-filter=FILTER \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 .TP
\fB\-h \-\-help \fB\-h \-\-help
Display a help message and exit 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 Incremental process filtering: type in part of a process command line and
only processes whose names match will be shown. To cancel filtering, only processes whose names match will be shown. To cancel filtering,
enter the Filter option again and press Esc. 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 .TP
.B F5, t .B F5, t
Tree view: organize processes by parenthood, and layout the relations Tree view: organize processes by parenthood, and layout the relations