Improve comment processing
This commit is contained in:
+32
-13
@@ -40,8 +40,8 @@ from novelwriter import SHARED
|
|||||||
from novelwriter.common import (
|
from novelwriter.common import (
|
||||||
checkInt, isHandle, isItemClass, isListInstance, isTitleTag, jsonEncode
|
checkInt, isHandle, isItemClass, isListInstance, isTitleTag, jsonEncode
|
||||||
)
|
)
|
||||||
from novelwriter.constants import nwFiles, nwKeyWords, nwHeaders
|
from novelwriter.constants import nwFiles, nwHeaders, nwKeyWords
|
||||||
from novelwriter.enum import nwComment, nwItemClass, nwItemType, nwItemLayout
|
from novelwriter.enum import nwComment, nwItemClass, nwItemLayout, nwItemType
|
||||||
from novelwriter.error import logException
|
from novelwriter.error import logException
|
||||||
from novelwriter.text.counting import standardCounter
|
from novelwriter.text.counting import standardCounter
|
||||||
|
|
||||||
@@ -1360,24 +1360,43 @@ class IndexHeading:
|
|||||||
# Text Processing Functions
|
# Text Processing Functions
|
||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
|
|
||||||
CLASSIFIERS = {
|
MODIFIERS = {
|
||||||
"synopsis": nwComment.SYNOPSIS,
|
"synopsis": nwComment.SYNOPSIS,
|
||||||
"short": nwComment.SHORT,
|
"short": nwComment.SHORT,
|
||||||
"note": nwComment.NOTE,
|
"note": nwComment.NOTE,
|
||||||
"footnote": nwComment.FOOTNOTE,
|
"footnote": nwComment.FOOTNOTE,
|
||||||
}
|
}
|
||||||
|
KEY_REQ = {
|
||||||
|
"synopsis": 0, # Key not allowed
|
||||||
|
"short": 0, # Key not allowed
|
||||||
|
"note": 1, # Key optional
|
||||||
|
"footnote": 2, # Key required
|
||||||
|
}
|
||||||
|
|
||||||
TERMS = ["note", "footnote"]
|
|
||||||
|
def _checkModKey(modifier: str, key: str) -> bool:
|
||||||
|
"""Check if a modifier and key set are ok."""
|
||||||
|
if modifier in MODIFIERS:
|
||||||
|
if key == "":
|
||||||
|
return KEY_REQ[modifier] < 2
|
||||||
|
elif key.replace("_", "").isalnum():
|
||||||
|
return KEY_REQ[modifier] > 0
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def processComment(text: str) -> tuple[nwComment, str, str, int, int]:
|
def processComment(text: str) -> tuple[nwComment, str, str, int, int]:
|
||||||
"""Extract comment style and text. Should only be called on text
|
"""Extract comment style, key and text. Should only be called on
|
||||||
starting with a %.
|
text starting with a %.
|
||||||
"""
|
"""
|
||||||
check = text[1:].lstrip()
|
if text[:2] == "%~":
|
||||||
classifier, _, content = check.partition(":")
|
return nwComment.IGNORE, "", text[2:].lstrip(), 0, 0
|
||||||
classifier, _, term = classifier.partition(".")
|
|
||||||
if content and (clean := classifier.strip().lower()) in CLASSIFIERS:
|
check = text[1:].strip()
|
||||||
term = "ERR" if term and clean not in TERMS else term.strip()
|
start, _, content = check.partition(":")
|
||||||
return CLASSIFIERS[clean], term, content.strip(), text.find(".") + 1, text.find(":") + 1
|
modifier, _, key = start.rstrip().partition(".")
|
||||||
return nwComment.IGNORE if text.startswith("%~") else nwComment.PLAIN, "", check, 0, 0
|
if content and (clean := modifier.lower()) and _checkModKey(clean, key):
|
||||||
|
col = text.find(":") + 1
|
||||||
|
dot = text.find(".", 0, col) + 1
|
||||||
|
return MODIFIERS[clean], key, content.lstrip(), dot, col
|
||||||
|
|
||||||
|
return nwComment.PLAIN, "", check, 0, 0
|
||||||
|
|||||||
@@ -26,16 +26,16 @@ from shutil import copyfile
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mocked import causeException
|
|
||||||
from tools import C, buildTestProject, cmpFiles, writeFile
|
|
||||||
|
|
||||||
from novelwriter import SHARED
|
from novelwriter import SHARED
|
||||||
from novelwriter.constants import nwFiles
|
from novelwriter.constants import nwFiles
|
||||||
from novelwriter.core.index import IndexItem, NWIndex, TagsIndex, processComment
|
from novelwriter.core.index import IndexItem, NWIndex, TagsIndex, _checkModKey, processComment
|
||||||
from novelwriter.core.item import NWItem
|
from novelwriter.core.item import NWItem
|
||||||
from novelwriter.core.project import NWProject
|
from novelwriter.core.project import NWProject
|
||||||
from novelwriter.enum import nwComment, nwItemClass, nwItemLayout
|
from novelwriter.enum import nwComment, nwItemClass, nwItemLayout
|
||||||
|
|
||||||
|
from tests.mocked import causeException
|
||||||
|
from tests.tools import C, buildTestProject, cmpFiles, writeFile
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreIndex_LoadSave(qtbot, monkeypatch, prjLipsum, mockGUI, tstPaths):
|
def testCoreIndex_LoadSave(qtbot, monkeypatch, prjLipsum, mockGUI, tstPaths):
|
||||||
@@ -1319,39 +1319,88 @@ def testCoreIndex_ItemIndex(mockGUI, fncPath, mockRnd):
|
|||||||
# END Test testCoreIndex_ItemIndex
|
# END Test testCoreIndex_ItemIndex
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.core
|
||||||
|
def testCoreIndex_checkModKey():
|
||||||
|
"""Test the _checkModKey function."""
|
||||||
|
# Check Requirements
|
||||||
|
|
||||||
|
# Synopsis
|
||||||
|
assert _checkModKey("synopsis", "") is True
|
||||||
|
assert _checkModKey("synopsis", "a") is False
|
||||||
|
|
||||||
|
# Short
|
||||||
|
assert _checkModKey("short", "") is True
|
||||||
|
assert _checkModKey("short", "a") is False
|
||||||
|
|
||||||
|
# Note
|
||||||
|
assert _checkModKey("note", "") is True
|
||||||
|
assert _checkModKey("note", "a") is True
|
||||||
|
|
||||||
|
# Footnote
|
||||||
|
assert _checkModKey("footnote", "") is False
|
||||||
|
assert _checkModKey("footnote", "a") is True
|
||||||
|
|
||||||
|
# Invalid
|
||||||
|
assert _checkModKey("stuff", "") is False
|
||||||
|
assert _checkModKey("stuff", "a") is False
|
||||||
|
|
||||||
|
# Check Keys
|
||||||
|
assert _checkModKey("note", "a") is True
|
||||||
|
assert _checkModKey("note", "a1") is True
|
||||||
|
assert _checkModKey("note", "a1.2") is False
|
||||||
|
assert _checkModKey("note", "a1_2") is True
|
||||||
|
|
||||||
|
# END Test testCoreIndex_checkModKey
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreIndex_processComment():
|
def testCoreIndex_processComment():
|
||||||
"""Test the comment processing function."""
|
"""Test the comment processing function."""
|
||||||
# Regular comment
|
# Plain
|
||||||
assert processComment("%Hi") == (nwComment.PLAIN, "", "Hi", 0, 0)
|
assert processComment("%Hi") == (nwComment.PLAIN, "", "Hi", 0, 0)
|
||||||
assert processComment("% Hi") == (nwComment.PLAIN, "", "Hi", 0, 0)
|
assert processComment("% Hi") == (nwComment.PLAIN, "", "Hi", 0, 0)
|
||||||
assert processComment("% Hi:You") == (nwComment.PLAIN, "", "Hi:You", 0, 0)
|
assert processComment("% Hi:You") == (nwComment.PLAIN, "", "Hi:You", 0, 0)
|
||||||
assert processComment("% Hi.You:There") == (nwComment.PLAIN, "", "Hi.You:There", 0, 0)
|
assert processComment("% Hi.You:There") == (nwComment.PLAIN, "", "Hi.You:There", 0, 0)
|
||||||
|
|
||||||
# Check Non-Term
|
# Ignore
|
||||||
|
assert processComment("%~Hi") == (nwComment.IGNORE, "", "Hi", 0, 0)
|
||||||
|
assert processComment("%~ Hi") == (nwComment.IGNORE, "", "Hi", 0, 0)
|
||||||
|
|
||||||
|
# Invalid
|
||||||
|
assert processComment("") == (nwComment.PLAIN, "", "", 0, 0)
|
||||||
|
|
||||||
|
# Short : Term not allowed
|
||||||
assert processComment("%short: Hi") == (nwComment.SHORT, "", "Hi", 0, 7)
|
assert processComment("%short: Hi") == (nwComment.SHORT, "", "Hi", 0, 7)
|
||||||
assert processComment("%short.term: Hi") == (nwComment.SHORT, "ERR", "Hi", 7, 12)
|
assert processComment("%short.a: Hi") == (nwComment.PLAIN, "", "short.a: Hi", 0, 0)
|
||||||
|
|
||||||
# Check Term
|
# Synopsis : Term not allowed
|
||||||
|
assert processComment("%synopsis: Hi") == (nwComment.SYNOPSIS, "", "Hi", 0, 10)
|
||||||
|
assert processComment("%synopsis.a: Hi") == (nwComment.PLAIN, "", "synopsis.a: Hi", 0, 0)
|
||||||
|
|
||||||
|
# Note : Term optional
|
||||||
assert processComment("%note: Hi") == (nwComment.NOTE, "", "Hi", 0, 6)
|
assert processComment("%note: Hi") == (nwComment.NOTE, "", "Hi", 0, 6)
|
||||||
assert processComment("%note.term: Hi") == (nwComment.NOTE, "term", "Hi", 6, 11)
|
assert processComment("%note.a: Hi") == (nwComment.NOTE, "a", "Hi", 6, 8)
|
||||||
|
|
||||||
# Check Padding
|
# Footnote : Term required
|
||||||
|
assert processComment("%footnote: Hi") == (nwComment.PLAIN, "", "footnote: Hi", 0, 0)
|
||||||
|
assert processComment("%footnote.a: Hi") == (nwComment.FOOTNOTE, "a", "Hi", 10, 12)
|
||||||
|
|
||||||
|
# Check Case
|
||||||
|
assert processComment("%Footnote.a: Hi") == (nwComment.FOOTNOTE, "a", "Hi", 10, 12)
|
||||||
|
assert processComment("%FOOTNOTE.A: Hi") == (nwComment.FOOTNOTE, "A", "Hi", 10, 12)
|
||||||
|
assert processComment("%FootNote.A_a: Hi") == (nwComment.FOOTNOTE, "A_a", "Hi", 10, 14)
|
||||||
|
|
||||||
|
# Padding without term
|
||||||
assert processComment("%short: Hi") == (nwComment.SHORT, "", "Hi", 0, 7)
|
assert processComment("%short: Hi") == (nwComment.SHORT, "", "Hi", 0, 7)
|
||||||
assert processComment("% short: Hi") == (nwComment.SHORT, "", "Hi", 0, 8)
|
assert processComment("% short: Hi") == (nwComment.SHORT, "", "Hi", 0, 8)
|
||||||
assert processComment("% short : Hi") == (nwComment.SHORT, "", "Hi", 0, 10)
|
assert processComment("% short : Hi") == (nwComment.SHORT, "", "Hi", 0, 10)
|
||||||
assert processComment("% short : Hi") == (nwComment.SHORT, "", "Hi", 0, 12)
|
assert processComment("% short : Hi") == (nwComment.SHORT, "", "Hi", 0, 12)
|
||||||
assert processComment("% \t short : Hi") == (nwComment.SHORT, "", "Hi", 0, 13)
|
assert processComment("% \t short : Hi") == (nwComment.SHORT, "", "Hi", 0, 13)
|
||||||
|
|
||||||
|
# Padding with term
|
||||||
assert processComment("%note.term: Hi") == (nwComment.NOTE, "term", "Hi", 6, 11)
|
assert processComment("%note.term: Hi") == (nwComment.NOTE, "term", "Hi", 6, 11)
|
||||||
assert processComment("% note.term: Hi") == (nwComment.NOTE, "term", "Hi", 7, 12)
|
assert processComment("% note.term: Hi") == (nwComment.NOTE, "term", "Hi", 7, 12)
|
||||||
assert processComment("% note . term : Hi") == (nwComment.NOTE, "term", "Hi", 9, 16)
|
assert processComment("% note. term : Hi") == (nwComment.PLAIN, "", "note. term : Hi", 0, 0)
|
||||||
assert processComment("% note . term : Hi") == (nwComment.NOTE, "term", "Hi", 11, 20)
|
assert processComment("% note . term : Hi") == (nwComment.PLAIN, "", "note . term : Hi", 0, 0)
|
||||||
|
|
||||||
# Check Classifiers
|
|
||||||
assert processComment("%short: Hi") == (nwComment.SHORT, "", "Hi", 0, 7)
|
|
||||||
assert processComment("%synopsis: Hi") == (nwComment.SYNOPSIS, "", "Hi", 0, 10)
|
|
||||||
assert processComment("%note.term: Hi") == (nwComment.NOTE, "term", "Hi", 6, 11)
|
|
||||||
assert processComment("%footnote.term: Hi") == (nwComment.FOOTNOTE, "term", "Hi", 10, 15)
|
|
||||||
|
|
||||||
# END Test testCoreIndex_processComment
|
# END Test testCoreIndex_processComment
|
||||||
|
|||||||
Reference in New Issue
Block a user