diff --git a/novelwriter/constants.py b/novelwriter/constants.py
index a45033ad2..9567c3bb4 100644
--- a/novelwriter/constants.py
+++ b/novelwriter/constants.py
@@ -23,6 +23,8 @@
"""
from __future__ import annotations
+import re
+
from PyQt5.QtCore import QCoreApplication, QT_TRANSLATE_NOOP
from novelwriter.enum import nwBuildFmt, nwItemClass, nwItemLayout, nwOutline
@@ -59,9 +61,12 @@ class nwRegEx:
FMT_EI = r"(? tuple[int, int, int]:
if nwUnicode.U_EMDASH in text:
text = text.replace(nwUnicode.U_EMDASH, " ")
+ # Strip shortcodes
+ if "[" in text:
+ text = nwRegEx.RX_SC.sub("", text)
+
for line in text.splitlines():
countPara = True
@@ -1241,9 +1245,10 @@ def countWords(text: str) -> tuple[int, int, int]:
continue
if line[0] == "[":
- if line.startswith(("[NEWPAGE]", "[NEW PAGE]", "[VSPACE]")):
+ check = line.lower()
+ if check.startswith(("[newpage]", "[new page]", "[vspace]")):
continue
- elif line.startswith("[VSPACE:") and line.endswith("]"):
+ elif check.startswith("[vspace:") and line.endswith("]"):
continue
elif line[0] == "#":
diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py
index 1555e61eb..93053f200 100644
--- a/novelwriter/gui/doceditor.py
+++ b/novelwriter/gui/doceditor.py
@@ -55,6 +55,7 @@
from novelwriter.common import minmax, transferCase
from novelwriter.constants import nwKeyWords, nwUnicode
from novelwriter.core.index import countWords
+from novelwriter.core.document import NWDocument
from novelwriter.gui.dochighlight import GuiDocHighlighter
from novelwriter.gui.editordocument import GuiTextDocument
from novelwriter.extensions.wheeleventfilter import WheelEventFilter
@@ -408,12 +409,6 @@ def updateTagHighLighting(self) -> None:
self._qDocument.syntaxHighlighter.rehighlightByType(GuiDocHighlighter.BLOCK_META)
return
- def redrawText(self) -> None:
- """Redraw the text by marking the document content as dirty."""
- self._qDocument.markContentsDirty(0, self._qDocument.characterCount())
- self.updateDocMargins()
- return
-
def replaceText(self, text: str) -> None:
"""Replace the text of the current document with the provided
text. This also clears undo history.
@@ -735,19 +730,17 @@ def revealLocation(self) -> None:
"""Tell the user where on the file system the file in the editor
is saved.
"""
- if self._nwDocument is None:
- logger.error("No document open")
- return
- SHARED.info(
- "
".join([
- self.tr("Document Details"),
- "–"*40,
- self.tr("Created: {0}").format(self._nwDocument.createdDate),
- self.tr("Updated: {0}").format(self._nwDocument.updatedDate),
- ]),
- details=self.tr("File Location: {0}").format(self._nwDocument.fileLocation),
- log=False
- )
+ if isinstance(self._nwDocument, NWDocument):
+ SHARED.info(
+ "
".join([
+ self.tr("Document Details"),
+ "–"*40,
+ self.tr("Created: {0}").format(self._nwDocument.createdDate),
+ self.tr("Updated: {0}").format(self._nwDocument.updatedDate),
+ ]),
+ details=self.tr("File Location: {0}").format(self._nwDocument.fileLocation),
+ log=False
+ )
return
def insertText(self, insert: str | nwDocInsert) -> bool:
@@ -775,15 +768,15 @@ def insertText(self, insert: str | nwDocInsert) -> bool:
newBlock = True
goAfter = True
elif insert == nwDocInsert.NEW_PAGE:
- text = "[NEW PAGE]"
+ text = "[newpage]"
newBlock = True
goAfter = False
elif insert == nwDocInsert.VSPACE_S:
- text = "[VSPACE]"
+ text = "[vspace]"
newBlock = True
goAfter = False
elif insert == nwDocInsert.VSPACE_M:
- text = "[VSPACE:2]"
+ text = "[vspace:2]"
newBlock = True
goAfter = False
else:
diff --git a/sample/content/974e400180a99.nwd b/sample/content/974e400180a99.nwd
index 0175798bc..5058f0ca7 100644
--- a/sample/content/974e400180a99.nwd
+++ b/sample/content/974e400180a99.nwd
@@ -1,11 +1,11 @@
%%~name: Page
%%~path: 7031beac91f75/974e400180a99
%%~kind: NOVEL/DOCUMENT
-%%~hash: 7547809e972205eb2a55dd988595e0aa1d01e139
-%%~date: Unknown/2023-08-25 16:51:54
-[NEW PAGE]
-[VSPACE:2]
+%%~hash: a0b0719e19763bf505bcf797bea0968c505c9b4a
+%%~date: Unknown/2023-11-06 11:19:33
+[newpage]
+[vspace:2]
This is a plain page with some text on it.
-If you want the text to start on a fresh page, add the [NEW PAGE] code above the text. You can also add empty paragraphs with the [VSPACE] code. The above code adds two empty paragraphs before the text starts.
+If you want the text to start on a fresh page, add the [newpage] code above the text. You can also add empty paragraphs with the [vspace] code. The above code adds two empty paragraphs before the text starts.
diff --git a/sample/nwProject.nwx b/sample/nwProject.nwx
index 34c50b8c3..67b86c1f9 100644
--- a/sample/nwProject.nwx
+++ b/sample/nwProject.nwx
@@ -1,6 +1,6 @@
-
-
+
+
Sample Project
Sample Project
Jane Smith
@@ -36,7 +36,7 @@
Main
-
+
-
Novel
@@ -46,7 +46,7 @@
Title Page
-
-
+
Page
-
@@ -58,7 +58,7 @@
Chapter One
-
-
+
Making a Scene
-
diff --git a/tests/test_core/test_core_index.py b/tests/test_core/test_core_index.py
index d8b7917eb..03b497dad 100644
--- a/tests/test_core/test_core_index.py
+++ b/tests/test_core/test_core_index.py
@@ -1281,7 +1281,7 @@ def testCoreIndex_CountWords():
assert wC == 9
assert pC == 4
- # Formatting Codes
+ # Formatting Codes, Upper Case (Old Implementation)
cC, wC, pC = countWords((
"Some text\n\n"
"[NEWPAGE]\n\n"
@@ -1297,4 +1297,29 @@ def testCoreIndex_CountWords():
assert wC == 13
assert pC == 5
+ # Formatting Codes, Lower Case (Current Implementation)
+ cC, wC, pC = countWords((
+ "Some text\n\n"
+ "[newpage]\n\n"
+ "more text\n\n"
+ "[new page]]\n\n"
+ "even more text\n\n"
+ "[vspace]\n\n"
+ "and some final text\n\n"
+ "[vspace:4]\n\n"
+ "THE END\n\n"
+ ))
+ assert cC == 58
+ assert wC == 13
+ assert pC == 5
+
+ # Check ShortCodes
+ cC, wC, pC = countWords((
+ "Text with [b]bold[/b] text and padded [b] bold [/b] text.\n\n"
+ "Text with [b][i] nested [/i] emphasis [/b] in it.\n\n"
+ ))
+ assert cC == 78
+ assert wC == 14
+ assert pC == 2
+
# END Test testCoreIndex_CountWords
diff --git a/tests/test_core/test_core_tokenizer.py b/tests/test_core/test_core_tokenizer.py
index df5590b39..d5cbee872 100644
--- a/tests/test_core/test_core_tokenizer.py
+++ b/tests/test_core/test_core_tokenizer.py
@@ -789,7 +789,7 @@ def testCoreToken_SpecialFormat(mockGUI):
tokens._isFirst = True
tokens._text = (
"# Title One\n\n"
- "[NEWPAGE]\n\n"
+ "[newpage]\n\n"
"# Title Two\n\n"
)
tokens.tokenizeText()
@@ -799,7 +799,7 @@ def testCoreToken_SpecialFormat(mockGUI):
tokens._isFirst = True
tokens._text = (
"# Title One\n\n"
- "[NEW PAGE]\n\n"
+ "[new page]\n\n"
"# Title Two\n\n"
)
tokens.tokenizeText()
@@ -809,7 +809,7 @@ def testCoreToken_SpecialFormat(mockGUI):
tokens._isFirst = True
tokens._text = (
"# Title One\n\n"
- "[NEW PAGE] \t\n\n"
+ "[new page] \t\n\n"
"# Title Two\n\n"
)
tokens.tokenizeText()
@@ -820,7 +820,7 @@ def testCoreToken_SpecialFormat(mockGUI):
tokens._text = (
"# Title One\n\n"
- "[VSPACE] \n\n"
+ "[vspace] \n\n"
"Some text to go here ...\n\n"
)
tokens.tokenizeText()
@@ -840,7 +840,7 @@ def testCoreToken_SpecialFormat(mockGUI):
# One Skip
tokens._text = (
"# Title One\n\n"
- "[VSPACE:1] \n\n"
+ "[vspace:1] \n\n"
"Some text to go here ...\n\n"
)
tokens.tokenizeText()
@@ -857,7 +857,7 @@ def testCoreToken_SpecialFormat(mockGUI):
# Three Skips
tokens._text = (
"# Title One\n\n"
- "[VSPACE:3] \n\n"
+ "[vspace:3] \n\n"
"Some text to go here ...\n\n"
)
tokens.tokenizeText()
@@ -876,7 +876,7 @@ def testCoreToken_SpecialFormat(mockGUI):
# Malformed Command, Case 1
tokens._text = (
"# Title One\n\n"
- "[VSPACE:3xa] \n\n"
+ "[vspace:3xa] \n\n"
"Some text to go here ...\n\n"
)
tokens.tokenizeText()
@@ -892,7 +892,7 @@ def testCoreToken_SpecialFormat(mockGUI):
# Malformed Command, Case 2
tokens._text = (
"# Title One\n\n"
- "[VSPACE:3.5]\n\n"
+ "[vspace:3.5]\n\n"
"Some text to go here ...\n\n"
)
tokens.tokenizeText()
@@ -908,7 +908,7 @@ def testCoreToken_SpecialFormat(mockGUI):
# Malformed Command, Case 3
tokens._text = (
"# Title One\n\n"
- "[VSPACE:-1]\n\n"
+ "[vspace:-1]\n\n"
"Some text to go here ...\n\n"
)
tokens.tokenizeText()
@@ -927,8 +927,8 @@ def testCoreToken_SpecialFormat(mockGUI):
# Single Skip
tokens._text = (
"# Title One\n\n"
- "[NEW PAGE]\n\n"
- "[VSPACE]\n\n"
+ "[new page]\n\n"
+ "[vspace]\n\n"
"Some text to go here ...\n\n"
)
tokens.tokenizeText()
@@ -946,8 +946,8 @@ def testCoreToken_SpecialFormat(mockGUI):
# Multiple Skip
tokens._text = (
"# Title One\n\n"
- "[NEW PAGE]\n\n"
- "[VSPACE:3]\n\n"
+ "[new page]\n\n"
+ "[vspace:3]\n\n"
"Some text to go here ...\n\n"
)
tokens.tokenizeText()
diff --git a/tests/test_gui/test_gui_mainmenu.py b/tests/test_gui/test_gui_mainmenu.py
index 5fe1ae495..e66e5dc61 100644
--- a/tests/test_gui/test_gui_mainmenu.py
+++ b/tests/test_gui/test_gui_mainmenu.py
@@ -600,15 +600,15 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
nwGUI.docEditor.setPlainText("### Stuff\n")
nwGUI.mainMenu.aInsNewPage.activate(QAction.Trigger)
- assert nwGUI.docEditor.getText() == "[NEW PAGE]\n### Stuff\n"
+ assert nwGUI.docEditor.getText() == "[newpage]\n### Stuff\n"
nwGUI.docEditor.setPlainText("### Stuff\n")
nwGUI.mainMenu.aInsVSpaceS.activate(QAction.Trigger)
- assert nwGUI.docEditor.getText() == "[VSPACE]\n### Stuff\n"
+ assert nwGUI.docEditor.getText() == "[vspace]\n### Stuff\n"
nwGUI.docEditor.setPlainText("### Stuff\n")
nwGUI.mainMenu.aInsVSpaceM.activate(QAction.Trigger)
- assert nwGUI.docEditor.getText() == "[VSPACE:2]\n### Stuff\n"
+ assert nwGUI.docEditor.getText() == "[vspace:2]\n### Stuff\n"
nwGUI.docEditor.clear()