From d333d0da74a6461d5a805c389cc35747293791b7 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Thu, 19 Aug 2021 11:46:01 +1000 Subject: [PATCH] allow adjusting tag case in rename https://forums.ankiweb.net/t/2-1-46-renaming-tags-to-tags-not-working/12426 --- rslib/src/tags/register.rs | 18 ++++++++++-------- rslib/src/tags/rename.rs | 17 +++++++++++------ 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/rslib/src/tags/register.rs b/rslib/src/tags/register.rs index 608a9622e..b2e902224 100644 --- a/rslib/src/tags/register.rs +++ b/rslib/src/tags/register.rs @@ -73,11 +73,7 @@ impl Collection { /// Create a tag object, normalize text, and match parents/existing case if available. /// True if tag is new. pub(super) fn prepare_tag_for_registering(&self, tag: &mut Tag) -> Result { - let normalized_name = normalize_tag_name(&tag.name); - if normalized_name.is_empty() { - // this should not be possible - return Err(AnkiError::invalid_input("blank tag")); - } + let normalized_name = normalize_tag_name(&tag.name)?; if let Some(existing_tag) = self.storage.get_tag(&normalized_name)? { tag.name = existing_tag.name; Ok(false) @@ -99,7 +95,7 @@ impl Collection { impl Collection { /// If parent tag(s) exist and differ in case, return a rewritten tag. - fn adjusted_case_for_parents(&self, tag: &str) -> Result> { + pub(super) fn adjusted_case_for_parents(&self, tag: &str) -> Result> { if let Some(parent_tag) = self.first_existing_parent_tag(tag)? { let child_split: Vec<_> = tag.split("::").collect(); let parent_count = parent_tag.matches("::").count() + 1; @@ -144,8 +140,8 @@ fn normalized_tag_name_component(comp: &str) -> Cow { } } -fn normalize_tag_name(name: &str) -> Cow { - if name +pub(super) fn normalize_tag_name(name: &str) -> Result> { + let normalized_name: Cow = if name .split("::") .any(|comp| matches!(normalized_tag_name_component(comp), Cow::Owned(_))) { @@ -157,6 +153,12 @@ fn normalize_tag_name(name: &str) -> Cow { } else { // no changes required name.into() + }; + if normalized_name.is_empty() { + // this should not be possible + Err(AnkiError::invalid_input("blank tag")) + } else { + Ok(normalized_name) } } diff --git a/rslib/src/tags/rename.rs b/rslib/src/tags/rename.rs index 0547d6190..3c427629b 100644 --- a/rslib/src/tags/rename.rs +++ b/rslib/src/tags/rename.rs @@ -1,8 +1,9 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -use super::{is_tag_separator, matcher::TagMatcher, Tag}; +use super::{is_tag_separator, matcher::TagMatcher}; use crate::prelude::*; +use crate::tags::register::normalize_tag_name; impl Collection { /// Rename a given tag and its children on all notes that reference it, returning changed @@ -29,10 +30,14 @@ impl Collection { let usn = self.usn()?; - // match existing case if available, and ensure normalized. - let mut tag = Tag::new(new_prefix.to_string(), usn); - self.prepare_tag_for_registering(&mut tag)?; - let new_prefix = &tag.name; + // ensure normalized+matching parent case, but not case of existing tag. + // The matching of parent case is mainly to be consistent with the way + // decks are handled. + let new_prefix = normalize_tag_name(new_prefix)?; + let new_prefix = self + .adjusted_case_for_parents(&new_prefix)? + .map(Into::into) + .unwrap_or(new_prefix); // gather tags that need replacing let mut re = TagMatcher::new(old_prefix)?; @@ -53,7 +58,7 @@ impl Collection { // replace tags for mut note in matched_notes { let original = note.clone(); - note.tags = re.replace(¬e.tags, new_prefix); + note.tags = re.replace(¬e.tags, &new_prefix); note.set_modified(usn); self.update_note_tags_undoable(¬e, original)?; }