--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ProjectKivy/CompleterKivy.py Sat Sep 09 17:43:15 2023 +0200 @@ -0,0 +1,179 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2023 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.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 ':' + elif char == "\n" and self.__autoIndentation: + txt = self.editor.text(line - 1) + 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) + + 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