From 90047c22b56eeb2abee2a39dc233ba60da9654a6 Mon Sep 17 00:00:00 2001 From: randogoth Date: Sat, 24 Oct 2026 21:28:00 +0300 Subject: [PATCH] fix: parse imported and embedded tags like CLI arguments so hyphenated tags survive --- orvanitag/orvani.py | 20 ++++++++------------ tests/test_orvani.py | 11 +++++++++++ tests/test_plugins.py | 9 +++++++++ 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/orvanitag/orvani.py b/orvanitag/orvani.py index b3ff49d..e1fbaa1 100644 --- a/orvanitag/orvani.py +++ b/orvanitag/orvani.py @@ -1,5 +1,4 @@ import os -import re import json import shutil import tomllib @@ -42,7 +41,6 @@ ERRORS: class OrvaniTag: ENABLE_PLUGINS = True # Toggle use of plugins - REGEX = r'\s*([@+]\w+|#\w+)' def __init__(self, path: str=CONTEXT_FILE, cache: str=CACHE_FILE, contexts=CONTEXTS, plugins:list=DEFAULT_PLUGINS): """ @@ -158,12 +156,14 @@ class OrvaniTag: # Add each argument list element to context dict based on the # prefix symbols defined in the schema - if arg[0] in self.SCHEMA.values(): + tag = arg[1:].replace(',', '') + if arg[0] in self.SCHEMA.values() and tag: for context_key in self.SCHEMA.keys(): if self.SCHEMA[context_key] != None and arg.startswith(self.SCHEMA[context_key]): - context[context_key].append(arg[1:].replace(',', '')) + if tag not in context[context_key]: + context[context_key].append(tag) else: - # No prefix, so it is part of the note + # No prefix (or a bare prefix), so it is part of the note note.append(arg) if note: @@ -325,14 +325,10 @@ class OrvaniTag: def __get_argv(self, context_string: str): """ - Make a list of args from a context string to pass as an *argv parameter + Make a list of args from a context string to pass as an *argv parameter. + Words are classified by __context, the same way as command line arguments. """ - - tags = re.findall(self.REGEX, context_string) - note = re.sub(self.REGEX, '', context_string).lstrip() - argv = ' '.join(tags).split(' ') + [note] - argv = [x for x in dict.fromkeys(argv) if x != ''] # make unique and remove empty items - return argv + return context_string.split() def add(self, file: str, *argv: str): diff --git a/tests/test_orvani.py b/tests/test_orvani.py index c45c0ec..4689167 100644 --- a/tests/test_orvani.py +++ b/tests/test_orvani.py @@ -243,3 +243,14 @@ def test_import_skips_known_tags_and_empty_lines(tree): (tree / 'context.txt').write_text('./a.mp3 --- #lofi #snare\n./b.mp3 --- \n') assert OrvaniTag().load('context.txt') == [0, 'context.txt', 1] assert lines(tree) == ['a.mp3 --- #lofi #snare'] + + +def test_import_keeps_hyphenated_tags(tree): + (tree / 'context.txt').write_text('./a.mp3 --- @home-office #lo-fi rock+roll take-2\n') + assert OrvaniTag().load('context.txt')[0] == 0 + assert lines(tree) == ['a.mp3 --- @home-office #lo-fi rock+roll take-2'] + + +def test_duplicate_and_bare_prefixes(tree): + OrvaniTag().add('a.mp3', '#lofi', '#lofi', 'C', '+', 'D') + assert lines(tree) == ['a.mp3 --- #lofi C + D'] diff --git a/tests/test_plugins.py b/tests/test_plugins.py index 50ee583..6706492 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -151,3 +151,12 @@ def test_write_ignores_configured_types_the_plugin_cannot_handle(cwd): OrvaniTag().add('doc.abc', '#lofi') assert OrvaniTag().write_metadata('doc.abc', 'pdf') == [4, ['.pdf'], 'pdf', True] assert (cwd / 'doc.abc').read_text() == 'not a pdf' + + +def test_pdf_keeps_hyphenated_tags(cwd): + writer = PdfWriter() + writer.add_blank_page(72, 72) + writer.add_metadata({'/Keywords': '+side-project #lo-fi'}) + writer.write(cwd / 'doc.pdf') + OrvaniTag().read_metadata('doc.pdf') + assert (cwd / orvani.CONTEXT_FILE).read_text() == 'doc.pdf --- +side-project #lo-fi\n'