top: introduce relational operators with other filters

When I originally entertained thoughts of maybe adding
relational operators to the new 'Other Filter' feature
the programming challenges seemed just too great. Yet,
when Jaromir suggests its desirability it now suddenly
becomes a reality. Another of life's little mysteries!

At any rate what was already an extremely powerful new
feature is even better by several orders of magnitude!

(everything is perfectly justified plus right margins)
(are completely filled, but of course it must be luck)

References:
http://www.freelists.org/post/procps/top-beyond-infinity,1

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2013-03-05 00:00:00 -06:00 committed by Jaromir Capik
parent f9a208b273
commit 2c2c5f5cd2
2 changed files with 44 additions and 22 deletions

View File

@ -1299,19 +1299,21 @@ static inline const char *hex_make (KLONG num, int noz) {
/*
* The sructure hung from a WIN_t when 'other' filtering is active. */
* This sructure is hung from a WIN_t when other filtering is active */
struct osel_s {
int flg; // include == 1, exclude == 0
FLG_t enu; // field (procflag) to filter
char *val; // value included or excluded
char *(*cmp)(const char *, const char *); // string comparison function
char *raw; // raw user input (dup check)
struct osel_s *nxt; // the next criteria or NULL.
int (*rel)(const char *, const char *); // relational strings compare
char *(*sel)(const char *, const char *); // for selection str compares
char *raw; // raw user input (dup check)
char *val; // value included or excluded
int ops; // filter delimiter/operation
int flg; // include == 1, exclude == 0
int enu; // field (procflag) to filter
};
/*
* A function to turn off any 'other' filtering in the given window */
* A function to turn off entire other filtering in the given window */
static void osel_clear (WIN_t *q) {
struct osel_s *osel = q->osel_1st;
@ -1333,17 +1335,30 @@ static void osel_clear (WIN_t *q) {
/*
* Determine if there's a matching value among the 'other' criteria
* in a given window -- it's called from only one place, and likely
* inlined even without the directive */
* Determine if there is a matching value or releationship among the
* other criteria in the passed window -- it's called from only one
* place, and likely inlined even without the directive */
static inline int osel_matched (const WIN_t *q, FLG_t enu, const char *str) {
struct osel_s *osel = q->osel_1st;
while (osel) {
if (osel->enu == enu) {
char *p = osel->cmp(str, osel->val);
if (p && !osel->flg) return 0;
if (!p && osel->flg) return 0;
int r;
switch (osel->ops) {
case '<': // '<' needs the r < 0 unless
r = osel->rel(str, osel->val); // '!' which needs an inverse
if ((0 <= r && osel->flg) || (0 >= r && !osel->flg)) return 0;
break;
case '>': // '>' needs the r > 0 unless
r = osel->rel(str, osel->val); // '!' which needs an inverse
if ((0 >= r && osel->flg) || (0 <= r && !osel->flg)) return 0;
break;
default:
{ char *p = osel->sel(str, osel->val);
if ((!p && osel->flg) || (p && !osel->flg)) return 0;
}
break;
}
}
osel = osel->nxt;
}
@ -4051,18 +4066,21 @@ signify_that:
static void other_selection (int ch) {
char *(*cmp)(const char *, const char *);
char raw[MEDBUFSIZ], *glob, *pval;
int (*rel)(const char *, const char *);
char *(*sel)(const char *, const char *);
char raw[MEDBUFSIZ], ops, *glob, *pval;
struct osel_s *osel;
const char *typ;
int flg, enu;
if (ch == 'o') {
typ = N_txt(OSEL_casenot_txt);
cmp = strcasestr;
rel = strcasecmp;
sel = strcasestr;
} else {
typ = N_txt(OSEL_caseyes_txt);
cmp = strstr;
rel = strcmp;
sel = strstr;
}
glob = ioline(fmtmk(N_fmt(OSEL_prompts_fmt), Curwin->osel_tot + 1, typ));
if (!snprintf(raw, sizeof(raw), "%s", glob)) return;
@ -4075,11 +4093,12 @@ static void other_selection (int ch) {
}
if (*glob != '!') flg = 1; // #2: is it include/exclude?
else { ++glob; flg = 0; }
if (!(pval = strchr(glob, ':'))) { // #3: do we see a delimiter?
if (!(pval = strpbrk(glob, "<=>"))) { // #3: do we see a delimiter?
show_msg(fmtmk(N_fmt(OSEL_errdelm_fmt)
, flg ? N_txt(WORD_include_txt) : N_txt(WORD_exclude_txt)));
return;
}
ops = *(pval);
*(pval++) = '\0';
for (enu = 0; enu < P_MAXPFLGS; enu++) // #4: is this a valid field?
if (!STRCMP(N_col(enu), glob)) break;
@ -4095,8 +4114,11 @@ static void other_selection (int ch) {
osel = alloc_c(sizeof(struct osel_s));
osel->flg = flg;
osel->enu = enu;
osel->val = alloc_s(pval);
osel->cmp = cmp;
osel->ops = ops;
if (ops == '=') osel->val = alloc_s(pval);
else osel->val = alloc_s(justify_pad(pval, Fieldstab[enu].width, Fieldstab[enu].align));
osel->rel = rel;
osel->sel = sel;
osel->raw = alloc_s(raw);
osel->nxt = Curwin->osel_1st;
Curwin->osel_1st = osel;

View File

@ -431,7 +431,7 @@ static void build_norm_nlstab (void) {
Norm_nlstab[YINSP_workin_txt] = _("patience please, working...");
/* Translation Hint: Below are 2 abbreviations which can be as long as needed:
. FLD = FIELD, VAL = VALUE */
Norm_nlstab[OSEL_prompts_fmt] = _("add filter #%d (%s) as: [!]FLD:VAL");
Norm_nlstab[OSEL_prompts_fmt] = _("add filter #%d (%s) as: [!]FLD?VAL");
Norm_nlstab[OSEL_casenot_txt] = _("ignoring case");
Norm_nlstab[OSEL_caseyes_txt] = _("case sensitive");
Norm_nlstab[OSEL_errdups_txt] = _("duplicate filter was ignored");
@ -439,7 +439,7 @@ static void build_norm_nlstab (void) {
Norm_nlstab[OSEL_errvalu_fmt] = _("'%s' filter value is missing");
Norm_nlstab[WORD_include_txt] = _("include");
Norm_nlstab[WORD_exclude_txt] = _("exclude");
Norm_nlstab[OSEL_statlin_fmt] = _("<Enter> to resume, filters = %s");
Norm_nlstab[OSEL_statlin_fmt] = _("<Enter> to resume, filters: %s");
Norm_nlstab[WORD_noneone_txt] = _("none");
}