From 146756a3957774c5aba36443e0ebf01beedfcdfa Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Tue, 29 Oct 2019 11:35:40 +0100 Subject: [PATCH] Added unicode constants class, and support for non-breaking spaces, which aren't preserved on save. --- nw/config.py | 6 +- nw/constants.py | 80 ++++++++++++++----- nw/gui/doceditor.py | 36 +++++++-- nw/gui/dochighlight.py | 10 +++ .../sampleNovel/data_b/a8a28a246524_main.nwd | 2 + sample/sampleNovel/nwProject.nwx | 12 +-- 6 files changed, 111 insertions(+), 35 deletions(-) diff --git a/nw/config.py b/nw/config.py index 695b31e0..e07852c6 100644 --- a/nw/config.py +++ b/nw/config.py @@ -19,7 +19,7 @@ from os import path, mkdir, makedirs, getcwd from appdirs import user_config_dir from datetime import datetime -from nw.constants import nwFiles +from nw.constants import nwFiles, nwUnicode from nw.common import splitVersionNumber from PyQt5.Qt import PYQT_VERSION_STR @@ -87,8 +87,8 @@ class Config: self.doReplaceDots = True self.wordCountTimer = 5.0 - self.fmtSingleQuotes = ["\u2018","\u2019"] - self.fmtDoubleQuotes = ["\u201c","\u201d"] + self.fmtSingleQuotes = [nwUnicode.U_LSQUO,nwUnicode.U_RSQUO] + self.fmtDoubleQuotes = [nwUnicode.U_LDQUO,nwUnicode.U_RDQUO] self.spellLanguage = "en_GB" diff --git a/nw/constants.py b/nw/constants.py index 4fa6ab02..e06942c8 100644 --- a/nw/constants.py +++ b/nw/constants.py @@ -142,26 +142,66 @@ class nwQuotes(): "\u300e", # Left white corner bracket "\u300f", # Right white corner bracket ] + +# END Class nwQuotes + +class nwUnicode: + """Suppoted unicode character constants and translation maps. + """ + + # Quotation Marks + U_QUOT = "\u0022" # Quotation mark + U_APOS = "\u0027" # Apostrophe + U_LAQUO = "\u00ab" # Left-pointing double angle quotation mark + U_RAQUO = "\u00bb" # Right-pointing double angle quotation mark + U_LSQUO = "\u2018" # Left single quotation mark + U_RSQUO = "\u2019" # Right single quotation mark + U_SBQUO = "\u201a" # Single low-9 quotation mark + U_SUQUO = "\u201b" # Single high-reversed-9 quotation mark + U_LDQUO = "\u201c" # Left double quotation mark + U_RDQUO = "\u201d" # Right double quotation mark + U_BDQUO = "\u201e" # Double low-9 quotation mark + U_UDQUO = "\u201f" # Double high-reversed-9 quotation mark + U_LSAQUO = "\u2039" # Single left-pointing angle quotation mark + U_RSAQUO = "\u203a" # Single right-pointing angle quotation mark + U_BDRQUO = "\u2e42" # Double low-reversed-9 quotation mark + U_LCQUO = "\u300c" # Left corner bracket + U_RCQUO = "\u300d" # Right corner bracket + U_LWCQUO = "\u300e" # Left white corner bracket + U_RECQUO = "\u300f" # Right white corner bracket + + # Punctuation + U_NDASH = "\u2013" # Short dash + U_MDASH = "\u2014" # Long dash + U_HELLIP = "\u2026" # Ellipsis + + # Other + U_NBSP = "\u00a0" # Non-breaking space + HTML = { - "\u0022" : """, - "\u0027" : "'", - "\u00ab" : "«", - "\u00bb" : "»", - "\u2018" : "‘", - "\u2019" : "’", - "\u201a" : "‚", - "\u201b" : "‛", - "\u201c" : "“", - "\u201d" : "”", - "\u201e" : "„", - "\u201f" : "‟", - "\u2039" : "‹", - "\u203a" : "›", - "\u2e42" : "⹂", - "\u300c" : "「", - "\u300d" : "」", - "\u300e" : "『", - "\u300f" : "』", + U_QUOT : """, + U_APOS : "'", + U_LAQUO : "«", + U_RAQUO : "»", + U_LSQUO : "‘", + U_RSQUO : "’", + U_SBQUO : "‚", + U_SUQUO : "‛", + U_LDQUO : "“", + U_RDQUO : "”", + U_BDQUO : "„", + U_UDQUO : "‟", + U_LSAQUO : "‹", + U_RSAQUO : "›", + U_BDRQUO : "⹂", + U_LCQUO : "「", + U_RCQUO : "」", + U_LWCQUO : "『", + U_LWCQUO : "『", + U_NDASH : "–", + U_MDASH : "—", + U_HELLIP : "…", + U_NBSP : " ", } -# END Class nwQuotes \ No newline at end of file +# END Class nwUnicode diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py index 03d3313d..e2ca9237 100644 --- a/nw/gui/doceditor.py +++ b/nw/gui/doceditor.py @@ -23,7 +23,7 @@ from nw.project.document import NWDoc from nw.gui.dochighlight import GuiDocHighlighter from nw.gui.wordcounter import WordCounter from nw.tools.spellcheck import NWSpellCheck -from nw.constants import nwFiles +from nw.constants import nwFiles, nwUnicode from nw.enum import nwDocAction, nwAlert logger = logging.getLogger(__name__) @@ -316,9 +316,26 @@ class GuiDocEditor(QTextEdit): to know whether we had a selection prior to triggering the _docChange slot, as we do not want to trigger autoreplace on selections. Autoreplace on selections messes with undo/redo history. + We also need to intercept the Shift key modifier for certain key combinations that modifies + standard keys like enter and space. However, we don't want to spend a lot of time in this + function as it is triggered on every keypress when typing. """ + self.hasSelection = self.textCursor().hasSelection() - QTextEdit.keyPressEvent(self, keyEvent) + + if keyEvent.modifiers() == Qt.ShiftModifier: + theKey = keyEvent.key() + if theKey == Qt.Key_Return: + self._insertHardBreak() + elif theKey == Qt.Key_Enter: + self._insertHardBreak() + elif theKey == Qt.Key_Space: + self._insertNonBreakingSpace() + else: + QTextEdit.keyPressEvent(self, keyEvent) + else: + QTextEdit.keyPressEvent(self, keyEvent) + return ## @@ -332,6 +349,13 @@ class GuiDocEditor(QTextEdit): theCursor.endEditBlock() return + def _insertNonBreakingSpace(self): + theCursor = self.textCursor() + theCursor.beginEditBlock() + theCursor.insertText(nwUnicode.U_NBSP) + theCursor.endEditBlock() + return + def _openSpellContext(self): self._openContextMenu(self.cursorRect().center()) return @@ -442,15 +466,15 @@ class GuiDocEditor(QTextEdit): elif self.mainConf.doReplaceDash and theTwo == "--": theCursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, 2) - theCursor.insertText("\u2013") + theCursor.insertText(nwUnicode.U_NDASH) - elif self.mainConf.doReplaceDash and theTwo == "\u2013-": + elif self.mainConf.doReplaceDash and theTwo == nwUnicode.U_NDASH+"-": theCursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, 2) - theCursor.insertText("\u2014") + theCursor.insertText(nwUnicode.U_MDASH) elif self.mainConf.doReplaceDots and theThree == "...": theCursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, 3) - theCursor.insertText("\u2026") + theCursor.insertText(nwUnicode.U_HELLIP) return diff --git a/nw/gui/dochighlight.py b/nw/gui/dochighlight.py index 74506f71..e356dbf7 100644 --- a/nw/gui/dochighlight.py +++ b/nw/gui/dochighlight.py @@ -16,6 +16,8 @@ import nw from PyQt5.QtCore import Qt, QRegularExpression from PyQt5.QtGui import QColor, QTextCharFormat, QFont, QSyntaxHighlighter, QBrush +from nw.constants import nwUnicode + logger = logging.getLogger(__name__) class GuiDocHighlighter(QSyntaxHighlighter): @@ -87,6 +89,7 @@ class GuiDocHighlighter(QSyntaxHighlighter): "strike" : self._makeFormat(self.colEmph, "strike"), "underline" : self._makeFormat(self.colEmph, "underline"), "trailing" : self._makeFormat(self.colTrail,"background"), + "nobreak" : self._makeFormat(self.colTrail,"background"), "dialogue1" : self._makeFormat(self.colDialN), "dialogue2" : self._makeFormat(self.colDialD), "dialogue3" : self._makeFormat(self.colDialS), @@ -145,6 +148,13 @@ class GuiDocHighlighter(QSyntaxHighlighter): } )) + # Non-breaking Space + self.hRules.append(( + "[\u00a0]+", { + 0 : self.hStyles["nobreak"], + } + )) + # Markdown self.hRules.append(( r"(? - + Sample Project Sample Project @@ -11,7 +11,7 @@ True ba8a28a246524 ba8a28a246524 - 859 + 864 B E @@ -103,10 +103,10 @@ Finished False UNNUMBERED - 626 - 101 - 3 - 583 + 658 + 106 + 4 + 678 A Note on Ipsums