Merge branch 'master' into selectable_path
This commit is contained in:
@@ -37,10 +37,9 @@ class nwConst():
|
||||
|
||||
class nwRegEx():
|
||||
|
||||
FMT_B = r"(?<![\w|\*|_|\\])([\*|_]{2})(?!\s|\*|_)(.+?)(?<![\s|\\])(\1)(?!\w)"
|
||||
FMT_I = r"(?<![\w|\*|_|\\])([\*|_])(?!\s|\*|_)(.+?)(?<![\s|\\])(\1)(?!\w)"
|
||||
FMT_BI = r"(?<![\w|\*|\\])([\*]{3})(?!\s|\*)(.+?)(?<![\s|\\])(\1)(?!\w)"
|
||||
FMT_ST = r"(?<![\w|~|\\])([~]{2})(?!\s|~)(.+?)(?<![\s|\\])(\1)(?!\w)"
|
||||
FMT_I = r"(?<![\w\\])(_)(?![\s_])(.+?)(?<![\s\\])(\1)(?!\w)"
|
||||
FMT_B = r"(?<![\w\\])([\*]{2})(?![\s\*])(.+?)(?<![\s\\])(\1)(?!\w)"
|
||||
FMT_ST = r"(?<![\w\\])([~]{2})(?![\s~])(.+?)(?<![\s\\])(\1)(?!\w)"
|
||||
|
||||
# END Class nwRegEx
|
||||
|
||||
|
||||
+18
-19
@@ -76,25 +76,24 @@ class nwDocAction(Enum):
|
||||
PASTE = 5
|
||||
EMPH = 6
|
||||
STRONG = 7
|
||||
STRONGEMPH = 8
|
||||
STRIKE = 9
|
||||
S_QUOTE = 10
|
||||
D_QUOTE = 11
|
||||
SEL_ALL = 12
|
||||
SEL_PARA = 13
|
||||
FIND = 14
|
||||
REPLACE = 15
|
||||
GO_NEXT = 16
|
||||
GO_PREV = 17
|
||||
REPL_NEXT = 18
|
||||
BLOCK_H1 = 19
|
||||
BLOCK_H2 = 20
|
||||
BLOCK_H3 = 21
|
||||
BLOCK_H4 = 22
|
||||
BLOCK_COM = 23
|
||||
BLOCK_TXT = 24
|
||||
REPL_SNG = 25
|
||||
REPL_DBL = 26
|
||||
STRIKE = 8
|
||||
S_QUOTE = 9
|
||||
D_QUOTE = 10
|
||||
SEL_ALL = 11
|
||||
SEL_PARA = 12
|
||||
FIND = 13
|
||||
REPLACE = 14
|
||||
GO_NEXT = 15
|
||||
GO_PREV = 16
|
||||
REPL_NEXT = 17
|
||||
BLOCK_H1 = 18
|
||||
BLOCK_H2 = 19
|
||||
BLOCK_H3 = 20
|
||||
BLOCK_H4 = 21
|
||||
BLOCK_COM = 22
|
||||
BLOCK_TXT = 23
|
||||
REPL_SNG = 24
|
||||
REPL_DBL = 25
|
||||
|
||||
# END Enum nwDocAction
|
||||
|
||||
|
||||
+1
-4
@@ -107,6 +107,7 @@ class ToHtml(Tokenizer):
|
||||
"""Reverse the html entities replacement on the markdown text.
|
||||
Otherwise, all the &something; bits will also be in there.
|
||||
"""
|
||||
Tokenizer.doPostProcessing(self)
|
||||
if self.genMode == self.M_PREVIEW:
|
||||
# Doesn't matter for preview as we don't use the markdown
|
||||
return
|
||||
@@ -125,8 +126,6 @@ class ToHtml(Tokenizer):
|
||||
self.FMT_B_E : "</b>",
|
||||
self.FMT_I_B : "<i>",
|
||||
self.FMT_I_E : "</i>",
|
||||
self.FMT_S_B : "<b><i>",
|
||||
self.FMT_S_E : "</i></b>",
|
||||
self.FMT_D_B : "<span style='text-decoration: line-through;'>",
|
||||
self.FMT_D_E : "</span>",
|
||||
}
|
||||
@@ -136,8 +135,6 @@ class ToHtml(Tokenizer):
|
||||
self.FMT_B_E : "</strong>",
|
||||
self.FMT_I_B : "<em>",
|
||||
self.FMT_I_E : "</em>",
|
||||
self.FMT_S_B : "<strong><em>",
|
||||
self.FMT_S_E : "</em></strong>",
|
||||
self.FMT_D_B : "<del>",
|
||||
self.FMT_D_E : "</del>",
|
||||
}
|
||||
|
||||
+15
-7
@@ -44,10 +44,8 @@ class Tokenizer():
|
||||
FMT_B_E = 2 # End bold
|
||||
FMT_I_B = 3 # Begin italics
|
||||
FMT_I_E = 4 # End italics
|
||||
FMT_S_B = 5 # Begin bold italic
|
||||
FMT_S_E = 6 # End bold italic
|
||||
FMT_D_B = 7 # Begin strikeout
|
||||
FMT_D_E = 8 # End strikeout
|
||||
FMT_D_B = 5 # Begin strikeout
|
||||
FMT_D_E = 6 # End strikeout
|
||||
|
||||
T_EMPTY = 1 # Empty line (new paragraph)
|
||||
T_SYNOPSIS = 2 # Synopsis comment
|
||||
@@ -269,7 +267,6 @@ class Tokenizer():
|
||||
def doAutoReplace(self):
|
||||
"""Run through the user's auto-replace dictionary.
|
||||
"""
|
||||
|
||||
if len(self.theProject.autoReplace) > 0:
|
||||
repDict = {}
|
||||
for aKey, aVal in self.theProject.autoReplace.items():
|
||||
@@ -280,8 +277,20 @@ class Tokenizer():
|
||||
return
|
||||
|
||||
def doPostProcessing(self):
|
||||
"""Do some postprocessing. Overloaded by subclasses.
|
||||
"""Do some postprocessing. Overloaded by subclasses. This just
|
||||
does the standard escaped characters.
|
||||
"""
|
||||
escapeDict = {
|
||||
"\*" : "*",
|
||||
"\~" : "~",
|
||||
"\_" : "_",
|
||||
}
|
||||
escReplace = re.compile(
|
||||
"|".join([re.escape(k) for k in escapeDict.keys()]), flags=re.DOTALL
|
||||
)
|
||||
self.theResult = escReplace.sub(
|
||||
lambda x: escapeDict[x.group(0)], self.theResult
|
||||
)
|
||||
return
|
||||
|
||||
def tokenizeText(self):
|
||||
@@ -304,7 +313,6 @@ class Tokenizer():
|
||||
rxFormats = [
|
||||
(QRegularExpression(nwRegEx.FMT_I), [None, self.FMT_I_B, None, self.FMT_I_E]),
|
||||
(QRegularExpression(nwRegEx.FMT_B), [None, self.FMT_B_B, None, self.FMT_B_E]),
|
||||
(QRegularExpression(nwRegEx.FMT_BI), [None, self.FMT_S_B, None, self.FMT_S_E]),
|
||||
(QRegularExpression(nwRegEx.FMT_ST), [None, self.FMT_D_B, None, self.FMT_D_E]),
|
||||
]
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@ from os import path, unlink, rmdir
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# =========================================================================== #
|
||||
# Simple Word Counter
|
||||
# =========================================================================== #
|
||||
|
||||
def countWords(theText):
|
||||
"""Count words in a piece of text, skipping special syntax and
|
||||
comments.
|
||||
@@ -80,6 +84,10 @@ def countWords(theText):
|
||||
|
||||
return charCount, wordCount, paraCount
|
||||
|
||||
# =========================================================================== #
|
||||
# Convert an Integer to a Word Number
|
||||
# =========================================================================== #
|
||||
|
||||
def numberToWord(numVal, theLanguage):
|
||||
"""Wrapper for converting numbers to words for chapter headings.
|
||||
"""
|
||||
|
||||
+26
-70
@@ -515,13 +515,11 @@ class GuiDocEditor(QTextEdit):
|
||||
elif theAction == nwDocAction.PASTE:
|
||||
self.paste()
|
||||
elif theAction == nwDocAction.EMPH:
|
||||
self._toggleEmph(1)
|
||||
self._toggleFormat(1, "_")
|
||||
elif theAction == nwDocAction.STRONG:
|
||||
self._toggleEmph(2)
|
||||
elif theAction == nwDocAction.STRONGEMPH:
|
||||
self._toggleEmph(3)
|
||||
self._toggleFormat(2, "*")
|
||||
elif theAction == nwDocAction.STRIKE:
|
||||
self._toggleStrike()
|
||||
self._toggleFormat(2, "~")
|
||||
elif theAction == nwDocAction.S_QUOTE:
|
||||
self._wrapSelection(self.typSQOpen, self.typSQClose)
|
||||
elif theAction == nwDocAction.D_QUOTE:
|
||||
@@ -998,69 +996,27 @@ class GuiDocEditor(QTextEdit):
|
||||
theCursor = self.textCursor()
|
||||
if self.mainConf.autoSelect and not theCursor.hasSelection():
|
||||
theCursor.select(QTextCursor.WordUnderCursor)
|
||||
self.setTextCursor(theCursor)
|
||||
return theCursor
|
||||
|
||||
def _toggleEmph(self, eLevel):
|
||||
"""Toggle emphasis of a given level between 1 and 3, where 1 is
|
||||
italic, 2 is bold, and 3 is bold italic. The current level in
|
||||
the text is cLevel. The rules are as follows:
|
||||
|
||||
cLevel | eLevel | Result
|
||||
============+============+============
|
||||
None | Italic | Italic
|
||||
None | Bold | Bold
|
||||
None | BoldItalic | BoldItalic
|
||||
------------+------------+------------
|
||||
Italic | Italic | None
|
||||
Italic | Bold | BoldItalic
|
||||
Italic | BoldItalic | BoldItalic
|
||||
------------+------------+------------
|
||||
Bold | Italic | BoldItalic
|
||||
Bold | Bold | None
|
||||
Bold | BoldItalic | BoldItalic
|
||||
------------+------------+------------
|
||||
BoldItalic | Italic | Bold
|
||||
BoldItalic | Bold | Italic
|
||||
BoldItalic | BoldItalic | None
|
||||
|
||||
"""
|
||||
theCursor = self._autoSelect()
|
||||
if theCursor.hasSelection():
|
||||
posS = theCursor.selectionStart()
|
||||
posE = theCursor.selectionEnd()
|
||||
|
||||
numB = 0
|
||||
for n in range(3):
|
||||
if self.qDocument.characterAt(posS-n-1) == "*":
|
||||
numB += 1
|
||||
else:
|
||||
break
|
||||
# Underscore counts as a part of the word, so check that the
|
||||
# selection isn't wrapped in italics markers.
|
||||
reSelect = False
|
||||
if self.qDocument.characterAt(posS) == "_":
|
||||
posS += 1
|
||||
reSelect = True
|
||||
if self.qDocument.characterAt(posE) == "_":
|
||||
posE -= 1
|
||||
reSelect = True
|
||||
if reSelect:
|
||||
theCursor.clearSelection()
|
||||
theCursor.setPosition(posE-1)
|
||||
theCursor.movePosition(QTextCursor.Left, QTextCursor.KeepAnchor, posE-posS-1)
|
||||
|
||||
numA = 0
|
||||
for n in range(3):
|
||||
if self.qDocument.characterAt(posE+n) == "*":
|
||||
numA += 1
|
||||
else:
|
||||
break
|
||||
self.setTextCursor(theCursor)
|
||||
return theCursor
|
||||
|
||||
cLevel = min(numB, numA)
|
||||
if cLevel == 0:
|
||||
# Has no emphasis, set to desired level
|
||||
self._wrapSelection("*"*eLevel)
|
||||
elif cLevel == 3:
|
||||
# Has max, so reduce by desired level
|
||||
self._clearSurrounding(theCursor, eLevel)
|
||||
elif cLevel == eLevel:
|
||||
# Toggle mode, so clear what we had set
|
||||
self._clearSurrounding(theCursor, cLevel)
|
||||
else:
|
||||
# Already at 1 or 2, increase to 3
|
||||
self._wrapSelection("*"*(3 - cLevel))
|
||||
|
||||
return
|
||||
|
||||
def _toggleStrike(self):
|
||||
def _toggleFormat(self, fLen, fChar):
|
||||
"""Toggle strikethrough text.
|
||||
"""
|
||||
theCursor = self._autoSelect()
|
||||
@@ -1069,24 +1025,24 @@ class GuiDocEditor(QTextEdit):
|
||||
posE = theCursor.selectionEnd()
|
||||
|
||||
numB = 0
|
||||
for n in range(2):
|
||||
if self.qDocument.characterAt(posS-n-1) == "~":
|
||||
for n in range(fLen):
|
||||
if self.qDocument.characterAt(posS-n-1) == fChar:
|
||||
numB += 1
|
||||
else:
|
||||
break
|
||||
|
||||
numA = 0
|
||||
for n in range(2):
|
||||
if self.qDocument.characterAt(posE+n) == "~":
|
||||
for n in range(fLen):
|
||||
if self.qDocument.characterAt(posE+n) == fChar:
|
||||
numA += 1
|
||||
else:
|
||||
break
|
||||
|
||||
cLevel = min(numB, numA)
|
||||
if cLevel == 2:
|
||||
self._clearSurrounding(theCursor, 2)
|
||||
if cLevel == fLen:
|
||||
self._clearSurrounding(theCursor, fLen)
|
||||
else:
|
||||
self._wrapSelection("~~")
|
||||
self._wrapSelection(fChar*fLen)
|
||||
|
||||
return
|
||||
|
||||
|
||||
+32
-36
@@ -107,7 +107,6 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
"header4h" : self._makeFormat(self.colHeadH, "bold", 1.2),
|
||||
"bold" : self._makeFormat(self.colEmph, "bold"),
|
||||
"italic" : self._makeFormat(self.colEmph, "italic"),
|
||||
"bolditalic" : self._makeFormat(self.colEmph, ("bold","italic")),
|
||||
"strike" : self._makeFormat(self.colEmph, "strike"),
|
||||
"trailing" : self._makeFormat(self.colTrail, "background"),
|
||||
"nobreak" : self._makeFormat(self.colTrail, "background"),
|
||||
@@ -137,36 +136,6 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
}
|
||||
))
|
||||
|
||||
# Markdown
|
||||
self.hRules.append((
|
||||
nwRegEx.FMT_I, {
|
||||
1 : self.hStyles["hidden"],
|
||||
2 : self.hStyles["italic"],
|
||||
3 : self.hStyles["hidden"],
|
||||
}
|
||||
))
|
||||
self.hRules.append((
|
||||
nwRegEx.FMT_B, {
|
||||
1 : self.hStyles["hidden"],
|
||||
2 : self.hStyles["bold"],
|
||||
3 : self.hStyles["hidden"],
|
||||
}
|
||||
))
|
||||
self.hRules.append((
|
||||
nwRegEx.FMT_BI, {
|
||||
1 : self.hStyles["hidden"],
|
||||
2 : self.hStyles["bolditalic"],
|
||||
3 : self.hStyles["hidden"],
|
||||
}
|
||||
))
|
||||
self.hRules.append((
|
||||
nwRegEx.FMT_ST, {
|
||||
1 : self.hStyles["hidden"],
|
||||
2 : self.hStyles["strike"],
|
||||
3 : self.hStyles["hidden"],
|
||||
}
|
||||
))
|
||||
|
||||
# Quoted Strings
|
||||
if self.mainConf.highlightQuotes:
|
||||
self.hRules.append((
|
||||
@@ -185,6 +154,29 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
}
|
||||
))
|
||||
|
||||
# Markdown
|
||||
self.hRules.append((
|
||||
nwRegEx.FMT_I, {
|
||||
1 : self.hStyles["hidden"],
|
||||
2 : self.hStyles["italic"],
|
||||
3 : self.hStyles["hidden"],
|
||||
}
|
||||
))
|
||||
self.hRules.append((
|
||||
nwRegEx.FMT_B, {
|
||||
1 : self.hStyles["hidden"],
|
||||
2 : self.hStyles["bold"],
|
||||
3 : self.hStyles["hidden"],
|
||||
}
|
||||
))
|
||||
self.hRules.append((
|
||||
nwRegEx.FMT_ST, {
|
||||
1 : self.hStyles["hidden"],
|
||||
2 : self.hStyles["strike"],
|
||||
3 : self.hStyles["hidden"],
|
||||
}
|
||||
))
|
||||
|
||||
# Auto-Replace Tags
|
||||
self.hRules.append((
|
||||
r"<(\S+?)>", {
|
||||
@@ -302,10 +294,14 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
rxItt = rX.globalMatch(theText, 0)
|
||||
while rxItt.hasNext():
|
||||
rxMatch = rxItt.next()
|
||||
for xM in xFmt.keys():
|
||||
for xM in xFmt:
|
||||
xPos = rxMatch.capturedStart(xM)
|
||||
xLen = rxMatch.capturedLength(xM)
|
||||
self.setFormat(xPos, xLen, xFmt[xM])
|
||||
for x in range(xPos, xPos+xLen):
|
||||
spFmt = self.format(x)
|
||||
if spFmt != self.hStyles["hidden"]:
|
||||
spFmt.merge(xFmt[xM])
|
||||
self.setFormat(x, 1, spFmt)
|
||||
|
||||
if self.theDict is None or not self.spellCheck:
|
||||
return
|
||||
@@ -318,11 +314,11 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
continue
|
||||
xPos = rxMatch.capturedStart(0)
|
||||
xLen = rxMatch.capturedLength(0)
|
||||
for x in range(xLen):
|
||||
spFmt = self.format(xPos+x)
|
||||
for x in range(xPos, xPos+xLen):
|
||||
spFmt = self.format(x)
|
||||
spFmt.setUnderlineColor(self.colSpell)
|
||||
spFmt.setUnderlineStyle(QTextCharFormat.SpellCheckUnderline)
|
||||
self.setFormat(xPos+x, 1, spFmt)
|
||||
self.setFormat(x, 1, spFmt)
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -540,13 +540,6 @@ class GuiMainMenu(QMenuBar):
|
||||
self.aFmtStrong.triggered.connect(lambda: self._docAction(nwDocAction.STRONG))
|
||||
self.fmtMenu.addAction(self.aFmtStrong)
|
||||
|
||||
# Format > Very Strong Emphasis
|
||||
self.aFmtStrongEmph = QAction("Very Strong Emphasis", self)
|
||||
self.aFmtStrongEmph.setStatusTip("Add very strong emphasis to selected text (bold and italic)")
|
||||
self.aFmtStrongEmph.setShortcut("Ctrl+Shift+B")
|
||||
self.aFmtStrongEmph.triggered.connect(lambda: self._docAction(nwDocAction.STRONGEMPH))
|
||||
self.fmtMenu.addAction(self.aFmtStrongEmph)
|
||||
|
||||
# Format > Strikethrough
|
||||
self.aFmtStrike = QAction("Strikethrough", self)
|
||||
self.aFmtStrike.setStatusTip("Add strikethrough to selected text")
|
||||
|
||||
@@ -1008,7 +1008,6 @@ class GuiMain(QMainWindow):
|
||||
# Format
|
||||
self.addAction(self.mainMenu.aFmtEmph)
|
||||
self.addAction(self.mainMenu.aFmtStrong)
|
||||
self.addAction(self.mainMenu.aFmtStrongEmph)
|
||||
self.addAction(self.mainMenu.aFmtStrike)
|
||||
self.addAction(self.mainMenu.aFmtDQuote)
|
||||
self.addAction(self.mainMenu.aFmtSQuote)
|
||||
|
||||
Reference in New Issue
Block a user