Add full test coverage of syntax highlighter
This commit is contained in:
@@ -1,23 +0,0 @@
|
||||
%%~name: New Scene
|
||||
%%~path: 6a2d6d5f4f401/f0260d04a8013
|
||||
%%~kind: NOVEL/DOCUMENT
|
||||
%%~hash: d37d33de7c022106f13239a3c310420653871b95
|
||||
%%~date: 2025-07-05 14:35:40/2025-07-06 09:55:14
|
||||
### Test 𐎀𐎘𐎗𐎚
|
||||
|
||||
@tag: 😅 | Smiley
|
||||
@char: Jane, 😅, John
|
||||
@story: 😅
|
||||
|
||||
% Test comment 𐎀𐎘𐎗𐎚 with stuff and **bold** text.
|
||||
|
||||
%Note.Consistency: 😅 _lol_ …
|
||||
%Note.𐎀𐎘𐎗𐎚: Test
|
||||
|
||||
Text **bold 𐎀𐎘𐎗𐎚** and so on and _so forth_. ~~😅 does it work?~~
|
||||
|
||||
Yada yada Anata (𐎀𐎐𐎚) – yada yada – yada yada Athirata (𐎀𐎘𐎗𐎚) – yada yada. “Test dialog here.”
|
||||
|
||||
Normal line
|
||||
|
||||
– tttttt
|
||||
+6
-10
@@ -1,6 +1,6 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<novelWriterXML appVersion="2.8a1" hexVersion="0x020800a1" fileVersion="1.5" fileRevision="6" timeStamp="2025-07-06 16:34:43">
|
||||
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="2274" autoCount="301" editTime="99789">
|
||||
<novelWriterXML appVersion="2.8a1" hexVersion="0x020800a1" fileVersion="1.5" fileRevision="6" timeStamp="2025-07-13 18:58:02">
|
||||
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="2279" autoCount="301" editTime="99977">
|
||||
<name>Sample Project</name>
|
||||
<author>Jane Smith</author>
|
||||
</project>
|
||||
@@ -9,8 +9,8 @@
|
||||
<language>en_GB</language>
|
||||
<spellChecking auto="yes">None</spellChecking>
|
||||
<lastHandle>
|
||||
<entry key="editor">f0260d04a8013</entry>
|
||||
<entry key="viewer">f0260d04a8013</entry>
|
||||
<entry key="editor">636b6aa9b697b</entry>
|
||||
<entry key="viewer">636b6aa9b697b</entry>
|
||||
<entry key="novel">7031beac91f75</entry>
|
||||
<entry key="outline">7031beac91f75</entry>
|
||||
</lastHandle>
|
||||
@@ -20,7 +20,7 @@
|
||||
<entry key="C">D</entry>
|
||||
</autoReplace>
|
||||
<status>
|
||||
<entry key="sf12341" count="9" color="#969896" shape="STAR">New</entry>
|
||||
<entry key="sf12341" count="8" color="#969896" shape="STAR">New</entry>
|
||||
<entry key="sf24ce6" count="2" color="red" shape="STAR">Notes</entry>
|
||||
<entry key="sc24b8f" count="3" color="yellow" shape="BARS_1">Started</entry>
|
||||
<entry key="s90e6c9" count="5" color="yellow" shape="BARS_2">1st Draft</entry>
|
||||
@@ -36,7 +36,7 @@
|
||||
<entry key="i56be10" count="1" color="purple" shape="BLOCK_4">Main</entry>
|
||||
</importance>
|
||||
</settings>
|
||||
<content items="32" novelWords="1049" notesWords="416" novelChars="5792" notesChars="2285">
|
||||
<content items="31" novelWords="1016" notesWords="416" novelChars="5606" notesChars="2285">
|
||||
<item handle="7031beac91f75" parent="None" root="7031beac91f75" order="0" type="ROOT" class="NOVEL">
|
||||
<meta expanded="yes" />
|
||||
<name status="sc24b8f" import="ia857f0">Novel</name>
|
||||
@@ -65,10 +65,6 @@
|
||||
<meta expanded="no" heading="H3" charCount="548" wordCount="108" paraCount="3" cursorPos="650" />
|
||||
<name status="s90e6c9" import="ia857f0" active="yes">Another Scene</name>
|
||||
</item>
|
||||
<item handle="f0260d04a8013" parent="6a2d6d5f4f401" root="7031beac91f75" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||
<meta expanded="no" heading="H3" charCount="186" wordCount="33" paraCount="4" cursorPos="373" />
|
||||
<name status="sf12341" import="ia857f0" active="yes">New Scene</name>
|
||||
</item>
|
||||
<item handle="ba8a28a246524" parent="7031beac91f75" root="7031beac91f75" order="4" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||
<meta expanded="no" heading="H2" charCount="617" wordCount="101" paraCount="3" cursorPos="1182" />
|
||||
<name status="s78ea90" import="ia857f0" active="yes">Interlude</name>
|
||||
|
||||
@@ -0,0 +1,631 @@
|
||||
"""
|
||||
novelWriter – GUI Syntax Highlighter Tester
|
||||
===========================================
|
||||
|
||||
This file is a part of novelWriter
|
||||
Copyright (C) 2020 Veronica Berglyd Olsen and novelWriter contributors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from PyQt6.QtGui import QTextCharFormat, QTextCursor, QTextDocument
|
||||
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.core.item import NWItem
|
||||
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType, nwTheme
|
||||
from novelwriter.gui.dochighlight import BLOCK_META, BLOCK_TITLE, GuiDocHighlighter, TextBlockData
|
||||
from novelwriter.types import QtKeepAnchor
|
||||
|
||||
R_HANDLE = "3456789abcdef"
|
||||
T_HANDLE = "0123456789abc"
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def syntax(nwGUI):
|
||||
"""Create a syntax object for use with testing."""
|
||||
CONFIG.lightTheme = "tomorrow"
|
||||
CONFIG.themeMode = nwTheme.LIGHT
|
||||
|
||||
CONFIG.dialogStyle = 3
|
||||
CONFIG.fmtDQuoteOpen = "\u201c"
|
||||
CONFIG.fmtDQuoteClose = "\u201d"
|
||||
CONFIG.altDialogOpen = "::"
|
||||
CONFIG.altDialogClose = "::"
|
||||
|
||||
theme = SHARED.theme
|
||||
theme.loadTheme(force=True)
|
||||
assert theme._guiPalette.base().color().getRgb() == (0xff, 0xff, 0xff, 0xff)
|
||||
assert theme.syntaxTheme.text.getRgb() == (0x4d, 0x4d, 0x4c, 0xff)
|
||||
|
||||
doc = QTextDocument()
|
||||
syntax = GuiDocHighlighter(doc)
|
||||
|
||||
# Add a Mock Item
|
||||
tRoot = NWItem(SHARED.project, R_HANDLE)
|
||||
tRoot.setClass(nwItemClass.NOVEL)
|
||||
tRoot.setType(nwItemType.ROOT)
|
||||
|
||||
tItem = NWItem(SHARED.project, T_HANDLE)
|
||||
tItem.setParent(R_HANDLE)
|
||||
tItem.setLayout(nwItemLayout.NOTE)
|
||||
tItem.setClass(nwItemClass.NOVEL)
|
||||
tItem.setType(nwItemType.FILE)
|
||||
|
||||
SHARED.project.tree.add(tRoot)
|
||||
SHARED.project.tree.add(tItem)
|
||||
|
||||
yield syntax
|
||||
|
||||
|
||||
def getFragments(
|
||||
syntax: GuiDocHighlighter
|
||||
) -> tuple[list[tuple[int, str]], list[QTextCharFormat]]:
|
||||
"""Extract all syntax highlighter fragments from a document."""
|
||||
pieces = []
|
||||
formats = []
|
||||
doc = syntax.document()
|
||||
cursor = QTextCursor(doc)
|
||||
assert doc is not None
|
||||
for b in range(doc.blockCount()):
|
||||
block = doc.findBlockByNumber(b)
|
||||
first = block.position()
|
||||
syntax.rehighlightBlock(block)
|
||||
if layout := block.layout():
|
||||
for fmt in layout.formats():
|
||||
cursor.setPosition(first + fmt.start)
|
||||
cursor.setPosition(first + fmt.start + fmt.length, QtKeepAnchor)
|
||||
pieces.append((b, fmt.start, fmt.length, cursor.selectedText()))
|
||||
formats.append(fmt.format)
|
||||
return pieces, formats
|
||||
|
||||
|
||||
def maxOrd(text: str) -> int:
|
||||
"""Get the max character value of a string."""
|
||||
return max(ord(c) for c in text)
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiDocHighlighter_Basic(syntax):
|
||||
"""Test the basic functionality of the syntax highlighter."""
|
||||
# Alternate Spell Check
|
||||
assert syntax._spellCheck is False
|
||||
syntax.setSpellCheck(True)
|
||||
assert syntax._spellCheck is True
|
||||
|
||||
# Check Handle
|
||||
assert syntax._tHandle is None
|
||||
syntax.setHandle(T_HANDLE)
|
||||
assert syntax._tHandle == T_HANDLE
|
||||
assert syntax._isNovel is False
|
||||
assert syntax._isInactive is False
|
||||
|
||||
tItem = SHARED.project.tree[T_HANDLE]
|
||||
assert tItem is not None
|
||||
tItem.setLayout(nwItemLayout.DOCUMENT)
|
||||
tItem.setClass(nwItemClass.ARCHIVE)
|
||||
syntax.setHandle(T_HANDLE)
|
||||
assert syntax._tHandle == T_HANDLE
|
||||
assert syntax._isNovel is True
|
||||
assert syntax._isInactive is True
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiDocHighlighter_Keywords(syntax):
|
||||
"""Test highlighting of keywords."""
|
||||
theme = SHARED.theme
|
||||
doc = syntax.document()
|
||||
assert doc is not None
|
||||
|
||||
# Settings
|
||||
syntax._tHandle = T_HANDLE
|
||||
|
||||
colKey = theme.syntaxTheme.key.getRgb()
|
||||
colTag = theme.syntaxTheme.tag.getRgb()
|
||||
colOpt = theme.syntaxTheme.opt.getRgb()
|
||||
colErr = theme.syntaxTheme.error.getRgb()
|
||||
|
||||
# Ascii
|
||||
doc.setPlainText(
|
||||
"@tag: Bob | Robert\n"
|
||||
"@char: Someone\n"
|
||||
)
|
||||
syntax.rehighlightByType(BLOCK_META)
|
||||
assert maxOrd(doc.toPlainText()) <= 0x7f
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 4, "@tag"), (0, 6, 3, "Bob"), (0, 12, 6, "Robert"),
|
||||
(1, 0, 5, "@char"), (1, 7, 7, "Someone"),
|
||||
]
|
||||
assert formats[0].foreground().color().getRgb() == colKey
|
||||
assert formats[1].foreground().color().getRgb() == colTag
|
||||
assert formats[2].foreground().color().getRgb() == colOpt
|
||||
assert formats[3].foreground().color().getRgb() == colKey
|
||||
assert formats[4].underlineColor().getRgb() == colErr
|
||||
|
||||
# # Unicode <= 0xFFFF
|
||||
doc.setPlainText(
|
||||
"@tag: Zoë | Zoë Smith\n"
|
||||
"@char: Олексій\n"
|
||||
)
|
||||
syntax.rehighlightByType(BLOCK_META)
|
||||
assert 0x7f < maxOrd(doc.toPlainText()) <= 0xffff
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 4, "@tag"), (0, 6, 3, "Zoë"), (0, 12, 9, "Zoë Smith"),
|
||||
(1, 0, 5, "@char"), (1, 7, 7, "Олексій"),
|
||||
]
|
||||
assert formats[0].foreground().color().getRgb() == colKey
|
||||
assert formats[1].foreground().color().getRgb() == colTag
|
||||
assert formats[2].foreground().color().getRgb() == colOpt
|
||||
assert formats[3].foreground().color().getRgb() == colKey
|
||||
assert formats[4].underlineColor().getRgb() == colErr
|
||||
|
||||
# # Unicode > 0xFFFF
|
||||
doc.setPlainText(
|
||||
"@tag: 😄 | Smiley 😄\n"
|
||||
"@char: 😎😎😎\n"
|
||||
)
|
||||
syntax.rehighlightByType(BLOCK_META)
|
||||
assert 0xffff < maxOrd(doc.toPlainText()) <= 0xffffffff
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 4, "@tag"), (0, 6, 2, "😄"), (0, 11, 9, "Smiley 😄"),
|
||||
(1, 0, 5, "@char"), (1, 7, 6, "😎😎😎"),
|
||||
]
|
||||
assert formats[0].foreground().color().getRgb() == colKey
|
||||
assert formats[1].foreground().color().getRgb() == colTag
|
||||
assert formats[2].foreground().color().getRgb() == colOpt
|
||||
assert formats[3].foreground().color().getRgb() == colKey
|
||||
assert formats[4].underlineColor().getRgb() == colErr
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiDocHighlighter_Titles(syntax):
|
||||
"""Test highlighting of titles."""
|
||||
theme = SHARED.theme
|
||||
doc = syntax.document()
|
||||
assert doc is not None
|
||||
|
||||
# Settings
|
||||
syntax._tHandle = T_HANDLE
|
||||
|
||||
colHeadMark = theme.syntaxTheme.headH.getRgb()
|
||||
colHeadText = theme.syntaxTheme.head.getRgb()
|
||||
|
||||
# Ascii
|
||||
doc.setPlainText(
|
||||
"# Heading 1\n\n"
|
||||
"## Heading 2\n\n"
|
||||
"### Heading 3\n\n"
|
||||
"#### Heading 4\n\n"
|
||||
"#! Heading A1\n\n"
|
||||
"##! Heading A2\n\n"
|
||||
"###! Heading A3\n\n"
|
||||
)
|
||||
syntax.rehighlightByType(BLOCK_TITLE)
|
||||
assert maxOrd(doc.toPlainText()) <= 0x7f
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 1, "#"), (0, 1, 10, " Heading 1"),
|
||||
(2, 0, 2, "##"), (2, 2, 10, " Heading 2"),
|
||||
(4, 0, 3, "###"), (4, 3, 10, " Heading 3"),
|
||||
(6, 0, 4, "####"), (6, 4, 10, " Heading 4"),
|
||||
(8, 0, 2, "#!"), (8, 2, 11, " Heading A1"),
|
||||
(10, 0, 3, "##!"), (10, 3, 11, " Heading A2"),
|
||||
(12, 0, 4, "###!"), (12, 4, 11, " Heading A3"),
|
||||
]
|
||||
for i in range(0, len(formats), 2):
|
||||
assert formats[i].foreground().color().getRgb() == colHeadMark
|
||||
assert formats[i+1].foreground().color().getRgb() == colHeadText
|
||||
|
||||
# Unicode <= 0xFFFF
|
||||
doc.setPlainText(
|
||||
"# Ȟǣđ 1\n\n"
|
||||
"## Ȟǣđ 2\n\n"
|
||||
"### Ȟǣđ 3\n\n"
|
||||
"#### Ȟǣđ 4\n\n"
|
||||
"#! Ȟǣđ A1\n\n"
|
||||
"##! Ȟǣđ A2\n\n"
|
||||
"###! Ȟǣđ A3\n\n"
|
||||
)
|
||||
syntax.rehighlightByType(BLOCK_TITLE)
|
||||
assert 0x7f < maxOrd(doc.toPlainText()) <= 0xffff
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 1, "#"), (0, 1, 6, " Ȟǣđ 1"),
|
||||
(2, 0, 2, "##"), (2, 2, 6, " Ȟǣđ 2"),
|
||||
(4, 0, 3, "###"), (4, 3, 6, " Ȟǣđ 3"),
|
||||
(6, 0, 4, "####"), (6, 4, 6, " Ȟǣđ 4"),
|
||||
(8, 0, 2, "#!"), (8, 2, 7, " Ȟǣđ A1"),
|
||||
(10, 0, 3, "##!"), (10, 3, 7, " Ȟǣđ A2"),
|
||||
(12, 0, 4, "###!"), (12, 4, 7, " Ȟǣđ A3"),
|
||||
]
|
||||
for i in range(0, len(formats), 2):
|
||||
assert formats[i].foreground().color().getRgb() == colHeadMark
|
||||
assert formats[i+1].foreground().color().getRgb() == colHeadText
|
||||
|
||||
# Unicode > 0xFFFF
|
||||
doc.setPlainText(
|
||||
"# 😇😎 1\n\n"
|
||||
"## 😇😎 2\n\n"
|
||||
"### 😇😎 3\n\n"
|
||||
"#### 😇😎 4\n\n"
|
||||
"#! 😇😎 A1\n\n"
|
||||
"##! 😇😎 A2\n\n"
|
||||
"###! 😇😎 A3\n\n"
|
||||
)
|
||||
syntax.rehighlightByType(BLOCK_TITLE)
|
||||
assert 0xffff < maxOrd(doc.toPlainText()) <= 0xffffffff
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 1, "#"), (0, 1, 7, " 😇😎 1"),
|
||||
(2, 0, 2, "##"), (2, 2, 7, " 😇😎 2"),
|
||||
(4, 0, 3, "###"), (4, 3, 7, " 😇😎 3"),
|
||||
(6, 0, 4, "####"), (6, 4, 7, " 😇😎 4"),
|
||||
(8, 0, 2, "#!"), (8, 2, 8, " 😇😎 A1"),
|
||||
(10, 0, 3, "##!"), (10, 3, 8, " 😇😎 A2"),
|
||||
(12, 0, 4, "###!"), (12, 4, 8, " 😇😎 A3"),
|
||||
]
|
||||
for i in range(0, len(formats), 2):
|
||||
assert formats[i].foreground().color().getRgb() == colHeadMark
|
||||
assert formats[i+1].foreground().color().getRgb() == colHeadText
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiDocHighlighter_Comments(syntax):
|
||||
"""Test highlighting of comments."""
|
||||
theme = SHARED.theme
|
||||
doc = syntax.document()
|
||||
assert doc is not None
|
||||
|
||||
# Settings
|
||||
syntax._tHandle = T_HANDLE
|
||||
|
||||
colHidden = theme.syntaxTheme.hidden.getRgb()
|
||||
colMod = theme.syntaxTheme.mod.getRgb()
|
||||
colValue = theme.syntaxTheme.val.getRgb()
|
||||
colNote = theme.syntaxTheme.note.getRgb()
|
||||
|
||||
# Ascii
|
||||
doc.setPlainText(
|
||||
"% Plain\n"
|
||||
"%~ Ignored\n"
|
||||
"%Synopsis: Synopsis\n"
|
||||
"%Note.Stuff: Note\n"
|
||||
)
|
||||
syntax.rehighlight()
|
||||
assert maxOrd(doc.toPlainText()) <= 0x7f
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 7, "% Plain"),
|
||||
(1, 0, 10, "%~ Ignored"),
|
||||
(2, 0, 10, "%Synopsis:"), (2, 10, 9, " Synopsis"),
|
||||
(3, 0, 6, "%Note."), (3, 6, 6, "Stuff:"), (3, 12, 5, " Note"),
|
||||
]
|
||||
assert formats[0].foreground().color().getRgb() == colHidden
|
||||
assert formats[1].foreground().color().getRgb() == colHidden
|
||||
assert formats[1].fontStrikeOut() is True
|
||||
assert formats[2].foreground().color().getRgb() == colMod
|
||||
assert formats[3].foreground().color().getRgb() == colNote
|
||||
assert formats[4].foreground().color().getRgb() == colMod
|
||||
assert formats[5].foreground().color().getRgb() == colValue
|
||||
assert formats[6].foreground().color().getRgb() == colNote
|
||||
|
||||
# Unicode <= 0xFFFF
|
||||
doc.setPlainText(
|
||||
"% Рівнина\n"
|
||||
"%~ Ігноровано\n"
|
||||
"%Synopsis: Синопсис\n"
|
||||
"%Note.Stuff: Примітка\n"
|
||||
)
|
||||
syntax.rehighlight()
|
||||
assert 0x7f < maxOrd(doc.toPlainText()) <= 0xffff
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 9, "% Рівнина"),
|
||||
(1, 0, 13, "%~ Ігноровано"),
|
||||
(2, 0, 10, "%Synopsis:"), (2, 10, 9, " Синопсис"),
|
||||
(3, 0, 6, "%Note."), (3, 6, 6, "Stuff:"), (3, 12, 9, " Примітка"),
|
||||
]
|
||||
assert formats[0].foreground().color().getRgb() == colHidden
|
||||
assert formats[1].foreground().color().getRgb() == colHidden
|
||||
assert formats[1].fontStrikeOut() is True
|
||||
assert formats[2].foreground().color().getRgb() == colMod
|
||||
assert formats[3].foreground().color().getRgb() == colNote
|
||||
assert formats[4].foreground().color().getRgb() == colMod
|
||||
assert formats[5].foreground().color().getRgb() == colValue
|
||||
assert formats[6].foreground().color().getRgb() == colNote
|
||||
|
||||
# Unicode > 0xFFFF
|
||||
doc.setPlainText(
|
||||
"% 😎😎\n"
|
||||
"%~ 🙈🙈🙈\n"
|
||||
"%Synopsis: 😍😍😍😍\n"
|
||||
"%Note.Stuff: 😡😡😡😡😡\n"
|
||||
)
|
||||
syntax.rehighlight()
|
||||
assert 0xffff < maxOrd(doc.toPlainText()) <= 0xffffffff
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 6, "% 😎😎"),
|
||||
(1, 0, 9, "%~ 🙈🙈🙈"),
|
||||
(2, 0, 10, "%Synopsis:"), (2, 10, 9, " 😍😍😍😍"),
|
||||
(3, 0, 6, "%Note."), (3, 6, 6, "Stuff:"), (3, 12, 11, " 😡😡😡😡😡"),
|
||||
]
|
||||
assert formats[0].foreground().color().getRgb() == colHidden
|
||||
assert formats[1].foreground().color().getRgb() == colHidden
|
||||
assert formats[1].fontStrikeOut() is True
|
||||
assert formats[2].foreground().color().getRgb() == colMod
|
||||
assert formats[3].foreground().color().getRgb() == colNote
|
||||
assert formats[4].foreground().color().getRgb() == colMod
|
||||
assert formats[5].foreground().color().getRgb() == colValue
|
||||
assert formats[6].foreground().color().getRgb() == colNote
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiDocHighlighter_Special(syntax):
|
||||
"""Test highlighting of special commands."""
|
||||
theme = SHARED.theme
|
||||
doc = syntax.document()
|
||||
assert doc is not None
|
||||
|
||||
# Settings
|
||||
syntax._tHandle = T_HANDLE
|
||||
|
||||
colErr = theme.syntaxTheme.error.getRgb()
|
||||
colCode = theme.syntaxTheme.code.getRgb()
|
||||
colValue = theme.syntaxTheme.val.getRgb()
|
||||
|
||||
# Ascii
|
||||
doc.setPlainText(
|
||||
"[NewPage]\n"
|
||||
"[New Page]\n"
|
||||
"[VSpace]\n"
|
||||
"[VSpace:123]\n"
|
||||
"[VSpace:Meh]\n"
|
||||
)
|
||||
syntax.rehighlight()
|
||||
assert maxOrd(doc.toPlainText()) <= 0x7f
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 9, "[NewPage]"),
|
||||
(1, 0, 10, "[New Page]"),
|
||||
(2, 0, 8, "[VSpace]"),
|
||||
(3, 0, 8, "[VSpace:"), (3, 8, 3, "123"), (3, 11, 1, "]"),
|
||||
(4, 0, 8, "[VSpace:"), (4, 8, 3, "Meh"), (4, 11, 1, "]"),
|
||||
]
|
||||
assert formats[0].foreground().color().getRgb() == colCode
|
||||
assert formats[1].foreground().color().getRgb() == colCode
|
||||
assert formats[2].foreground().color().getRgb() == colCode
|
||||
assert formats[3].foreground().color().getRgb() == colCode
|
||||
assert formats[4].foreground().color().getRgb() == colValue
|
||||
assert formats[5].foreground().color().getRgb() == colCode
|
||||
assert formats[6].foreground().color().getRgb() == colCode
|
||||
assert formats[7].underlineColor().getRgb() == colErr
|
||||
assert formats[8].foreground().color().getRgb() == colCode
|
||||
|
||||
# Unicode <= 0xFFFF
|
||||
doc.setPlainText(
|
||||
"[NewPage]\n"
|
||||
"[New Page]\n"
|
||||
"[VSpace]\n"
|
||||
"[VSpace:123]\n"
|
||||
"[VSpace:⅘]\n"
|
||||
)
|
||||
syntax.rehighlight()
|
||||
assert 0x7f < maxOrd(doc.toPlainText()) <= 0xffff
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 9, "[NewPage]"),
|
||||
(1, 0, 10, "[New Page]"),
|
||||
(2, 0, 8, "[VSpace]"),
|
||||
(3, 0, 8, "[VSpace:"), (3, 8, 3, "123"), (3, 11, 1, "]"),
|
||||
(4, 0, 8, "[VSpace:"), (4, 8, 1, "⅘"), (4, 9, 1, "]"),
|
||||
]
|
||||
assert formats[0].foreground().color().getRgb() == colCode
|
||||
assert formats[1].foreground().color().getRgb() == colCode
|
||||
assert formats[2].foreground().color().getRgb() == colCode
|
||||
assert formats[3].foreground().color().getRgb() == colCode
|
||||
assert formats[4].foreground().color().getRgb() == colValue
|
||||
assert formats[5].foreground().color().getRgb() == colCode
|
||||
assert formats[6].foreground().color().getRgb() == colCode
|
||||
assert formats[7].underlineColor().getRgb() == colErr
|
||||
assert formats[8].foreground().color().getRgb() == colCode
|
||||
|
||||
# Unicode > 0xFFFF
|
||||
doc.setPlainText(
|
||||
"[NewPage]\n"
|
||||
"[New Page]\n"
|
||||
"[VSpace]\n"
|
||||
"[VSpace:123]\n"
|
||||
"[VSpace:🙈🙈]\n"
|
||||
)
|
||||
syntax.rehighlight()
|
||||
assert 0xffff < maxOrd(doc.toPlainText()) <= 0xffffffff
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 9, "[NewPage]"),
|
||||
(1, 0, 10, "[New Page]"),
|
||||
(2, 0, 8, "[VSpace]"),
|
||||
(3, 0, 8, "[VSpace:"), (3, 8, 3, "123"), (3, 11, 1, "]"),
|
||||
(4, 0, 8, "[VSpace:"), (4, 8, 4, "🙈🙈"), (4, 12, 1, "]"),
|
||||
]
|
||||
assert formats[0].foreground().color().getRgb() == colCode
|
||||
assert formats[1].foreground().color().getRgb() == colCode
|
||||
assert formats[2].foreground().color().getRgb() == colCode
|
||||
assert formats[3].foreground().color().getRgb() == colCode
|
||||
assert formats[4].foreground().color().getRgb() == colValue
|
||||
assert formats[5].foreground().color().getRgb() == colCode
|
||||
assert formats[6].foreground().color().getRgb() == colCode
|
||||
assert formats[7].underlineColor().getRgb() == colErr
|
||||
assert formats[8].foreground().color().getRgb() == colCode
|
||||
|
||||
|
||||
@pytest.mark.gui
|
||||
def testGuiDocHighlighter_Text(monkeypatch, syntax):
|
||||
"""Test highlighting of text."""
|
||||
theme = SHARED.theme
|
||||
doc = syntax.document()
|
||||
assert doc is not None
|
||||
|
||||
# Settings
|
||||
syntax._tHandle = T_HANDLE
|
||||
syntax._isNovel = True
|
||||
syntax.setSpellCheck(True)
|
||||
monkeypatch.setattr(SHARED.spelling, "checkWord", lambda *a: False)
|
||||
|
||||
colHidden = theme.syntaxTheme.hidden.getRgb()
|
||||
colEmph = theme.syntaxTheme.emph.getRgb()
|
||||
colLink = theme.syntaxTheme.link.getRgb()
|
||||
colSpell = theme.syntaxTheme.spell.getRgb()
|
||||
colCode = theme.syntaxTheme.code.getRgb()
|
||||
colDialogue = theme.syntaxTheme.dialN.getRgb()
|
||||
colAltDialogue = theme.syntaxTheme.dialA.getRgb()
|
||||
|
||||
# Ascii
|
||||
doc.setPlainText(
|
||||
"Text **bold** text _italic_ text ~~strike~~ text [b]bold[/b], http://example.com\n\n"
|
||||
)
|
||||
syntax.rehighlight()
|
||||
assert maxOrd(doc.toPlainText()) <= 0x7f
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 4, "Text"),
|
||||
(0, 5, 2, "**"), (0, 7, 4, "bold"), (0, 11, 2, "**"),
|
||||
(0, 14, 4, "text"),
|
||||
(0, 19, 1, "_"), (0, 20, 6, "italic"), (0, 26, 1, "_"),
|
||||
(0, 28, 4, "text"),
|
||||
(0, 33, 2, "~~"), (0, 35, 6, "strike"), (0, 41, 2, "~~"),
|
||||
(0, 44, 4, "text"),
|
||||
(0, 49, 3, "[b]"), (0, 52, 4, "bold"), (0, 56, 4, "[/b]"),
|
||||
(0, 62, 18, "http://example.com"),
|
||||
]
|
||||
assert formats[0].underlineColor().getRgb() == colSpell # Text
|
||||
assert formats[1].foreground().color().getRgb() == colHidden # **
|
||||
assert formats[2].foreground().color().getRgb() == colEmph # bold
|
||||
assert formats[2].underlineColor().getRgb() == colSpell
|
||||
assert formats[3].foreground().color().getRgb() == colHidden # **
|
||||
assert formats[4].underlineColor().getRgb() == colSpell # text
|
||||
assert formats[5].foreground().color().getRgb() == colHidden # _
|
||||
assert formats[6].foreground().color().getRgb() == colEmph # italic
|
||||
assert formats[6].underlineColor().getRgb() == colSpell
|
||||
assert formats[7].foreground().color().getRgb() == colHidden # _
|
||||
assert formats[8].underlineColor().getRgb() == colSpell # text
|
||||
assert formats[9].foreground().color().getRgb() == colHidden # ~~
|
||||
assert formats[10].foreground().color().getRgb() == colHidden # strike
|
||||
assert formats[10].fontStrikeOut() is True
|
||||
assert formats[10].underlineColor().getRgb() == colSpell
|
||||
assert formats[11].foreground().color().getRgb() == colHidden # ~~
|
||||
assert formats[12].underlineColor().getRgb() == colSpell # text
|
||||
assert formats[13].foreground().color().getRgb() == colCode # [b]
|
||||
assert formats[14].underlineColor().getRgb() == colSpell # bold
|
||||
assert formats[15].foreground().color().getRgb() == colCode # [/b]
|
||||
assert formats[16].foreground().color().getRgb() == colLink # http://example.com
|
||||
|
||||
# Spell Check
|
||||
data = doc.findBlockByNumber(0).userData()
|
||||
assert isinstance(data, TextBlockData)
|
||||
assert data.metaData == [(62, 80, "http://example.com", "url")]
|
||||
assert data.spellErrors == [
|
||||
(0, 4, "Text"), (7, 11, "bold"),
|
||||
(14, 18, "text"), (20, 26, "italic"),
|
||||
(28, 32, "text"), (35, 41, "strike"),
|
||||
(44, 48, "text"), (52, 56, "bold"),
|
||||
]
|
||||
|
||||
# Unicode <= 0xFFFF
|
||||
doc.setPlainText(
|
||||
"\u201cDialogue,\u201d and then ::dialogue::, http://example.com\n\n"
|
||||
)
|
||||
syntax.rehighlight()
|
||||
assert 0x7f < maxOrd(doc.toPlainText()) <= 0xffff
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 1, "\u201c"), (0, 1, 8, "Dialogue"), (0, 9, 2, ",\u201d"),
|
||||
(0, 12, 3, "and"), (0, 16, 4, "then"),
|
||||
(0, 21, 2, "::"), (0, 23, 8, "dialogue"), (0, 31, 2, "::"),
|
||||
(0, 35, 18, "http://example.com"),
|
||||
]
|
||||
assert formats[0].foreground().color().getRgb() == colDialogue # Quote
|
||||
assert formats[1].foreground().color().getRgb() == colDialogue # Dialogue
|
||||
assert formats[1].underlineColor().getRgb() == colSpell
|
||||
assert formats[2].foreground().color().getRgb() == colDialogue # Quote
|
||||
assert formats[3].underlineColor().getRgb() == colSpell # and
|
||||
assert formats[4].underlineColor().getRgb() == colSpell # then
|
||||
assert formats[5].foreground().color().getRgb() == colAltDialogue # ::
|
||||
assert formats[6].foreground().color().getRgb() == colAltDialogue # dialogue
|
||||
assert formats[6].underlineColor().getRgb() == colSpell
|
||||
assert formats[7].foreground().color().getRgb() == colAltDialogue # ::
|
||||
assert formats[8].foreground().color().getRgb() == colLink # http://example.com
|
||||
|
||||
# Spell Check
|
||||
data = doc.findBlockByNumber(0).userData()
|
||||
assert isinstance(data, TextBlockData)
|
||||
assert data.metaData == [(35, 53, "http://example.com", "url")]
|
||||
assert data.spellErrors == [
|
||||
(1, 9, "Dialogue"), (12, 15, "and"),
|
||||
(16, 20, "then"), (23, 31, "dialogue"),
|
||||
]
|
||||
|
||||
# Unicode > 0xFFFF
|
||||
doc.setPlainText(
|
||||
"\u201c😁 Grinning 😁,\u201d and then ::🙊 shush 🙊::, http://example.com\n\n"
|
||||
)
|
||||
syntax.rehighlight()
|
||||
assert 0xffff < maxOrd(doc.toPlainText()) <= 0xffffffff
|
||||
|
||||
pieces, formats = getFragments(syntax)
|
||||
assert pieces == [
|
||||
(0, 0, 4, "\u201c😁 "), (0, 4, 8, "Grinning"), (0, 12, 5, " 😁,\u201d"),
|
||||
(0, 18, 3, "and"), (0, 22, 4, "then"),
|
||||
(0, 27, 5, "::🙊 "), (0, 32, 5, "shush"), (0, 37, 5, " 🙊::"),
|
||||
(0, 44, 18, "http://example.com"),
|
||||
]
|
||||
assert formats[0].foreground().color().getRgb() == colDialogue # Quote😁
|
||||
assert formats[1].foreground().color().getRgb() == colDialogue # Grinning
|
||||
assert formats[1].underlineColor().getRgb() == colSpell
|
||||
assert formats[2].foreground().color().getRgb() == colDialogue # 😁Quote
|
||||
assert formats[3].underlineColor().getRgb() == colSpell # and
|
||||
assert formats[4].underlineColor().getRgb() == colSpell # then
|
||||
assert formats[5].foreground().color().getRgb() == colAltDialogue # ::🙊
|
||||
assert formats[6].foreground().color().getRgb() == colAltDialogue # shush
|
||||
assert formats[6].underlineColor().getRgb() == colSpell
|
||||
assert formats[7].foreground().color().getRgb() == colAltDialogue # 🙊::
|
||||
assert formats[8].foreground().color().getRgb() == colLink # http://example.com
|
||||
|
||||
# Spell Check
|
||||
data = doc.findBlockByNumber(0).userData()
|
||||
assert isinstance(data, TextBlockData)
|
||||
assert data.metaData == [(40, 58, "http://example.com", "url")]
|
||||
assert data.spellErrors == [
|
||||
(4, 12, "Grinning"), (18, 21, "and"),
|
||||
(22, 26, "then"), (32, 37, "shush"),
|
||||
]
|
||||
Reference in New Issue
Block a user