Implement alternative tag display name format

This commit is contained in:
Veronica Berglyd Olsen
2024-01-30 21:34:36 +01:00
parent c5edbbfaf6
commit ca188fee08
7 changed files with 65 additions and 68 deletions
+18 -14
View File
@@ -420,8 +420,7 @@ class NWIndex:
return
if tBits[0] == nwKeyWords.TAG_KEY:
tagKey = tBits[1]
displayName = tBits[2] if len(tBits) > 2 else tagKey
tagKey, displayName = self.parseValue(tBits[1])
self._tagsIndex.add(tagKey, displayName, tHandle, sTitle, itemClass.name)
self._itemIndex.setHeadingTag(tHandle, sTitle, tagKey)
tags[tagKey.lower()] = True
@@ -472,10 +471,8 @@ class NWIndex:
return True, tBits, tPos
def checkThese(self, tBits: list[str], nwItem: NWItem) -> list[bool]:
"""Check the tags against the index to see if they are valid
tags. This is needed for syntax highlighting.
"""
def checkThese(self, tBits: list[str], tHandle: str) -> list[bool]:
"""Check tags against the index to see if they are valid."""
nBits = len(tBits)
isGood = [False]*nBits
if nBits == 0:
@@ -489,19 +486,25 @@ class NWIndex:
# For a tag, only the first value is accepted, the rest are ignored
if tBits[0] == nwKeyWords.TAG_KEY and nBits > 1:
if tBits[1] in self._tagsIndex:
isGood[1] = self._tagsIndex.tagHandle(tBits[1]) == nwItem.itemHandle
isGood[1] = self._tagsIndex.tagHandle(tBits[1]) == tHandle
else:
isGood[1] = True
return isGood
# If we're still here, we check that the references exist
# Class references cannot have the | symbol in them
refKey = nwKeyWords.KEY_CLASS[tBits[0]].name
for n in range(1, nBits):
if tBits[n] in self._tagsIndex:
isGood[n] = self._tagsIndex.tagClass(tBits[n]) == refKey
if (aBit := tBits[n]) in self._tagsIndex:
isGood[n] = self._tagsIndex.tagClass(aBit) == refKey and "|" not in aBit
return isGood
def parseValue(self, text: str) -> tuple[str, str]:
"""Parse a single value into a name and display part."""
name, _, display = text.partition("|")
return name.rstrip(), display.lstrip()
##
# Extract Data
##
@@ -725,11 +728,12 @@ class TagsIndex:
"""Return a dictionary view of all tags."""
return self._tags.items()
def add(self, tagKey: str, display: str, tHandle: str, sTitle: str, className: str) -> None:
def add(self, tagKey: str, displayName: str, tHandle: str,
sTitle: str, className: str) -> None:
"""Add a key to the index and set all values."""
self._tags[tagKey.lower()] = {
"name": tagKey,
"display": display,
"display": displayName or tagKey,
"handle": tHandle,
"heading": sTitle,
"class": className,
@@ -786,9 +790,9 @@ class TagsIndex:
name = entry.get("name")
display = entry.get("display")
handle = entry.get("handle", "")
heading = entry.get("heading", "")
className = entry.get("class", "")
handle = entry.get("handle")
heading = entry.get("heading")
className = entry.get("class")
if not isinstance(name, str):
raise ValueError("tagsIndex name is not a string")
+4 -1
View File
@@ -484,7 +484,10 @@ class ToHtml(Tokenizer):
result = f"<span class='tags'>{self._localLookup(nwLabels.KEY_NAME[bits[0]])}:</span> "
if len(bits) > 1:
if bits[0] == nwKeyWords.TAG_KEY:
result += f"<a name='tag_{bits[1]}'>{bits[1]}</a>"
one, two = self._project.index.parseValue(bits[1])
result += f"<a name='tag_{one}'>{one}</a>"
if two:
result += f" | <span class='optional'>{two}</a>"
else:
if self._genMode == self.M_PREVIEW:
result += ", ".join(f"<a href='#{bits[0][1:]}={t}'>{t}</a>" for t in bits[1:])
+3 -4
View File
@@ -56,7 +56,6 @@ from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwDocAction, nwDocInsert, nwDocMode, nwItemClass, nwTrinary
from novelwriter.common import minmax, transferCase
from novelwriter.constants import nwKeyWords, nwLabels, nwShortcode, nwUnicode, trConst
from novelwriter.core.item import NWItem
from novelwriter.core.index import countWords
from novelwriter.tools.lipsum import GuiLipsum
from novelwriter.core.document import NWDocument
@@ -1835,16 +1834,16 @@ class GuiDocEditor(QPlainTextEdit):
if len(text) == 0:
return nwTrinary.NEUTRAL
if text.startswith("@") and isinstance(self._nwItem, NWItem):
if text.startswith("@") and self._docHandle:
isGood, tBits, tPos = SHARED.project.index.scanThis(text)
if not isGood:
if not isGood or not tBits or tBits[0] == nwKeyWords.TAG_KEY:
return nwTrinary.NEUTRAL
tag = ""
exist = False
cPos = cursor.selectionStart() - block.position()
tExist = SHARED.project.index.checkThese(tBits, self._nwItem)
tExist = SHARED.project.index.checkThese(tBits, self._docHandle)
for sTag, sPos, sExist in zip(reversed(tBits), reversed(tPos), reversed(tExist)):
if cPos >= sPos:
# The cursor is between the start of two tags
+17 -17
View File
@@ -279,23 +279,23 @@ class GuiDocHighlighter(QSyntaxHighlighter):
if text.startswith("@"): # Keywords and commands
self.setCurrentBlockState(self.BLOCK_META)
if self._tItem:
pIndex = SHARED.project.index
isValid, bits, pos = pIndex.scanThis(text)
isGood = pIndex.checkThese(bits, self._tItem)
if isValid:
for n, bit in enumerate(bits):
xPos = pos[n]
xLen = len(bit)
if isGood[n]:
if n == 0:
self.setFormat(xPos, xLen, self._hStyles["keyword"])
else:
self.setFormat(xPos, xLen, self._hStyles["value"])
else:
kwFmt = self.format(xPos)
kwFmt.merge(self._hStyles["codeinval"])
self.setFormat(xPos, xLen, kwFmt)
index = SHARED.project.index
isValid, bits, pos = index.scanThis(text)
isGood = index.checkThese(bits, self._tHandle)
if isValid:
for n, bit in enumerate(bits):
xPos = pos[n]
xLen = len(bit)
if not isGood[n]:
self.setFormat(xPos, xLen, self._hStyles["codeinval"])
elif n == 0:
self.setFormat(xPos, xLen, self._hStyles["keyword"])
else:
one, two = index.parseValue(bit)
self.setFormat(xPos, len(one), self._hStyles["value"])
if two:
yPos = xPos + len(bit) - len(two)
self.setFormat(yPos, len(two), self._hStyles["optional"])
# We never want to run the spell checker on keyword/values,
# so we force a return here
+17 -26
View File
@@ -461,15 +461,16 @@ class GuiDocViewer(QTextBrowser):
def _makeStyleSheet(self) -> None:
"""Generate an appropriate style sheet for the document viewer,
based on the current syntax highlighter theme,
based on the current syntax highlighter theme.
"""
colText = SHARED.theme.colText
colHead = SHARED.theme.colHead
colVal = SHARED.theme.colVal
colVals = SHARED.theme.colVal
colEmph = SHARED.theme.colEmph
colKey = SHARED.theme.colKey
colHidden = SHARED.theme.colHidden
colMod = SHARED.theme.colMod
colKeys = SHARED.theme.colKey
colHide = SHARED.theme.colHidden
colMods = SHARED.theme.colMod
colOpts = SHARED.theme.colOpt
styleSheet = (
"body {{"
" color: rgb({tColR}, {tColG}, {tColB});"
@@ -486,6 +487,9 @@ class GuiDocViewer(QTextBrowser):
".tags {{"
" color: rgb({kColR}, {kColG}, {kColB});"
"}}\n"
".optional {{"
" color: rgb({oColR}, {oColG}, {oColB});"
"}}\n"
".comment {{"
" color: rgb({cColR}, {cColG}, {cColB});"
"}}\n"
@@ -496,27 +500,14 @@ class GuiDocViewer(QTextBrowser):
" text-align: center;"
"}}\n"
).format(
tColR=colText.red(),
tColG=colText.green(),
tColB=colText.blue(),
hColR=colHead.red(),
hColG=colHead.green(),
hColB=colHead.blue(),
aColR=colVal.red(),
aColG=colVal.green(),
aColB=colVal.blue(),
eColR=colEmph.red(),
eColG=colEmph.green(),
eColB=colEmph.blue(),
kColR=colKey.red(),
kColG=colKey.green(),
kColB=colKey.blue(),
cColR=colHidden.red(),
cColG=colHidden.green(),
cColB=colHidden.blue(),
mColR=colMod.red(),
mColG=colMod.green(),
mColB=colMod.blue(),
tColR=colText.red(), tColG=colText.green(), tColB=colText.blue(),
hColR=colHead.red(), hColG=colHead.green(), hColB=colHead.blue(),
aColR=colVals.red(), aColG=colVals.green(), aColB=colVals.blue(),
eColR=colEmph.red(), eColG=colEmph.green(), eColB=colEmph.blue(),
kColR=colKeys.red(), kColG=colKeys.green(), kColB=colKeys.blue(),
cColR=colHide.red(), cColG=colHide.green(), cColB=colHide.blue(),
mColR=colMods.red(), mColG=colMods.green(), mColB=colMods.blue(),
oColR=colOpts.red(), oColG=colOpts.green(), oColB=colOpts.blue(),
)
self.document().setDefaultStyleSheet(styleSheet)
+3 -3
View File
@@ -1,11 +1,11 @@
%%~name: John Smith
%%~path: f7e2d9f330615/14298de4d9524
%%~kind: CHARACTER/NOTE
%%~hash: 0f40182de0bb7935bb40fc4c7fd0d75d55421299
%%~date: Unknown/2024-01-29 12:19:42
%%~hash: f85b4da6ba4a557db0c4d5f1b59f33ba01542606
%%~date: Unknown/2024-01-30 10:58:18
# John Smith
@tag: John, John Smith
@tag: John | John Smith
% Short: The sidekick
+3 -3
View File
@@ -1,11 +1,11 @@
%%~name: Jane Smith
%%~path: f7e2d9f330615/bb2c23b3c42cc
%%~kind: CHARACTER/NOTE
%%~hash: 0faba71c86841552090a9e82dd9b7acd5b0bf56f
%%~date: Unknown/2024-01-29 12:31:34
%%~hash: 10f072a4bf7389b0c178a4181e50833d39b945af
%%~date: Unknown/2024-01-30 11:05:37
# Jane Smith
@tag: Jane, Jane Smith
@tag: Jane | Jane Smith
% Short: The heroine