Skip to content

Commit ffa2703

Browse files
committed
Add user-configurable distribution path prefixes
Assisted-by: Claude (Anthropic)
1 parent 13187f2 commit ffa2703

6 files changed

Lines changed: 158 additions & 45 deletions

File tree

DisplayOptionsPanel.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ static HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) {
4545
}
4646

4747
NumberItem* numItem = (OptionItem_kind(selected) == OPTION_ITEM_NUMBER) ? (NumberItem*)selected : NULL;
48+
StringItem* strItem = (OptionItem_kind(selected) == OPTION_ITEM_STRING) ? (StringItem*)selected : NULL;
4849

4950
/* Helper: position the hardware cursor right after the edit buffer.
5051
* +1 on Y for the panel header row; +1 on X for the leading '[' bracket. */
@@ -54,8 +55,19 @@ static HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) {
5455
super->cursorOn = true; \
5556
} while (0)
5657

58+
#define SET_STR_CURSOR() do { \
59+
super->cursorY = super->y + 1 + (super->selected - super->scrollV); \
60+
super->cursorX = super->x + 1 + (int)LineEditor_getCursor(&strItem->editor); \
61+
super->cursorOn = true; \
62+
} while (0)
63+
5764
switch (ch) {
5865
case 27: /* Escape: cancel editing */
66+
if (numItem && numItem->editing) {
67+
NumberItem_cancelEditing(numItem);
68+
super->cursorOn = false;
69+
return HANDLED;
70+
}
5971
if (numItem && numItem->editing) {
6072
NumberItem_cancelEditing(numItem);
6173
super->cursorOn = false;
@@ -64,6 +76,11 @@ static HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) {
6476
break;
6577
case KEY_BACKSPACE:
6678
case KEY_DEL_MAC:
79+
if (strItem && strItem->editing) {
80+
LineEditor_handleKey(&strItem->editor, KEY_BACKSPACE);
81+
SET_STR_CURSOR();
82+
return HANDLED;
83+
}
6784
if (numItem) {
6885
if (!numItem->editing) {
6986
NumberItem_startEditingFromValue(numItem);
@@ -76,6 +93,19 @@ static HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) {
7693
case '\n':
7794
case '\r':
7895
case KEY_ENTER:
96+
if (strItem && strItem->editing) {
97+
StringItem_applyEditing(strItem);
98+
super->cursorOn = false;
99+
settingsChanged = true;
100+
result = HANDLED;
101+
break;
102+
}
103+
if (strItem && !strItem->editing) {
104+
StringItem_startEditing(strItem);
105+
SET_STR_CURSOR();
106+
result = HANDLED;
107+
break;
108+
}
79109
if (numItem && numItem->editing) {
80110
if (NumberItem_applyEditing(numItem)) {
81111
settingsChanged = true;
@@ -219,6 +249,12 @@ static HandlerResult DisplayOptionsPanel_eventHandler(Panel* super, int ch) {
219249
SET_EDIT_CURSOR();
220250
return HANDLED;
221251
}
252+
} else if (strItem) {
253+
if (strItem->editing) {
254+
LineEditor_handleKey(&strItem->editor, ch);
255+
SET_STR_CURSOR();
256+
return HANDLED;
257+
}
222258
}
223259
break;
224260
}
@@ -282,6 +318,7 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
282318
Panel_add(super, (Object*) CheckItem_newByRef("Highlight program \"basename\"", &(settings->highlightBaseName)));
283319
Panel_add(super, (Object*) CheckItem_newByRef("Highlight out-dated/removed programs (red) / libraries (yellow)", &(settings->highlightDeletedExe)));
284320
Panel_add(super, (Object*) CheckItem_newByRef("Shadow distribution path prefixes", &(settings->shadowDistPathPrefix)));
321+
Panel_add(super, (Object*) StringItem_newByRef("- Custom path prefixes (colon-separated)", &(settings->distPathPrefixes), NULL));
285322
Panel_add(super, (Object*) CheckItem_newByRef("Merge exe, comm and cmdline in Command", &(settings->showMergedCommand)));
286323
Panel_add(super, (Object*) CheckItem_newByRef("- Try to find comm in cmdline (when Command is merged)", &(settings->findCommInCmdline)));
287324
Panel_add(super, (Object*) CheckItem_newByRef("- Try to strip exe from cmdline (when Command is merged)", &(settings->stripExeFromCmdline)));

OptionItem.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,23 @@ static void NumberItem_display(const Object* cast, RichString* out) {
7676
RichString_appendWide(out, CRT_colors[CHECK_TEXT], this->super.text);
7777
}
7878

79+
static void StringItem_display(const Object* cast, RichString* out) {
80+
const StringItem* this = (const StringItem*)cast;
81+
int labelAttr = CRT_colors[CHECK_TEXT];
82+
int boxAttr = CRT_colors[CHECK_BOX];
83+
int valAttr = this->valid ? CRT_colors[CHECK_MARK] : CRT_colors[FAILED_READ];
84+
85+
RichString_writeAscii(out, boxAttr, "[");
86+
if (this->editing) {
87+
RichString_appendAscii(out, valAttr, this->editor.buffer);
88+
} else {
89+
const char* val = (this->ref && *this->ref) ? *this->ref : "";
90+
RichString_appendAscii(out, valAttr, *val ? val : "(empty)");
91+
}
92+
RichString_appendAscii(out, boxAttr, "] ");
93+
RichString_appendWide(out, labelAttr, this->super.text);
94+
}
95+
7996
const OptionItemClass OptionItem_class = {
8097
.super = {
8198
.extends = Class(Object),
@@ -112,6 +129,15 @@ const OptionItemClass NumberItem_class = {
112129
.kind = OPTION_ITEM_NUMBER
113130
};
114131

132+
const OptionItemClass StringItem_class = {
133+
.super = {
134+
.extends = Class(OptionItem),
135+
.delete = OptionItem_delete,
136+
.display = StringItem_display
137+
},
138+
.kind = OPTION_ITEM_STRING
139+
};
140+
115141
TextItem* TextItem_new(const char* text) {
116142
TextItem* this = AllocThis(TextItem);
117143
this->super.text = xStrdup(text);
@@ -323,3 +349,40 @@ void NumberItem_deleteChar(NumberItem* this) {
323349
this->editBuffer[this->editLen] = '\0';
324350
}
325351
}
352+
StringItem* StringItem_newByRef(const char* text, char** ref, bool (*validate)(const char* text)) {
353+
StringItem* this = AllocThis(StringItem);
354+
this->super.text = xStrdup(text);
355+
this->ref = ref;
356+
this->editing = false;
357+
this->valid = true;
358+
this->validate = validate;
359+
LineEditor_init(&this->editor);
360+
if (ref && *ref)
361+
LineEditor_setText(&this->editor, *ref);
362+
return this;
363+
}
364+
365+
void StringItem_startEditing(StringItem* this) {
366+
this->editing = true;
367+
LineEditor_setText(&this->editor, (this->ref && *this->ref) ? *this->ref : "");
368+
}
369+
370+
void StringItem_cancelEditing(StringItem* this) {
371+
this->editing = false;
372+
LineEditor_setText(&this->editor, (this->ref && *this->ref) ? *this->ref : "");
373+
}
374+
375+
bool StringItem_applyEditing(StringItem* this) {
376+
this->editing = false;
377+
const char* text = this->editor.buffer;
378+
if (this->validate && !this->validate(text)) {
379+
this->valid = false;
380+
return false;
381+
}
382+
this->valid = true;
383+
if (this->ref) {
384+
free(*this->ref);
385+
*this->ref = (*text != '\0') ? xStrdup(text) : NULL;
386+
}
387+
return true;
388+
}

OptionItem.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ in the source distribution for its full text.
99

1010
#include <stdbool.h>
1111

12+
#include "LineEditor.h"
1213
#include "Object.h"
1314

1415
#define NUMBERITEM_EDIT_MAX 10
@@ -17,6 +18,7 @@ enum OptionItemType {
1718
OPTION_ITEM_TEXT,
1819
OPTION_ITEM_CHECK,
1920
OPTION_ITEM_NUMBER,
21+
OPTION_ITEM_STRING,
2022
};
2123

2224
typedef struct OptionItemClass_ {
@@ -62,10 +64,20 @@ typedef struct NumberItem_ {
6264
int savedValue;
6365
} NumberItem;
6466

67+
typedef struct StringItem_ {
68+
OptionItem super;
69+
char** ref;
70+
bool editing;
71+
bool valid;
72+
LineEditor editor;
73+
bool (*validate)(const char* text);
74+
} StringItem;
75+
6576
extern const OptionItemClass OptionItem_class;
6677
extern const OptionItemClass TextItem_class;
6778
extern const OptionItemClass CheckItem_class;
6879
extern const OptionItemClass NumberItem_class;
80+
extern const OptionItemClass StringItem_class;
6981

7082
TextItem* TextItem_new(const char* text);
7183

@@ -88,4 +100,9 @@ bool NumberItem_applyEditing(NumberItem* this);
88100
bool NumberItem_addChar(NumberItem* this, char c);
89101
void NumberItem_deleteChar(NumberItem* this);
90102

103+
StringItem* StringItem_newByRef(const char* text, char** ref, bool (*validate)(const char* text));
104+
void StringItem_startEditing(StringItem* this);
105+
void StringItem_cancelEditing(StringItem* this);
106+
bool StringItem_applyEditing(StringItem* this);
107+
91108
#endif

Process.c

Lines changed: 35 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,37 @@ static inline char* stpcpyWithNewlineConversion(char* dstStr, const char* srcStr
174174
return dstStr;
175175
}
176176

177+
static size_t matchesDistPrefix(const char* str, const Settings* settings) {
178+
if (settings->distPathPrefixes && settings->distPathPrefixes[0] != '\0') {
179+
char* list = xStrdup(settings->distPathPrefixes);
180+
char* saveptr;
181+
char* token = strtok_r(list, ":", &saveptr);
182+
size_t matched = 0;
183+
while (token) {
184+
if (String_startsWith(str, token)) {
185+
matched = strlen(token);
186+
break;
187+
}
188+
token = strtok_r(NULL, ":", &saveptr);
189+
}
190+
free(list);
191+
return matched;
192+
}
193+
194+
static const char* const prefixes[] = {
195+
"/bin/", "/sbin/", "/lib/", "/lib32/", "/lib64/", "/libx32/",
196+
"/usr/bin/", "/usr/sbin/", "/usr/lib/", "/usr/lib32/", "/usr/lib64/",
197+
"/usr/libx32/", "/usr/libexec/", "/usr/local/bin/", "/usr/local/lib/",
198+
"/usr/local/sbin/", "/nix/store/", "/run/current-system/",
199+
NULL
200+
};
201+
for (size_t i = 0; prefixes[i]; i++) {
202+
if (String_startsWith(str, prefixes[i]))
203+
return strlen(prefixes[i]);
204+
}
205+
return 0;
206+
}
207+
177208
/*
178209
* This function makes the merged Command string. It also stores the offsets of the
179210
* basename, comm w.r.t the merged Command string - these offsets will be used by
@@ -256,51 +287,10 @@ void Process_makeCommandStr(Process* this, const Settings* settings) {
256287

257288
#define CHECK_AND_MARK_DIST_PATH_PREFIXES(str_) \
258289
do { \
259-
if ((str_)[0] != '/') { \
260-
break; \
261-
} \
262-
switch ((str_)[1]) { \
263-
case 'b': \
264-
CHECK_AND_MARK(str_, "/bin/"); \
265-
break; \
266-
case 'l': \
267-
CHECK_AND_MARK(str_, "/lib/"); \
268-
CHECK_AND_MARK(str_, "/lib32/"); \
269-
CHECK_AND_MARK(str_, "/lib64/"); \
270-
CHECK_AND_MARK(str_, "/libx32/"); \
271-
break; \
272-
case 's': \
273-
CHECK_AND_MARK(str_, "/sbin/"); \
274-
break; \
275-
case 'u': \
276-
if (String_startsWith(str_, "/usr/")) { \
277-
switch ((str_)[5]) { \
278-
case 'b': \
279-
CHECK_AND_MARK(str_, "/usr/bin/"); \
280-
break; \
281-
case 'l': \
282-
CHECK_AND_MARK(str_, "/usr/libexec/"); \
283-
CHECK_AND_MARK(str_, "/usr/lib/"); \
284-
CHECK_AND_MARK(str_, "/usr/lib32/"); \
285-
CHECK_AND_MARK(str_, "/usr/lib64/"); \
286-
CHECK_AND_MARK(str_, "/usr/libx32/"); \
287-
\
288-
CHECK_AND_MARK(str_, "/usr/local/bin/"); \
289-
CHECK_AND_MARK(str_, "/usr/local/lib/"); \
290-
CHECK_AND_MARK(str_, "/usr/local/sbin/"); \
291-
break; \
292-
case 's': \
293-
CHECK_AND_MARK(str_, "/usr/sbin/"); \
294-
break; \
295-
} \
296-
} \
297-
break; \
298-
case 'n': \
299-
CHECK_AND_MARK(str_, "/nix/store/"); \
300-
break; \
301-
case 'r': \
302-
CHECK_AND_MARK(str_, "/run/current-system/"); \
303-
break; \
290+
size_t _plen = matchesDistPrefix(str_, settings); \
291+
if (_plen > 0) { \
292+
WRITE_HIGHLIGHT(0, _plen, CRT_colors[PROCESS_SHADOW], \
293+
CMDLINE_HIGHLIGHT_FLAG_PREFIXDIR); \
304294
} \
305295
} while (0)
306296

Settings.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ static void Settings_deleteScreens(Settings* this) {
5151
void Settings_delete(Settings* this) {
5252
free(this->filename);
5353
free(this->initialFilename);
54+
free(this->distPathPrefixes);
5455
Settings_deleteColumns(this);
5556
Settings_deleteScreens(this);
5657
free(this);
@@ -440,6 +441,8 @@ static bool Settings_read(Settings* this, const char* fileName, const Machine* h
440441
this->highlightDeletedExe = atoi(option[1]);
441442
} else if (String_eq(option[0], "shadow_distribution_path_prefix")) {
442443
this->shadowDistPathPrefix = atoi(option[1]);
444+
} else if (String_eq(option[0], "dist_path_prefixes")) {
445+
free_and_xStrdup(&this->distPathPrefixes, option[1]);
443446
} else if (String_eq(option[0], "highlight_megabytes")) {
444447
this->highlightMegabytes = atoi(option[1]);
445448
} else if (String_eq(option[0], "highlight_threads")) {
@@ -696,6 +699,8 @@ int Settings_write(const Settings* this, bool onCrash) {
696699
printSettingInteger("highlight_base_name", this->highlightBaseName);
697700
printSettingInteger("highlight_deleted_exe", this->highlightDeletedExe);
698701
printSettingInteger("shadow_distribution_path_prefix", this->shadowDistPathPrefix);
702+
if (this->distPathPrefixes && this->distPathPrefixes[0] != '\0')
703+
printSettingString("dist_path_prefixes", this->distPathPrefixes);
699704
printSettingInteger("highlight_megabytes", this->highlightMegabytes);
700705
printSettingInteger("highlight_threads", this->highlightThreads);
701706
printSettingInteger("highlight_changes", this->highlightChanges);

Settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ typedef struct Settings_ {
9191
bool highlightBaseName;
9292
bool highlightDeletedExe;
9393
bool shadowDistPathPrefix;
94+
char* distPathPrefixes;
9495
bool highlightMegabytes;
9596
bool highlightThreads;
9697
bool highlightChanges;

0 commit comments

Comments
 (0)