# -*- coding: utf-8 -*- """novelWriter Text Tokenizer novelWriter – Text Tokenizer ============================== Splits a piece of nW markdown text into its elements File History: Created: 2019-05-05 [0.0.1] """ import logging import re import nw from operator import itemgetter from PyQt5.QtCore import QRegularExpression from nw.project.document import NWDoc from nw.tools.translate import numberToWord from nw.constants import nwItemLayout logger = logging.getLogger(__name__) class Tokenizer(): FMT_B_B = 1 # Begin bold FMT_B_E = 2 # End bold FMT_I_B = 3 # Begin italics FMT_I_E = 4 # End italics FMT_U_B = 5 # Begin underline FMT_U_E = 6 # End underline T_EMPTY = 1 # Empty line (new paragraph) T_COMMENT = 2 # Comment line T_KEYWORD = 3 # Command line T_HEAD1 = 4 # Header 1 (title) T_HEAD2 = 5 # Header 2 (chapter) T_HEAD3 = 6 # Header 3 (scene) T_HEAD4 = 7 # Header 4 T_TEXT = 8 # Text line T_SEP = 9 # Scene separator T_SKIP = 10 # Paragraph break T_PBREAK = 11 # Page break A_LEFT = 1 # Left aligned A_RIGHT = 2 # Right aligned A_CENTRE = 3 # Centred A_JUSTIFY = 4 # Justified def __init__(self, theProject, theParent): self.mainConf = nw.CONFIG self.theProject = theProject self.theParent = theParent self.theText = None self.theHandle = None self.theItem = None self.theTokens = None self.theResult = None self.wordWrap = 0 self.doComments = False self.doKeywords = False self.fmtTitle = "%title%" self.fmtChapter = "%title%" self.fmtUnNum = "%title%" self.fmtScene = "%title%" self.fmtSection = "%title%" self.hideScene = False self.hideSection = False self.numChapter = 0 self.firstScene = False return ## # Setters ## def setComments(self, doComments): self.doComments = doComments return def setKeywords(self, doKeywords): self.doKeywords = doKeywords return def setWordWrap(self, wordWrap): if wordWrap >= 0: self.wordWrap = wordWrap else: self.wordWrap = 0 return def setTitleFormat(self, fmtTitle): self.fmtTitle = fmtTitle return def setChapterFormat(self, fmtChapter): self.fmtChapter = fmtChapter return def setUnNumberedFormat(self, fmtUnNum): self.fmtUnNum = fmtUnNum return def setSceneFormat(self, fmtScene, hideScene): self.fmtScene = fmtScene self.hideScene = hideScene return def setSectionFormat(self, fmtSection, hideSection): self.fmtSection = fmtSection self.hideSection = hideSection return ## # Class Methods ## def setText(self, theHandle, theText=None): self.theHandle = theHandle self.theItem = self.theProject.getItem(theHandle) if theText is not None: # If the text is set, just use that self.theText = theText else: # Otherwise, load it from file theDocument = NWDoc(self.theProject, self.theParent) self.theText = theDocument.openDocument(theHandle) return def doAutoReplace(self): if len(self.theProject.autoReplace) > 0: repDict = {} for aKey, aVal in self.theProject.autoReplace.items(): repDict["<%s>" % aKey] = aVal xRep = re.compile("|".join([re.escape(k) for k in repDict.keys()]), flags=re.DOTALL) self.theText = xRep.sub(lambda x: repDict[x.group(0)], self.theText) return def doPostProcessing(self): return def tokenizeText(self): """Scan the text for either lines starting with specific characters that indicate headers, comments, commands etc, or just contains plain text. in the case of plain text, apply the same RegExes that the syntax highlighter uses and save the locations of these formatting tags into the token array. """ # RegExes for adding formatting tags within text lines # Keep in sync with the DocHighlighter class rxFormats = [( QRegularExpression(r"(?