fix globs not working in bulk tag add/remove
This commit is contained in:
parent
3d0d21e4bc
commit
9e53c84a35
@ -9,11 +9,9 @@ use crate::{
|
||||
err::Result,
|
||||
notes::field_checksum,
|
||||
notetype::NoteTypeID,
|
||||
text::matches_wildcard,
|
||||
text::{matches_wildcard, text_to_re},
|
||||
text::{normalize_to_nfc, strip_html_preserving_image_filenames, without_combining},
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use regex::{Captures, Regex};
|
||||
use std::{borrow::Cow, fmt::Write};
|
||||
|
||||
pub(crate) struct SqlWriter<'a> {
|
||||
@ -458,38 +456,6 @@ fn glob_to_re(glob: &str) -> Option<String> {
|
||||
Some(text_to_re(glob))
|
||||
}
|
||||
|
||||
/// Escape text, converting glob characters to regex syntax, then return.
|
||||
fn text_to_re(glob: &str) -> String {
|
||||
lazy_static! {
|
||||
static ref ESCAPED: Regex = Regex::new(r"(\\\\)?\\\*").unwrap();
|
||||
static ref GLOB: Regex = Regex::new(r"(\\\\)?[_%]").unwrap();
|
||||
}
|
||||
|
||||
let escaped = regex::escape(glob);
|
||||
|
||||
let text = ESCAPED.replace_all(&escaped, |caps: &Captures| {
|
||||
if caps.get(0).unwrap().as_str().len() == 2 {
|
||||
".*"
|
||||
} else {
|
||||
r"\*"
|
||||
}
|
||||
});
|
||||
|
||||
let text2 = GLOB.replace_all(&text, |caps: &Captures| {
|
||||
match caps.get(0).unwrap().as_str() {
|
||||
"_" => ".",
|
||||
"%" => ".*",
|
||||
other => {
|
||||
// strip off the escaping char
|
||||
&other[2..]
|
||||
}
|
||||
}
|
||||
.to_string()
|
||||
});
|
||||
|
||||
text2.into()
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub enum RequiredTable {
|
||||
Notes,
|
||||
|
@ -5,6 +5,7 @@ use crate::{
|
||||
collection::Collection,
|
||||
err::{AnkiError, Result},
|
||||
notes::{NoteID, TransformNoteOutput},
|
||||
text::text_to_re,
|
||||
{text::normalize_to_nfc, types::Usn},
|
||||
};
|
||||
use regex::{NoExpand, Regex, Replacer};
|
||||
@ -123,11 +124,7 @@ impl Collection {
|
||||
// generate regexps
|
||||
let tags = split_tags(tags)
|
||||
.map(|tag| {
|
||||
let tag = if regex {
|
||||
tag.into()
|
||||
} else {
|
||||
regex::escape(tag)
|
||||
};
|
||||
let tag = if regex { tag.into() } else { text_to_re(tag) };
|
||||
Regex::new(&format!("(?i){}", tag))
|
||||
.map_err(|_| AnkiError::invalid_input("invalid regex"))
|
||||
})
|
||||
@ -234,6 +231,10 @@ mod test {
|
||||
let note = col.storage.get_note(note.id)?.unwrap();
|
||||
assert_eq!(note.tags[0], "bar");
|
||||
|
||||
col.replace_tags_for_notes(&[note.id], "b*r", "baz", false)?;
|
||||
let note = col.storage.get_note(note.id)?.unwrap();
|
||||
assert_eq!(note.tags[0], "baz");
|
||||
|
||||
col.replace_tags_for_notes(&[note.id], "b.r", "baz", true)?;
|
||||
let note = col.storage.get_note(note.id)?.unwrap();
|
||||
assert_eq!(note.tags[0], "baz");
|
||||
|
@ -261,6 +261,38 @@ pub(crate) fn without_combining(s: &str) -> Cow<str> {
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Escape text, converting glob characters to regex syntax, then return.
|
||||
pub(crate) fn text_to_re(glob: &str) -> String {
|
||||
lazy_static! {
|
||||
static ref ESCAPED: Regex = Regex::new(r"(\\\\)?\\\*").unwrap();
|
||||
static ref GLOB: Regex = Regex::new(r"(\\\\)?[_%]").unwrap();
|
||||
}
|
||||
|
||||
let escaped = regex::escape(glob);
|
||||
|
||||
let text = ESCAPED.replace_all(&escaped, |caps: &Captures| {
|
||||
if caps.get(0).unwrap().as_str().len() == 2 {
|
||||
".*"
|
||||
} else {
|
||||
r"\*"
|
||||
}
|
||||
});
|
||||
|
||||
let text2 = GLOB.replace_all(&text, |caps: &Captures| {
|
||||
match caps.get(0).unwrap().as_str() {
|
||||
"_" => ".",
|
||||
"%" => ".*",
|
||||
other => {
|
||||
// strip off the escaping char
|
||||
&other[2..]
|
||||
}
|
||||
}
|
||||
.to_string()
|
||||
});
|
||||
|
||||
text2.into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::matches_wildcard;
|
||||
|
Loading…
Reference in New Issue
Block a user