Tue, 10 Dec 2024 15:48:59 +0100
Updated copyright for 2025.
# -*- coding: utf-8 -*- # Copyright (c) 2023 - 2025 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing the Kivy typing completer. """ import re from PyQt6.Qsci import QsciScintilla from eric7.QScintilla.TypingCompleters.CompleterBase import CompleterBase class CompleterKivy(CompleterBase): """ Class implementing the Kivy typing completer. """ def __init__(self, plugin, editor, parent=None): """ Constructor @param plugin reference to the plugin object @type ProjectKivyPlugin @param editor reference to the editor object @type Editor @param parent reference to the parent object @type QObject """ super().__init__(editor, parent) self.__plugin = plugin self.__autoIndentationRe = re.compile(r"(?:\(|\[|{|:)(\s*)\r?\n") self.__trailingBlankRe = re.compile(r"(?:,)(\s*)\r?\n") # Trailing blank after ':' is already covered by auto indent rule self.readSettings() def readSettings(self): """ Public slot called to reread the configuration parameters. """ self.setEnabled(self.__plugin.getTypingPreferences("EnabledTypingAids")) self.__insertClosingBrace = self.__plugin.getTypingPreferences( "InsertClosingBrace" ) self.__skipBrace = self.__plugin.getTypingPreferences("SkipBrace") self.__colonDetection = self.__plugin.getTypingPreferences("ColonDetection") self.__autoIndentation = self.__plugin.getTypingPreferences("AutoIndentation") self.__insertQuote = self.__plugin.getTypingPreferences("InsertQuote") self.__insertBlankColon = self.__plugin.getTypingPreferences("InsertBlankColon") self.__insertBlankComma = self.__plugin.getTypingPreferences("InsertBlankComma") def charAdded(self, charNumber): """ Public slot called to handle the user entering a character. @param charNumber value of the character entered @type int """ char = chr(charNumber) if char not in ( "{", "}", "[", "]", "(", ")", "<", ">", "'", '"', ":", ",", "\n", ): return # take the short route line, col = self.editor.getCursorPosition() if self.__inComment(line, col): return # open parenthesis # insert closing parenthesis if char == "(" and self.__insertClosingBrace: self.editor.insert(")") # open curly bracket # insert closing bracket elif char == "{" and self.__insertClosingBrace: self.editor.insert("}") # open bracket # insert closing bracket elif char == "[" and self.__insertClosingBrace: self.editor.insert("]") # open tag bracket # insert closing bracket elif char == "<" and self.__insertClosingBrace: self.editor.insert(">") # closing parenthesis # skip matching closing parenthesis elif char in (")", "}", "]", ">"): txt = self.editor.text(line) if col < len(txt) and char == txt[col] and self.__skipBrace: self.editor.setSelection(line, col, line, col + 1) self.editor.removeSelectedText() # colon # 1. skip colon if not last character # 2. insert blank if last character elif char == ":": text = self.editor.text(line) if col < len(text) and char == text[col]: if self.__colonDetection: self.editor.setSelection(line, col, line, col + 1) self.editor.removeSelectedText() elif self.__insertBlankColon and col == len(text.rstrip()): self.editor.insert(" ") self.editor.setCursorPosition(line, col + 1) # comma # insert blank elif char == "," and self.__insertBlankComma: self.editor.insert(" ") self.editor.setCursorPosition(line, col + 1) # double quote # insert double quote elif char == '"' and self.__insertQuote: self.editor.insert('"') # quote # insert quote elif char == "'" and self.__insertQuote: self.editor.insert("'") # new line # indent after line ending with auto indentation character elif char == "\n": txt = self.editor.text(line - 1) if self.__autoIndentation and self.__autoIndentationRe.search(txt): match = self.__autoIndentationRe.search(txt) if match is not None: startBlanks = match.start(1) endBlanks = match.end(1) if startBlanks != -1 and startBlanks != endBlanks: # previous line ends with whitespace, e.g. caused by # blank insertion above self.editor.setSelection( line - 1, startBlanks, line - 1, endBlanks ) self.editor.removeSelectedText() self.editor.indent(line) self.editor.setCursorPosition(line, 0) self.editor.editorCommand(QsciScintilla.SCI_VCHOME) elif ( self.__insertBlankColon or self.__insertBlankComma ) and self.__trailingBlankRe.search(txt): # remove blank at end of line inserted by blank insertion above match = self.__trailingBlankRe.search(txt) if match is not None: startBlanks = match.start(1) endBlanks = match.end(1) if startBlanks != -1 and startBlanks != endBlanks: self.editor.setSelection( line - 1, startBlanks, line - 1, endBlanks ) self.editor.removeSelectedText() self.editor.setCursorPosition(line, 0) self.editor.editorCommand(QsciScintilla.SCI_VCHOME) def __inComment(self, line, col): """ Private method to check, if the cursor is inside a comment. @param line current line @type int @param col current position within line @type int @return flag indicating, if the cursor is inside a comment @rtype bool """ txt = self.editor.text(line) if col == len(txt): col -= 1 while col >= 0: if txt[col] == "#": return True col -= 1 return False