Updated autoreplace to handle quotes better, and to not destry undo history when replacing on a selection.
This commit is contained in:
+19
-17
@@ -58,15 +58,19 @@ class Config:
|
||||
self.mainPanePos = [300, 800]
|
||||
|
||||
## Text Editor
|
||||
self.textFixedW = True
|
||||
self.textWidth = 600
|
||||
self.textMargin = [40, 40]
|
||||
self.doReplace = True
|
||||
self.doReplaceQuote = True
|
||||
self.doReplaceDash = True
|
||||
self.doReplaceDots = True
|
||||
self.replaceQuotes = ["“","”"]
|
||||
self.wordCountTimer = 5.0
|
||||
self.textFixedW = True
|
||||
self.textWidth = 600
|
||||
self.textMargin = [40, 40]
|
||||
self.doReplace = True
|
||||
self.doReplaceSQuote = True
|
||||
self.doReplaceDQuote = True
|
||||
self.doReplaceDash = True
|
||||
self.doReplaceDots = True
|
||||
self.wordCountTimer = 5.0
|
||||
|
||||
self.fmtDoubleQuotes = ["“","”"]
|
||||
self.fmtSingleQuotes = ["‘","’"]
|
||||
self.fmtApostrophe = "’"
|
||||
|
||||
# Check if config file exists
|
||||
if path.isfile(path.join(self.confPath,self.confFile)):
|
||||
@@ -119,16 +123,14 @@ class Config:
|
||||
)
|
||||
if confParser.has_option(cnfSec,"autoreplace"):
|
||||
self.doReplace = confParser.getboolean(cnfSec,"autoreplace")
|
||||
if confParser.has_option(cnfSec,"repquotes"):
|
||||
self.doReplaceQuote = confParser.getboolean(cnfSec,"repquotes")
|
||||
if confParser.has_option(cnfSec,"repsquotes"):
|
||||
self.doReplaceSQuote = confParser.getboolean(cnfSec,"repsquotes")
|
||||
if confParser.has_option(cnfSec,"repdquotes"):
|
||||
self.doReplaceDQuote = confParser.getboolean(cnfSec,"repdquotes")
|
||||
if confParser.has_option(cnfSec,"repdash"):
|
||||
self.doReplaceDash = confParser.getboolean(cnfSec,"repdash")
|
||||
if confParser.has_option(cnfSec,"repdots"):
|
||||
self.doReplaceDots = confParser.getboolean(cnfSec,"repdots")
|
||||
if confParser.has_option(cnfSec,"usequotes"):
|
||||
self.replaceQuotes = self.unpackList(
|
||||
confParser.get(cnfSec,"usequotes"), 2, self.replaceQuotes
|
||||
)
|
||||
|
||||
## Path
|
||||
cnfSec = "Path"
|
||||
@@ -165,10 +167,10 @@ class Config:
|
||||
confParser.set(cnfSec,"width", str(self.textWidth))
|
||||
confParser.set(cnfSec,"margins", self.packList(self.textMargin))
|
||||
confParser.set(cnfSec,"autoreplace",str(self.doReplace))
|
||||
confParser.set(cnfSec,"repquotes", str(self.doReplaceQuote))
|
||||
confParser.set(cnfSec,"repsquotes", str(self.doReplaceSQuote))
|
||||
confParser.set(cnfSec,"repdquotes", str(self.doReplaceDQuote))
|
||||
confParser.set(cnfSec,"repdash", str(self.doReplaceDash))
|
||||
confParser.set(cnfSec,"repdots", str(self.doReplaceDots))
|
||||
confParser.set(cnfSec,"usequotes", self.packList(self.replaceQuotes))
|
||||
|
||||
## Path
|
||||
cnfSec = "Path"
|
||||
|
||||
+47
-11
@@ -30,13 +30,27 @@ class GuiDocEditor(QWidget):
|
||||
QWidget.__init__(self)
|
||||
|
||||
logger.debug("Initialising DocEditor ...")
|
||||
|
||||
# Class Variables
|
||||
self.mainConf = nw.CONFIG
|
||||
self.theParent = theParent
|
||||
|
||||
# Document Variables
|
||||
self.charCount = 0
|
||||
self.wordCount = 0
|
||||
self.paraCount = 0
|
||||
self.lastEdit = 0
|
||||
|
||||
# Typography
|
||||
self.typDQOpen = self.mainConf.fmtDoubleQuotes[0]
|
||||
self.typDQClose = self.mainConf.fmtDoubleQuotes[1]
|
||||
self.typSQOpen = self.mainConf.fmtSingleQuotes[0]
|
||||
self.typSQClose = self.mainConf.fmtSingleQuotes[1]
|
||||
self.typApos = self.mainConf.fmtApostrophe
|
||||
|
||||
# Editor State
|
||||
self.hasSelection = False
|
||||
|
||||
self.outerBox = QVBoxLayout()
|
||||
self.guiEditor = QTextEdit()
|
||||
if self.mainConf.textFixedW:
|
||||
@@ -59,6 +73,7 @@ class GuiDocEditor(QWidget):
|
||||
|
||||
self.guiEditor.setMinimumWidth(400)
|
||||
self.guiEditor.setAcceptRichText(False)
|
||||
self.guiEditor.keyPressEvent = self.keyPressEvent
|
||||
|
||||
self.theDoc = self.guiEditor.document()
|
||||
self.theDoc.setDocumentMargin(0)
|
||||
@@ -108,11 +123,22 @@ class GuiDocEditor(QWidget):
|
||||
# Document Events and Maintenance
|
||||
##
|
||||
|
||||
def keyPressEvent(self, keyEvent):
|
||||
"""Intercept key press events.
|
||||
We need to intercept key presses briefly to record the state of selection. This is in order
|
||||
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.
|
||||
"""
|
||||
self.hasSelection = self.guiEditor.textCursor().hasSelection()
|
||||
QTextEdit.keyPressEvent(self.guiEditor, keyEvent)
|
||||
return
|
||||
|
||||
def _docChange(self, thePos, charsRemoved, charsAdded):
|
||||
self.lastEdit = time()
|
||||
if not self.wcTimer.isActive():
|
||||
self.wcTimer.start()
|
||||
if self.mainConf.doReplace:
|
||||
if self.mainConf.doReplace and not self.hasSelection:
|
||||
self._docAutoReplace(self.theDoc.findBlock(thePos))
|
||||
logger.verbose("Doc change signal took %.3f µs" % ((time()-self.lastEdit)*1e6))
|
||||
return
|
||||
@@ -136,17 +162,27 @@ class GuiDocEditor(QWidget):
|
||||
theTwo = theText[thePos-2:thePos]
|
||||
theThree = theText[thePos-3:thePos]
|
||||
|
||||
if self.mainConf.doReplaceQuote and theOne == "\"":
|
||||
qOpen = self.mainConf.replaceQuotes[0]
|
||||
qClose = self.mainConf.replaceQuotes[1]
|
||||
nOpen = theText.count(qOpen)
|
||||
nClose = theText.count(qClose)
|
||||
if nOpen > nClose:
|
||||
self.guiEditor.textCursor().deletePreviousChar()
|
||||
self.guiEditor.textCursor().insertText(qClose)
|
||||
if self.mainConf.doReplaceDQuote and theTwo == " \"":
|
||||
self.guiEditor.textCursor().deletePreviousChar()
|
||||
self.guiEditor.textCursor().insertText(self.typSQOpen)
|
||||
|
||||
elif self.mainConf.doReplaceDQuote and theOne == "\"":
|
||||
self.guiEditor.textCursor().deletePreviousChar()
|
||||
if thePos == 1:
|
||||
self.guiEditor.textCursor().insertText(self.typDQOpen)
|
||||
else:
|
||||
self.guiEditor.textCursor().deletePreviousChar()
|
||||
self.guiEditor.textCursor().insertText(qOpen)
|
||||
self.guiEditor.textCursor().insertText(self.typDQClose)
|
||||
|
||||
elif self.mainConf.doReplaceSQuote and theTwo == " '":
|
||||
self.guiEditor.textCursor().deletePreviousChar()
|
||||
self.guiEditor.textCursor().insertText(self.typSQOpen)
|
||||
|
||||
elif self.mainConf.doReplaceSQuote and theOne == "'":
|
||||
self.guiEditor.textCursor().deletePreviousChar()
|
||||
if thePos == 1:
|
||||
self.guiEditor.textCursor().insertText(self.typSQOpen)
|
||||
else:
|
||||
self.guiEditor.textCursor().insertText(self.typSQClose)
|
||||
|
||||
elif self.mainConf.doReplaceDash and theTwo == "--":
|
||||
self.guiEditor.textCursor().deletePreviousChar()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#### Header 4
|
||||
|
||||
**Lorem** ipsum dolor sit amet, consectetur "adipiscing" elit. Proin vitae nisi augue. Sed elementum lacus risus, eu lobortis ipsum malesuada rutrum. Nam egestas elit id commodo porta. **Ut eget lacinia ipsum, non interdum mi.** Sed tincidunt commodo metus, at faucibus nisi finibus eget. In malesuada egestas nulla et tempor. //Nulla eu sem// vel mi sollicitudin cursus. Nullam ultricies ex eu dui scelerisque, ut venenatis turpis ultricies.
|
||||
**Lorem** ipsum dolor sit amet, consectetur "adipiscing" elit. Proin vitae nisi augue. Sed elementum lacus risus, eu lobortis ipsum malesuada rutrum. Nam egestas elit id commodo porta. **Ut eget lacinia ipsum, non interdum mi.** Sed tincidunt commodo metus, at faucibus nisi finibus eget. In malesuada egestas nulla et tempor. _Nulla eu sem_ vel mi sollicitudin cursus. Nullam ultricies ex eu dui scelerisque, ut venenatis turpis ultricies.
|
||||
|
||||
Nunc in ex molestie, __efficitur__ diam ~~semper~~, pellentesque eros. Morbi vel lacus quis turpis sagittis iaculis. Sed rhoncus tortor et finibus lobortis. Suspendisse non ultrices odio, at venenatis mi. Sed congue congue tortor, et egestas neque malesuada ac. Nulla facilisi. Maecenas finibus elementum vestibulum. Nam id rhoncus mauris, vel “ullamcorper” «neque».
|
||||
|
||||
|
||||
Reference in New Issue
Block a user