Skip to content

Commit 7552e2a

Browse files
committed
Include default value and 'declared by' value in output
1 parent 1089dc7 commit 7552e2a

2 files changed

Lines changed: 129 additions & 10 deletions

File tree

src/home_manager.rs

Lines changed: 123 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub(crate) struct HomeManagerOption {
1111
pub(crate) name: String,
1212
pub(crate) description: String,
1313
pub(crate) type_info: String,
14+
pub(crate) default_value: String,
15+
pub(crate) declared_by: String,
1416
}
1517

1618
fn decode_html_entities(input: &str) -> String {
@@ -111,25 +113,130 @@ fn extract_description(dd_block: &str) -> String {
111113
}
112114

113115
fn extract_type_info(dd_block: &str) -> String {
116+
extract_section_value(
117+
dd_block,
118+
"Type:",
119+
&[
120+
"Default:",
121+
"Example:",
122+
"Declared by:",
123+
"Defined by:",
124+
"Related packages:",
125+
"Related options:",
126+
],
127+
)
128+
}
129+
130+
fn extract_default_value(dd_block: &str) -> String {
131+
extract_section_value(
132+
dd_block,
133+
"Default:",
134+
&[
135+
"Example:",
136+
"Declared by:",
137+
"Defined by:",
138+
"Related packages:",
139+
"Related options:",
140+
"Type:",
141+
],
142+
)
143+
}
144+
145+
fn extract_declared_by(dd_block: &str) -> String {
146+
let Some(section) = extract_section_html(
147+
dd_block,
148+
"Declared by:",
149+
&[
150+
"Defined by:",
151+
"Related packages:",
152+
"Related options:",
153+
"Example:",
154+
"Default:",
155+
"Type:",
156+
],
157+
) else {
158+
return String::new();
159+
};
160+
161+
let links = extract_links(section);
162+
if links.is_empty() {
163+
String::new()
164+
} else {
165+
links.join(", ")
166+
}
167+
}
168+
169+
fn extract_links(section: &str) -> Vec<String> {
170+
let mut links = Vec::new();
171+
let mut seen = HashSet::new();
172+
let mut cursor = 0;
173+
174+
while let Some(href_rel) = section[cursor..].find("href=") {
175+
let href_start = cursor + href_rel + "href=".len();
176+
let bytes = section.as_bytes();
177+
if href_start >= bytes.len() {
178+
break;
179+
}
180+
181+
let quote = bytes[href_start];
182+
if quote != b'"' && quote != b'\'' {
183+
cursor = href_start + 1;
184+
continue;
185+
}
186+
187+
let mut end = href_start + 1;
188+
while end < bytes.len() && bytes[end] != quote {
189+
end += 1;
190+
}
191+
if end >= bytes.len() {
192+
break;
193+
}
194+
195+
let url = &section[href_start + 1..end];
196+
let decoded = decode_html_entities(url);
197+
if !decoded.is_empty() && seen.insert(decoded.clone()) {
198+
links.push(decoded);
199+
}
200+
201+
cursor = end + 1;
202+
}
203+
204+
links
205+
}
206+
207+
fn extract_section_html<'a>(
208+
input: &'a str,
209+
label: &str,
210+
stop_markers: &[&str],
211+
) -> Option<&'a str> {
212+
let label_idx = input.find(label)?;
213+
let rest = &input[label_idx + label.len()..];
214+
let mut end = rest.len();
215+
216+
for marker in stop_markers {
217+
if let Some(idx) = rest.find(marker) {
218+
if idx < end {
219+
end = idx;
220+
}
221+
}
222+
}
223+
224+
Some(&rest[..end])
225+
}
226+
227+
fn extract_section_value(dd_block: &str, label: &str, stop_markers: &[&str]) -> String {
114228
let text = clean_html_text(dd_block);
115-
let Some(type_idx) = text.find("Type:") else {
229+
let Some(section_idx) = text.find(label) else {
116230
return String::new();
117231
};
118232

119-
let rest = text[type_idx + "Type:".len()..].trim_start();
233+
let rest = text[section_idx + label.len()..].trim_start();
120234
if rest.is_empty() {
121235
return String::new();
122236
}
123237

124238
let mut end = rest.len();
125-
for marker in [
126-
"Default:",
127-
"Example:",
128-
"Declared by:",
129-
"Defined by:",
130-
"Related packages:",
131-
"Related options:",
132-
] {
239+
for marker in stop_markers {
133240
if let Some(idx) = rest.find(marker) {
134241
if idx < end {
135242
end = idx;
@@ -183,11 +290,15 @@ fn parse_home_manager_options(
183290

184291
let mut description = String::new();
185292
let mut type_info = String::new();
293+
let mut default_value = String::new();
294+
let mut declared_by = String::new();
186295
let mut next_cursor = cursor;
187296

188297
if let Some((dd_block, dd_next_cursor)) = extract_dd_block(html, cursor) {
189298
description = extract_description(dd_block);
190299
type_info = extract_type_info(dd_block);
300+
default_value = extract_default_value(dd_block);
301+
declared_by = extract_declared_by(dd_block);
191302
next_cursor = dd_next_cursor;
192303
}
193304

@@ -201,6 +312,8 @@ fn parse_home_manager_options(
201312
name,
202313
description,
203314
type_info: type_info.trim().to_string(),
315+
default_value: default_value.trim().to_string(),
316+
declared_by: declared_by.trim().to_string(),
204317
});
205318

206319
cursor = next_cursor;

src/tools.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,12 @@ impl HomeManagerOptionsSearch {
762762
if !option.type_info.is_empty() {
763763
lines.push(format!(" type: {}", option.type_info));
764764
}
765+
if !option.default_value.is_empty() {
766+
lines.push(format!(" default: {}", option.default_value));
767+
}
768+
if !option.declared_by.is_empty() {
769+
lines.push(format!(" declared by: {}", option.declared_by));
770+
}
765771
if !option.description.is_empty() {
766772
lines.push(format!(" {}", option.description));
767773
}

0 commit comments

Comments
 (0)