Skip to content

Commit ef36d39

Browse files
committed
Add configurable delimiter; Improve text rendering
1 parent a9e29b1 commit ef36d39

File tree

2 files changed

+40
-14
lines changed

2 files changed

+40
-14
lines changed

README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,12 @@ Usage: build/hq [options] <selector> <mode> [mode argument]
3030
Options:
3131
-h, --help
3232
show this text
33-
-f, --file
33+
-f, --file <file>
3434
file to read (defaults to stdin)
35+
-d, --delimiter <delim>
36+
delimiter character to use between results (defaults to newline)
37+
-0, --null
38+
uses \0 as delimiter
3539
3640
<selector>
3741
CSS selector to match against

main.cpp

+35-13
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@ Usage: %s [options] <selector> <mode> [mode argument]
2121
Options:
2222
-h, --help
2323
show this text
24-
-f, --file
24+
-f, --file <file>
2525
file to read (defaults to stdin)
26+
-d, --delimiter <delim>
27+
delimiter character to use between results (defaults to newline)
28+
-0, --null
29+
uses \0 as delimiter
2630
2731
<selector>
2832
CSS selector to match against
@@ -47,6 +51,7 @@ static map<const string, bool> flags = {
4751
static map<const string, string> state = { // global state
4852
{"progname", "hq"}, // program name
4953
{"file", "-"}, // input file path, or - for stdin
54+
{"delim", "\n"}, // result delimiter
5055
{"selector", ""}, // matching selector
5156
{"mode", ""}, // output mode
5257
{"data", ""}, // read input data
@@ -87,7 +92,9 @@ template <typename T> inline bool vec_has(vector<T> &vec, T val){
8792

8893
static map<const char, const string> option_longopts = { // maps shortopts to longopts from option_handlers
8994
{'h', "help"},
90-
{'f', "file"}
95+
{'f', "file"},
96+
{'d', "delimiter"},
97+
{'0', "zero"}
9198
};
9299

93100
static map<const string, const function<void(int&, const char**&)>> option_handlers = { // maps longopts to functions
@@ -98,6 +105,13 @@ static map<const string, const function<void(int&, const char**&)>> option_handl
98105
{"file", [](int &argc, const char** &argv) {
99106
readarg(argc, ++argv, "file");
100107
argv--;
108+
}},
109+
{"delimiter", [](int &argc, const char** &argv) {
110+
readarg(argc, ++argv, "delim");
111+
argv--;
112+
}},
113+
{"zero", [](int &argc, const char** &argv) {
114+
state["delim"] = "\0";
101115
}}
102116
};
103117

@@ -107,15 +121,19 @@ static map<const string, const function<void(myhtml_tree_node_t*)>> mode_handler
107121
printf("%.*s", static_cast<int>(len), data);
108122
return 0;
109123
}, nullptr);
110-
cout << endl;
124+
printf("%c", state["delim"][0]);
111125
}},
112126

113127
{"text", [](myhtml_tree_node_t* node) {
114128
string rendered = "";
115129

116130
static vector<char> collapsible = {' ', '\t', '\n', '\r'};
131+
static vector<unsigned long> breaking = {
132+
MyHTML_TAG_BR,
133+
MyHTML_TAG_P
134+
};
117135

118-
myhtml_tree_node_t* node_iter = node;
136+
myhtml_tree_node_t* node_iter = node->child;
119137
while(node_iter){
120138
const char* text_c = myhtml_node_text(node_iter, nullptr);
121139
string text = "";
@@ -136,14 +154,15 @@ static map<const string, const function<void(myhtml_tree_node_t*)>> mode_handler
136154
rendered += text;
137155
}
138156

139-
if(node_iter->tag_id == MyHTML_TAG_BR){ // <br/>
140-
rendered += "\n";
141-
}
142-
143157
if(node_iter->child) node_iter = node_iter->child;
144158
else{
145159
while(node_iter != node && node_iter->next == nullptr) node_iter = node_iter->parent;
146160
if(node_iter == node) break;
161+
162+
if(vec_has(breaking, node_iter->tag_id)){ // <br/>
163+
rendered += "\n";
164+
}
165+
147166
node_iter = node_iter->next;
148167
}
149168
}
@@ -157,10 +176,11 @@ static map<const string, const function<void(myhtml_tree_node_t*)>> mode_handler
157176
rendered.erase(index, 1);
158177
}
159178

160-
while(rendered[0] == ' ') rendered.erase(0, 1); // clear whitespace before single-line content
161-
while(*(rendered.end()-1) == ' ') rendered.erase(rendered.length()-1, 1); // clear whitespace after single-line content
179+
while(vec_has(collapsible, rendered[0])) rendered.erase(0, 1); // clear whitespace before single-line content
180+
while(vec_has(collapsible, *(rendered.end()-1))) rendered.erase(rendered.length()-1, 1); // clear whitespace after single-line content
162181

163-
cout << rendered << endl;
182+
cout << rendered;
183+
printf("%c", state["delim"][0]);
164184
}},
165185

166186
{"attr", [](myhtml_tree_node_t* node) {
@@ -176,8 +196,10 @@ static map<const string, const function<void(myhtml_tree_node_t*)>> mode_handler
176196
if(attr == nullptr) return;
177197

178198
do{
179-
if(state["modearg"] == mycore_string_data(&attr->key))
180-
cout << mycore_string_data(&attr->value) << endl;
199+
if(state["modearg"] == mycore_string_data(&attr->key)){
200+
cout << mycore_string_data(&attr->value);
201+
printf("%c", state["delim"][0]);
202+
}
181203

182204
if(attr != token->attr_last) attr = attr->next;
183205
}while(attr != token->attr_last);

0 commit comments

Comments
 (0)