+225 -220 +/-12 browse
1 | diff --git a/.cargo/config.toml b/.cargo/config.toml |
2 | deleted file mode 100644 |
3 | index f0ad4ff..0000000 |
4 | --- a/.cargo/config.toml |
5 | +++ /dev/null |
6 | @@ -1,2 +0,0 @@ |
7 | - [env] |
8 | - PCRE2_SYS_STATIC = "1" |
9 | diff --git a/BUILD.md b/BUILD.md |
10 | index 942166d..e564309 100644 |
11 | --- a/BUILD.md |
12 | +++ b/BUILD.md |
13 | @@ -28,10 +28,6 @@ Some functionality is held behind "feature gates", or compile-time flags. The fo |
14 | - `jmap` provides support for connecting to a jmap server and use it as a mail backend (on by default) |
15 | - `sqlite3` provides support for builting fast search indexes in local sqlite3 databases (on by default) |
16 | - `cli-docs` includes the manpage documentation compiled by either `mandoc` or `man` binary to plain text in `meli`'s command line. Embedded documentation can be viewed with the subcommand `meli man [PAGE]` (on by default). |
17 | - - `regexp` provides experimental support for theming some e-mail fields based |
18 | - on regular expressions. |
19 | - It uses the `pcre2` library. |
20 | - Since it's actual use in the code is very limited, it is not recommended to use this (off by default). |
21 | - `static` and `*-static` bundle C libraries in dependencies so that you don't need them installed in your system (on by default). |
22 | |
23 | Though not a feature, the presence of the environment variable `UNICODE_REGENERATE_TABLES` in compile-time of the `melib` crate will force the regeneration of unicode tables. |
24 | diff --git a/Cargo.lock b/Cargo.lock |
25 | index 658b502..b927dba 100644 |
26 | --- a/Cargo.lock |
27 | +++ b/Cargo.lock |
28 | @@ -325,7 +325,6 @@ version = "1.0.83" |
29 | source = "registry+https://github.com/rust-lang/crates.io-index" |
30 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" |
31 | dependencies = [ |
32 | - "jobserver", |
33 | "libc", |
34 | ] |
35 | |
36 | @@ -1096,15 +1095,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
37 | checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" |
38 | |
39 | [[package]] |
40 | - name = "jobserver" |
41 | - version = "0.1.26" |
42 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
43 | - checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" |
44 | - dependencies = [ |
45 | - "libc", |
46 | - ] |
47 | - |
48 | - [[package]] |
49 | name = "js-sys" |
50 | version = "0.3.64" |
51 | source = "registry+https://github.com/rust-lang/crates.io-index" |
52 | @@ -1292,7 +1282,6 @@ dependencies = [ |
53 | "melib", |
54 | "nix", |
55 | "notify-rust", |
56 | - "pcre2", |
57 | "predicates", |
58 | "proc-macro2", |
59 | "quote", |
60 | @@ -1595,29 +1584,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
61 | checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" |
62 | |
63 | [[package]] |
64 | - name = "pcre2" |
65 | - version = "0.2.4" |
66 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
67 | - checksum = "486aca7e74edb8cab09a48d461177f450a5cca3b55e61d139f7552190e2bbcf5" |
68 | - dependencies = [ |
69 | - "libc", |
70 | - "log", |
71 | - "pcre2-sys", |
72 | - "thread_local", |
73 | - ] |
74 | - |
75 | - [[package]] |
76 | - name = "pcre2-sys" |
77 | - version = "0.2.6" |
78 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
79 | - checksum = "ae234f441970dbd52d4e29bee70f3b56ca83040081cb2b55b7df772b16e0b06e" |
80 | - dependencies = [ |
81 | - "cc", |
82 | - "libc", |
83 | - "pkg-config", |
84 | - ] |
85 | - |
86 | - [[package]] |
87 | name = "percent-encoding" |
88 | version = "2.3.0" |
89 | source = "registry+https://github.com/rust-lang/crates.io-index" |
90 | diff --git a/meli/Cargo.toml b/meli/Cargo.toml |
91 | index 34cfc54..1532baa 100644 |
92 | --- a/meli/Cargo.toml |
93 | +++ b/meli/Cargo.toml |
94 | @@ -46,12 +46,6 @@ termion = { version = "1.5.1", default-features = false } |
95 | toml = { version = "0.8", default-features = false, features = ["display","preserve_order","parse"] } |
96 | xdg = { version = "2.1.0" } |
97 | |
98 | - [dependencies.pcre2] |
99 | - # An [env] entry in .cargo/config.toml should force a static build instead of |
100 | - # looking for a system library. |
101 | - version = "0.2.3" |
102 | - optional = true |
103 | - |
104 | [features] |
105 | default = ["sqlite3", "notmuch", "smtp", "dbus-notifications", "gpgme", "cli-docs", "jmap", "static"] |
106 | notmuch = ["melib/notmuch"] |
107 | @@ -59,7 +53,6 @@ jmap = ["melib/jmap"] |
108 | sqlite3 = ["melib/sqlite3"] |
109 | smtp = ["melib/smtp"] |
110 | smtp-trace = ["smtp", "melib/smtp-trace"] |
111 | - regexp = ["dep:pcre2"] |
112 | dbus-notifications = ["dep:notify-rust"] |
113 | cli-docs = ["dep:flate2"] |
114 | svgscreenshot = ["dep:svg_crate"] |
115 | diff --git a/meli/src/conf/data_types/mod.rs b/meli/src/conf/data_types/mod.rs |
116 | index c9a7e34..e657d7c 100644 |
117 | --- a/meli/src/conf/data_types/mod.rs |
118 | +++ b/meli/src/conf/data_types/mod.rs |
119 | @@ -21,6 +21,7 @@ |
120 | // SPDX-License-Identifier: EUPL-1.2 OR GPL-3.0-or-later |
121 | |
122 | pub mod dotaddressable; |
123 | + pub mod regex_pattern; |
124 | |
125 | use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; |
126 | |
127 | diff --git a/meli/src/conf/data_types/regex_pattern.rs b/meli/src/conf/data_types/regex_pattern.rs |
128 | new file mode 100644 |
129 | index 0000000..0d27b4f |
130 | --- /dev/null |
131 | +++ b/meli/src/conf/data_types/regex_pattern.rs |
132 | @@ -0,0 +1,215 @@ |
133 | + // |
134 | + // meli |
135 | + // |
136 | + // Copyright 2024 Emmanouil Pitsidianakis <manos@pitsidianak.is> |
137 | + // |
138 | + // This file is part of meli. |
139 | + // |
140 | + // meli is free software: you can redistribute it and/or modify |
141 | + // it under the terms of the GNU General Public License as published by |
142 | + // the Free Software Foundation, either version 3 of the License, or |
143 | + // (at your option) any later version. |
144 | + // |
145 | + // meli is distributed in the hope that it will be useful, |
146 | + // but WITHOUT ANY WARRANTY; without even the implied warranty of |
147 | + // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
148 | + // GNU General Public License for more details. |
149 | + // |
150 | + // You should have received a copy of the GNU General Public License |
151 | + // along with meli. If not, see <http://www.gnu.org/licenses/>. |
152 | + // |
153 | + // SPDX-License-Identifier: EUPL-1.2 OR GPL-3.0-or-later |
154 | + |
155 | + use melib::error::{Result, WrapResultIntoError}; |
156 | + use serde::{Deserialize, Deserializer}; |
157 | + |
158 | + const fn lf_val() -> u8 { |
159 | + b'\n' |
160 | + } |
161 | + |
162 | + #[derive(Debug, Clone)] |
163 | + pub enum RegexValue { |
164 | + Default { |
165 | + pattern: regex::Regex, |
166 | + }, |
167 | + Builder { |
168 | + pattern: regex::Regex, |
169 | + options: RegexOptions, |
170 | + }, |
171 | + } |
172 | + |
173 | + impl RegexValue { |
174 | + pub fn new_with_options(pattern: &str, o: RegexOptions) -> Result<Self> { |
175 | + let mut b = regex::RegexBuilder::new(pattern); |
176 | + b.unicode(o.unicode) |
177 | + .case_insensitive(o.case_insensitive) |
178 | + .multi_line(o.multi_line) |
179 | + .dot_matches_new_line(o.dot_matches_new_line) |
180 | + .crlf(o.crlf) |
181 | + .line_terminator(o.line_terminator) |
182 | + .swap_greed(o.swap_greed) |
183 | + .ignore_whitespace(o.ignore_whitespace) |
184 | + .octal(o.octal); |
185 | + if let Some(v) = o.size_limit { |
186 | + b.size_limit(v); |
187 | + } |
188 | + let pattern = b |
189 | + .build() |
190 | + .wrap_err(|| format!("Could not compile regular expression `{}`", pattern))?; |
191 | + Ok(Self::Builder { |
192 | + pattern, |
193 | + options: o, |
194 | + }) |
195 | + } |
196 | + |
197 | + pub fn find_iter<'w, 's>(&'w self, s: &'s str) -> FindIter<'w, 's> { |
198 | + let (Self::Default { pattern } | Self::Builder { pattern, .. }) = self; |
199 | + FindIter { |
200 | + iter: pattern.find_iter(s), |
201 | + char_indices: s.char_indices(), |
202 | + char_offset: 0, |
203 | + } |
204 | + } |
205 | + } |
206 | + |
207 | + #[derive(Clone, Copy, Serialize, Deserialize, Debug)] |
208 | + pub struct RegexOptions { |
209 | + #[serde(default = "crate::conf::true_val")] |
210 | + unicode: bool, |
211 | + #[serde(default = "crate::conf::false_val")] |
212 | + case_insensitive: bool, |
213 | + #[serde(default = "crate::conf::false_val")] |
214 | + multi_line: bool, |
215 | + #[serde(default = "crate::conf::false_val")] |
216 | + dot_matches_new_line: bool, |
217 | + #[serde(default = "crate::conf::false_val")] |
218 | + crlf: bool, |
219 | + #[serde(default = "lf_val")] |
220 | + line_terminator: u8, |
221 | + #[serde(default = "crate::conf::false_val")] |
222 | + swap_greed: bool, |
223 | + #[serde(default = "crate::conf::false_val")] |
224 | + ignore_whitespace: bool, |
225 | + #[serde(default = "crate::conf::false_val")] |
226 | + octal: bool, |
227 | + #[serde(default, skip_serializing_if = "Option::is_none")] |
228 | + size_limit: Option<usize>, |
229 | + } |
230 | + |
231 | + impl Default for RegexOptions { |
232 | + fn default() -> Self { |
233 | + Self { |
234 | + unicode: true, |
235 | + case_insensitive: false, |
236 | + multi_line: false, |
237 | + dot_matches_new_line: false, |
238 | + crlf: false, |
239 | + line_terminator: b'\n', |
240 | + swap_greed: false, |
241 | + ignore_whitespace: false, |
242 | + octal: false, |
243 | + size_limit: None, |
244 | + } |
245 | + } |
246 | + } |
247 | + |
248 | + impl<'de> Deserialize<'de> for RegexValue { |
249 | + fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error> |
250 | + where |
251 | + D: Deserializer<'de>, |
252 | + { |
253 | + // [ref:FIXME]: clippy false positive, remove when resolved. |
254 | + #![allow(clippy::collection_is_never_read)] |
255 | + |
256 | + #[derive(Deserialize)] |
257 | + #[serde(untagged)] |
258 | + enum Inner<'a> { |
259 | + Default { |
260 | + pattern: &'a str, |
261 | + }, |
262 | + Builder { |
263 | + pattern: &'a str, |
264 | + #[serde(flatten)] |
265 | + o: RegexOptions, |
266 | + }, |
267 | + } |
268 | + let s = <Inner>::deserialize(deserializer); |
269 | + Ok( |
270 | + match s.map_err(|err| { |
271 | + serde::de::Error::custom(format!( |
272 | + r#"expected one of "true", "false", "ask", found `{}`"#, |
273 | + err |
274 | + )) |
275 | + })? { |
276 | + Inner::Default { pattern } => Self::Default { |
277 | + pattern: regex::Regex::new(pattern).map_err(|err| { |
278 | + serde::de::Error::custom(format!( |
279 | + "Could not compile regular expression `{}`: {}", |
280 | + pattern, err |
281 | + )) |
282 | + })?, |
283 | + }, |
284 | + Inner::Builder { pattern, o } => { |
285 | + let mut b = regex::RegexBuilder::new(pattern); |
286 | + b.unicode(o.unicode) |
287 | + .case_insensitive(o.case_insensitive) |
288 | + .multi_line(o.multi_line) |
289 | + .dot_matches_new_line(o.dot_matches_new_line) |
290 | + .crlf(o.crlf) |
291 | + .line_terminator(o.line_terminator) |
292 | + .swap_greed(o.swap_greed) |
293 | + .ignore_whitespace(o.ignore_whitespace) |
294 | + .octal(o.octal); |
295 | + if let Some(v) = o.size_limit { |
296 | + b.size_limit(v); |
297 | + } |
298 | + let pattern = b.build().map_err(|err| { |
299 | + serde::de::Error::custom(format!( |
300 | + "Could not compile regular expression `{}`: {}", |
301 | + pattern, err |
302 | + )) |
303 | + })?; |
304 | + Self::Builder { |
305 | + pattern, |
306 | + options: o, |
307 | + } |
308 | + } |
309 | + }, |
310 | + ) |
311 | + } |
312 | + } |
313 | + |
314 | + pub struct FindIter<'r, 's> { |
315 | + iter: regex::Matches<'r, 's>, |
316 | + char_indices: std::str::CharIndices<'s>, |
317 | + char_offset: usize, |
318 | + } |
319 | + |
320 | + impl<'r, 's> Iterator for FindIter<'r, 's> { |
321 | + type Item = (usize, usize); |
322 | + |
323 | + fn next(&mut self) -> Option<Self::Item> { |
324 | + let next_byte_offset = self.iter.next()?; |
325 | + |
326 | + let mut next_char_index = self.char_indices.next()?; |
327 | + |
328 | + while next_byte_offset.start() < next_char_index.0 { |
329 | + self.char_offset += 1; |
330 | + next_char_index = self.char_indices.next()?; |
331 | + } |
332 | + let start = self.char_offset; |
333 | + |
334 | + while next_byte_offset.end() |
335 | + > self |
336 | + .char_indices |
337 | + .next() |
338 | + .map(|(v, _)| v) |
339 | + .unwrap_or_else(|| next_byte_offset.end()) |
340 | + { |
341 | + self.char_offset += 1; |
342 | + } |
343 | + let end = self.char_offset + 1; |
344 | + |
345 | + Some((start, end)) |
346 | + } |
347 | + } |
348 | diff --git a/meli/src/conf/themes.rs b/meli/src/conf/themes.rs |
349 | index a5832bd..606a50b 100644 |
350 | --- a/meli/src/conf/themes.rs |
351 | +++ b/meli/src/conf/themes.rs |
352 | @@ -43,6 +43,7 @@ use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; |
353 | use smallvec::SmallVec; |
354 | |
355 | use crate::{ |
356 | + conf::data_types::regex_pattern::{RegexOptions, RegexValue}, |
357 | terminal::{Attr, Color}, |
358 | Context, |
359 | }; |
360 | @@ -520,30 +521,23 @@ pub struct Themes { |
361 | pub struct Theme { |
362 | color_aliases: IndexMap<Cow<'static, str>, ThemeValue<Color>>, |
363 | attr_aliases: IndexMap<Cow<'static, str>, ThemeValue<Attr>>, |
364 | - #[cfg(feature = "regexp")] |
365 | text_format_regexps: IndexMap<Cow<'static, str>, SmallVec<[TextFormatterSetting; 32]>>, |
366 | pub keys: IndexMap<Cow<'static, str>, ThemeAttributeInner>, |
367 | } |
368 | |
369 | - #[cfg(feature = "regexp")] |
370 | pub use regexp::text_format_regexps; |
371 | - #[cfg(feature = "regexp")] |
372 | use regexp::*; |
373 | |
374 | - #[cfg(feature = "regexp")] |
375 | mod regexp { |
376 | use super::*; |
377 | - use crate::terminal::FormatTag; |
378 | + use crate::{conf::data_types::regex_pattern::RegexValue, terminal::FormatTag}; |
379 | |
380 | pub(super) const DEFAULT_TEXT_FORMATTER_KEYS: &[&str] = |
381 | &["pager.envelope.body", "listing.from", "listing.subject"]; |
382 | |
383 | - #[derive(Clone)] |
384 | - pub struct RegexpWrapper(pub pcre2::bytes::Regex); |
385 | - |
386 | #[derive(Clone, Debug)] |
387 | pub(super) struct TextFormatterSetting { |
388 | - pub(super) regexp: RegexpWrapper, |
389 | + pub(super) regexp: RegexValue, |
390 | pub(super) fg: Option<ThemeValue<Color>>, |
391 | pub(super) bg: Option<ThemeValue<Color>>, |
392 | pub(super) attrs: Option<ThemeValue<Attr>>, |
393 | @@ -552,108 +546,10 @@ mod regexp { |
394 | |
395 | #[derive(Clone, Debug)] |
396 | pub struct TextFormatter<'r> { |
397 | - pub regexp: &'r RegexpWrapper, |
398 | + pub regexp: &'r RegexValue, |
399 | pub tag: FormatTag, |
400 | } |
401 | |
402 | - impl Default for RegexpWrapper { |
403 | - fn default() -> Self { |
404 | - Self(pcre2::bytes::Regex::new("").unwrap()) |
405 | - } |
406 | - } |
407 | - |
408 | - impl std::fmt::Debug for RegexpWrapper { |
409 | - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { |
410 | - std::fmt::Debug::fmt(self.0.as_str(), fmt) |
411 | - } |
412 | - } |
413 | - |
414 | - impl std::hash::Hash for RegexpWrapper { |
415 | - fn hash<H: std::hash::Hasher>(&self, state: &mut H) { |
416 | - self.0.as_str().hash(state) |
417 | - } |
418 | - } |
419 | - |
420 | - impl Eq for RegexpWrapper {} |
421 | - |
422 | - impl PartialEq for RegexpWrapper { |
423 | - fn eq(&self, other: &Self) -> bool { |
424 | - self.0.as_str().eq(other.0.as_str()) |
425 | - } |
426 | - } |
427 | - |
428 | - impl RegexpWrapper { |
429 | - pub(super) fn new( |
430 | - pattern: &str, |
431 | - caseless: bool, |
432 | - dotall: bool, |
433 | - extended: bool, |
434 | - multi_line: bool, |
435 | - ucp: bool, |
436 | - jit_if_available: bool, |
437 | - ) -> std::result::Result<Self, pcre2::Error> { |
438 | - Ok(Self( |
439 | - pcre2::bytes::RegexBuilder::new() |
440 | - .caseless(caseless) |
441 | - .dotall(dotall) |
442 | - .extended(extended) |
443 | - .multi_line(multi_line) |
444 | - .ucp(ucp) |
445 | - .jit_if_available(jit_if_available) |
446 | - .build(pattern)?, |
447 | - )) |
448 | - } |
449 | - |
450 | - pub fn find_iter<'w, 's>(&'w self, s: &'s str) -> FindIter<'w, 's> { |
451 | - FindIter { |
452 | - pcre_iter: self.0.find_iter(s.as_bytes()), |
453 | - char_indices: s.char_indices(), |
454 | - char_offset: 0, |
455 | - } |
456 | - } |
457 | - } |
458 | - |
459 | - pub struct FindIter<'r, 's> { |
460 | - pcre_iter: pcre2::bytes::Matches<'r, 's>, |
461 | - char_indices: std::str::CharIndices<'s>, |
462 | - char_offset: usize, |
463 | - } |
464 | - |
465 | - impl<'r, 's> Iterator for FindIter<'r, 's> { |
466 | - type Item = (usize, usize); |
467 | - |
468 | - fn next(&mut self) -> Option<Self::Item> { |
469 | - loop { |
470 | - let next_byte_offset = self.pcre_iter.next()?; |
471 | - if next_byte_offset.is_err() { |
472 | - continue; |
473 | - } |
474 | - let next_byte_offset = next_byte_offset.unwrap(); |
475 | - |
476 | - let mut next_char_index = self.char_indices.next()?; |
477 | - |
478 | - while next_byte_offset.start() < next_char_index.0 { |
479 | - self.char_offset += 1; |
480 | - next_char_index = self.char_indices.next()?; |
481 | - } |
482 | - let start = self.char_offset; |
483 | - |
484 | - while next_byte_offset.end() |
485 | - > self |
486 | - .char_indices |
487 | - .next() |
488 | - .map(|(v, _)| v) |
489 | - .unwrap_or_else(|| next_byte_offset.end()) |
490 | - { |
491 | - self.char_offset += 1; |
492 | - } |
493 | - let end = self.char_offset + 1; |
494 | - |
495 | - return Some((start, end)); |
496 | - } |
497 | - } |
498 | - } |
499 | - |
500 | #[inline(always)] |
501 | pub fn text_format_regexps<'ctx>( |
502 | context: &'ctx Context, |
503 | @@ -775,14 +671,6 @@ impl<'de> Deserialize<'de> for Themes { |
504 | where |
505 | D: Deserializer<'de>, |
506 | { |
507 | - #[cfg(feature = "regexp")] |
508 | - const fn false_val() -> bool { |
509 | - false |
510 | - } |
511 | - #[cfg(feature = "regexp")] |
512 | - const fn true_val() -> bool { |
513 | - true |
514 | - } |
515 | #[derive(Deserialize)] |
516 | struct ThemesOptions { |
517 | #[serde(default)] |
518 | @@ -798,27 +686,15 @@ impl<'de> Deserialize<'de> for Themes { |
519 | color_aliases: IndexMap<Cow<'static, str>, ThemeValue<Color>>, |
520 | #[serde(default)] |
521 | attr_aliases: IndexMap<Cow<'static, str>, ThemeValue<Attr>>, |
522 | - #[cfg(feature = "regexp")] |
523 | #[serde(default)] |
524 | text_format_regexps: IndexMap<Cow<'static, str>, IndexMap<String, RegexpOptions>>, |
525 | #[serde(flatten, default)] |
526 | keys: IndexMap<Cow<'static, str>, ThemeAttributeInnerOptions>, |
527 | } |
528 | - #[cfg(feature = "regexp")] |
529 | #[derive(Default, Deserialize)] |
530 | struct RegexpOptions { |
531 | - #[serde(default = "false_val")] |
532 | - caseless: bool, |
533 | - #[serde(default = "false_val")] |
534 | - dotall: bool, |
535 | - #[serde(default = "false_val")] |
536 | - extended: bool, |
537 | - #[serde(default = "false_val")] |
538 | - multi_line: bool, |
539 | - #[serde(default = "true_val")] |
540 | - ucp: bool, |
541 | - #[serde(default = "false_val")] |
542 | - jit_if_available: bool, |
543 | + #[serde(flatten)] |
544 | + o: RegexOptions, |
545 | #[serde(default)] |
546 | priority: u8, |
547 | #[serde(flatten)] |
548 | @@ -867,19 +743,10 @@ impl<'de> Deserialize<'de> for Themes { |
549 | } |
550 | ret.light.color_aliases = s.light.color_aliases; |
551 | ret.light.attr_aliases = s.light.attr_aliases; |
552 | - #[cfg(feature = "regexp")] |
553 | for (k, v) in s.light.text_format_regexps { |
554 | let mut acc = SmallVec::new(); |
555 | for (rs, v) in v { |
556 | - match RegexpWrapper::new( |
557 | - &rs, |
558 | - v.caseless, |
559 | - v.dotall, |
560 | - v.extended, |
561 | - v.multi_line, |
562 | - v.ucp, |
563 | - v.jit_if_available, |
564 | - ) { |
565 | + match RegexValue::new_with_options(&rs, v.o) { |
566 | Ok(regexp) => { |
567 | acc.push(TextFormatterSetting { |
568 | regexp, |
569 | @@ -922,19 +789,10 @@ impl<'de> Deserialize<'de> for Themes { |
570 | } |
571 | ret.dark.color_aliases = s.dark.color_aliases; |
572 | ret.dark.attr_aliases = s.dark.attr_aliases; |
573 | - #[cfg(feature = "regexp")] |
574 | for (k, v) in s.dark.text_format_regexps { |
575 | let mut acc = SmallVec::new(); |
576 | for (rs, v) in v { |
577 | - match RegexpWrapper::new( |
578 | - &rs, |
579 | - v.caseless, |
580 | - v.dotall, |
581 | - v.extended, |
582 | - v.multi_line, |
583 | - v.ucp, |
584 | - v.jit_if_available, |
585 | - ) { |
586 | + match RegexValue::new_with_options(&rs, v.o) { |
587 | Ok(regexp) => { |
588 | acc.push(TextFormatterSetting { |
589 | regexp, |
590 | @@ -980,19 +838,10 @@ impl<'de> Deserialize<'de> for Themes { |
591 | } |
592 | t.color_aliases = theme.color_aliases; |
593 | t.attr_aliases = theme.attr_aliases; |
594 | - #[cfg(feature = "regexp")] |
595 | for (k, v) in theme.text_format_regexps { |
596 | let mut acc = SmallVec::new(); |
597 | for (rs, v) in v { |
598 | - match RegexpWrapper::new( |
599 | - &rs, |
600 | - v.caseless, |
601 | - v.dotall, |
602 | - v.extended, |
603 | - v.multi_line, |
604 | - v.ucp, |
605 | - v.jit_if_available, |
606 | - ) { |
607 | + match RegexValue::new_with_options(&rs, v.o) { |
608 | Ok(regexp) => { |
609 | acc.push(TextFormatterSetting { |
610 | regexp, |
611 | @@ -1126,7 +975,6 @@ impl Themes { |
612 | } |
613 | })) |
614 | .collect::<SmallVec<[(Option<_>, &'_ str, &'_ str, &'_ str); 128]>>(); |
615 | - #[cfg(feature = "regexp")] |
616 | { |
617 | for (key, v) in &theme.text_format_regexps { |
618 | if !regexp::DEFAULT_TEXT_FORMATTER_KEYS.contains(&key.as_ref()) { |
619 | @@ -1759,7 +1607,6 @@ impl Default for Themes { |
620 | keys: light, |
621 | attr_aliases: Default::default(), |
622 | color_aliases: Default::default(), |
623 | - #[cfg(feature = "regexp")] |
624 | text_format_regexps: DEFAULT_TEXT_FORMATTER_KEYS |
625 | .iter() |
626 | .map(|&k| (k.into(), SmallVec::new())) |
627 | @@ -1769,7 +1616,6 @@ impl Default for Themes { |
628 | keys: dark, |
629 | attr_aliases: Default::default(), |
630 | color_aliases: Default::default(), |
631 | - #[cfg(feature = "regexp")] |
632 | text_format_regexps: DEFAULT_TEXT_FORMATTER_KEYS |
633 | .iter() |
634 | .map(|&k| (k.into(), SmallVec::new())) |
635 | diff --git a/meli/src/mail/listing/compact.rs b/meli/src/mail/listing/compact.rs |
636 | index e9d8d1a..5c5be5f 100644 |
637 | --- a/meli/src/mail/listing/compact.rs |
638 | +++ b/meli/src/mail/listing/compact.rs |
639 | @@ -1221,7 +1221,6 @@ impl CompactListing { |
640 | .set_attrs(row_attr.attrs) |
641 | .set_ch(' '); |
642 | } |
643 | - #[cfg(feature = "regexp")] |
644 | { |
645 | for text_formatter in crate::conf::text_format_regexps(context, "listing.from") { |
646 | let t = columns[2].grid_mut().insert_tag(text_formatter.tag); |
647 | @@ -1280,7 +1279,6 @@ impl CompactListing { |
648 | None, |
649 | None, |
650 | )); |
651 | - #[cfg(feature = "regexp")] |
652 | { |
653 | for text_formatter in |
654 | crate::conf::text_format_regexps(context, "listing.subject") |
655 | diff --git a/meli/src/mail/listing/plain.rs b/meli/src/mail/listing/plain.rs |
656 | index 558e895..8dffae8 100644 |
657 | --- a/meli/src/mail/listing/plain.rs |
658 | +++ b/meli/src/mail/listing/plain.rs |
659 | @@ -931,7 +931,6 @@ impl PlainListing { |
660 | None, |
661 | None, |
662 | ); |
663 | - #[cfg(feature = "regexp")] |
664 | { |
665 | for text_formatter in crate::conf::text_format_regexps(context, "listing.from") |
666 | { |
667 | @@ -1004,7 +1003,6 @@ impl PlainListing { |
668 | None, |
669 | None, |
670 | )); |
671 | - #[cfg(feature = "regexp")] |
672 | { |
673 | for text_formatter in |
674 | crate::conf::text_format_regexps(context, "listing.subject") |
675 | @@ -1212,7 +1210,6 @@ impl PlainListing { |
676 | None, |
677 | None, |
678 | )); |
679 | - #[cfg(feature = "regexp")] |
680 | { |
681 | for text_formatter in crate::conf::text_format_regexps(context, "listing.subject") { |
682 | let t = columns[4].grid_mut().insert_tag(text_formatter.tag); |
683 | diff --git a/meli/src/mail/listing/thread.rs b/meli/src/mail/listing/thread.rs |
684 | index b32c4ac..862f4e3 100644 |
685 | --- a/meli/src/mail/listing/thread.rs |
686 | +++ b/meli/src/mail/listing/thread.rs |
687 | @@ -987,7 +987,6 @@ impl ThreadListing { |
688 | None, |
689 | None, |
690 | ); |
691 | - #[cfg(feature = "regexp")] |
692 | { |
693 | for text_formatter in crate::conf::text_format_regexps(context, "listing.from") |
694 | { |
695 | @@ -1060,7 +1059,6 @@ impl ThreadListing { |
696 | None, |
697 | None, |
698 | )); |
699 | - #[cfg(feature = "regexp")] |
700 | { |
701 | for text_formatter in |
702 | crate::conf::text_format_regexps(context, "listing.subject") |
703 | diff --git a/meli/src/subcommands.rs b/meli/src/subcommands.rs |
704 | index efdecb2..be36097 100644 |
705 | --- a/meli/src/subcommands.rs |
706 | +++ b/meli/src/subcommands.rs |
707 | @@ -115,8 +115,6 @@ pub fn compiled_with() -> Result<()> { |
708 | println!("sqlite3"); |
709 | #[cfg(feature = "smtp")] |
710 | println!("smtp"); |
711 | - #[cfg(feature = "regexp")] |
712 | - println!("regexp"); |
713 | #[cfg(feature = "dbus-notifications")] |
714 | println!("dbus-notifications"); |
715 | #[cfg(feature = "cli-docs")] |
716 | diff --git a/meli/src/utilities/pager.rs b/meli/src/utilities/pager.rs |
717 | index 3532462..ca4ea4d 100644 |
718 | --- a/meli/src/utilities/pager.rs |
719 | +++ b/meli/src/utilities/pager.rs |
720 | @@ -393,7 +393,6 @@ impl Pager { |
721 | } |
722 | |
723 | { |
724 | - #[cfg(feature = "regexp")] |
725 | { |
726 | let area3 = area; |
727 | for text_formatter in |