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 |
|