diff -r 63d6350f3a34 -r b854a825d483 QScintilla/MiniEditor.py --- a/QScintilla/MiniEditor.py Thu Feb 01 19:32:19 2018 +0100 +++ b/QScintilla/MiniEditor.py Fri Feb 02 19:42:01 2018 +0100 @@ -34,6 +34,8 @@ import Utilities import Preferences +from ThirdParty.EditorConfig import editorconfig + class MiniScintilla(QsciScintillaCompat): """ @@ -120,7 +122,7 @@ self.__textEdit.clearSearchIndicators = self.clearSearchIndicators self.__textEdit.setSearchIndicator = self.setSearchIndicator self.__textEdit.setUtf8(True) - self.encoding = Preferences.getEditor("DefaultEncoding") + self.srHistory = { "search": [], @@ -184,9 +186,11 @@ self.__textEdit.selectionChanged.connect( self.__replaceWidget.selectionChanged) - self.__setCurrentFile("") if filename: self.__loadFile(filename, filetype) + else: + self.__setCurrentFile("") + self.encoding = self.__getEditorConfig("DefaultEncoding") self.__checkActions() @@ -252,25 +256,8 @@ fileName = E5FileDialog.getSaveFileName(self) if not fileName: return - - QApplication.setOverrideCursor(Qt.WaitCursor) - txt = self.__textEdit.text() - try: - self.encoding = Utilities.writeEncodedFile( - fileName, txt, self.encoding) - except (IOError, Utilities.CodingError, UnicodeError) as why: - E5MessageBox.critical( - self, self.tr('Save File'), - self.tr('<p>The file <b>{0}</b> could not be saved.<br/>' - 'Reason: {1}</p>') - .format(fileName, str(why))) - QApplication.restoreOverrideCursor() - return - QApplication.restoreOverrideCursor() - self.__statusBar.showMessage(self.tr("File saved"), 2000) - - return + self.__writeFile(fileName) def __about(self): """ @@ -2304,10 +2291,18 @@ @param fileName name of the file to load (string) @param filetype type of the source file (string) """ + self.__loadEditorConfig(fileName=fileName) + QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) try: - txt, self.encoding = Utilities.readEncodedFile(fileName) + encoding = self.__getEditorConfig("DefaultEncoding", + nodefault=True) + if encoding: + txt, self.encoding = Utilities.readEncodedFileWithEncoding( + fileName, encoding) + else: + txt, self.encoding = Utilities.readEncodedFile(fileName) except (UnicodeDecodeError, IOError) as why: QApplication.restoreOverrideCursor() E5MessageBox.critical( @@ -2328,6 +2323,7 @@ self.__setCurrentFile(fileName) fileEol = self.__textEdit.detectEolString(txt) + # TODO: editorconfig: end_of_line self.__textEdit.setEolModeByEolString(fileEol) self.__statusBar.showMessage(self.tr("File loaded"), 2000) @@ -2336,36 +2332,57 @@ """ Private method to save to the given file. - @param fileName name of the file to save to (string) - @return flag indicating success (boolean) + @param fileName name of the file to save to + @type str + @return flag indicating success + @rtype bool """ + res = self.__writeFile(fileName) + + if res: + self.editorSaved.emit() + self.__setCurrentFile(fileName) + + self.__checkActions() + + return res + + def __writeFile(self, fileName): + """ + Private method to write the current editor text to a file. + + @param fileName name of the file to be written to + @type str + @return flag indicating success + @rtype bool + """ + # TODO: editorconfig: apply end_of_line, trim_trailing_whitespace, + # insert_final_newline + config = self.__loadEditorConfigObject(fileName) + QApplication.setOverrideCursor(Qt.WaitCursor) txt = self.__textEdit.text() + # TODO: editorconfig: insert_final_newline try: + editorConfigEncoding = self.__getEditorConfig( + "DefaultEncoding", nodefault=True, config=config) self.encoding = Utilities.writeEncodedFile( - fileName, txt, self.encoding) + fileName, txt, self.encoding, + forcedEncoding=editorConfigEncoding) except (IOError, Utilities.CodingError, UnicodeError) as why: + QApplication.restoreOverrideCursor() E5MessageBox.critical( self, self.tr('Save File'), self.tr('<p>The file <b>{0}</b> could not be saved.<br/>' 'Reason: {1}</p>') .format(fileName, str(why))) - QApplication.restoreOverrideCursor() - - self.__checkActions() - return False QApplication.restoreOverrideCursor() - self.editorSaved.emit() - - self.__setCurrentFile(fileName) self.__statusBar.showMessage(self.tr("File saved"), 2000) - self.__checkActions() - return True - + def __setCurrentFile(self, fileName): """ Private method to register the file name of the current file. @@ -2386,6 +2403,8 @@ self.setWindowModified(False) self.setLanguage(self.__bindName(self.__textEdit.text(0))) + + self.__loadEditorConfig() def getFileName(self): """ @@ -2506,9 +2525,14 @@ """ Private method to configure the text display. """ + # TODO: editorconfig: move these to separate method called, when + # EditorConfig has been loaded + # TODO: editorconfig: tab_width self.__textEdit.setTabWidth(Preferences.getEditor("TabWidth")) + # TODO: editorconfig: indent_size self.__textEdit.setIndentationWidth( Preferences.getEditor("IndentWidth")) + # TODO: editorconfig: indent_style if self.lexer_ and self.lexer_.alwaysKeepTabs(): self.__textEdit.setIndentationsUseTabs(True) else: @@ -2610,6 +2634,7 @@ """ Private method to configure the eol mode of the editor. """ + # TODO: editorconfig: end_of_line eolMode = Preferences.getEditor("EOLMode") eolMode = QsciScintilla.EolMode(eolMode) self.__textEdit.setEolMode(eolMode) @@ -3239,7 +3264,100 @@ else: self.filetype = filetype + # TODO: editorconfig: end_of_line fileEol = self.__textEdit.detectEolString(txt) self.__textEdit.setEolModeByEolString(fileEol) self.__textEdit.setModified(False) + + ####################################################################### + ## Methods implementing the interface to EditorConfig + ####################################################################### + + def __loadEditorConfig(self, fileName=""): + """ + Private method to load the EditorConfig properties. + + @param fileName name of the file + @type str + """ + if not fileName: + fileName = self.__curFile + + self.__editorConfig = self.__loadEditorConfigObject(fileName) + + def __loadEditorConfigObject(self, fileName): + """ + Private method to load the EditorConfig properties for the given + file name. + + @param fileName name of the file + @type str + @return EditorConfig dictionary + @rtype dict + """ + editorConfig = {} + + if fileName: + try: + editorConfig = editorconfig.get_properties(fileName) + except editorconfig.EditorConfigError: + E5MessageBox.warning( + self, + self.tr("EditorConfig Properties"), + self.tr("""<p>The EditorConfig properties for file""" + """ <b>{0}</b> could not be loaded.</p>""") + .format(fileName)) + + return editorConfig + + def __getEditorConfig(self, option, nodefault=False, config=None): + """ + Private method to get the requested option via EditorConfig. + + If there is no EditorConfig defined, the equivalent built-in option + will be used (Preferences.getEditor(). The option must be given as the + Preferences option key. The mapping to the EditorConfig option name + will be done within this method. + + @param option Preferences option key + @type str + @param nodefault flag indicating to not get the default value from + Preferences but return None instead + @type bool + @param config reference to an EditorConfig object or None + @type dict + @return value of requested setting or None if nothing was found and + nodefault parameter was True + @rtype any + """ + if config is None: + config = self.__editorConfig + + if not config: + if nodefault: + return None + else: + return Preferences.getEditor(option) + + try: + if option == "EOLMode": + value = config["end_of_line"] + if value == "lf": + value = QsciScintilla.EolUnix + elif value == "crlf": + value = QsciScintilla.EolWindows + elif value == "cr": + value = QsciScintilla.EolMac + else: + value = None + elif option == "DefaultEncoding": + value = config["charset"] + except KeyError: + value = None + + if value is None and not nodefault: + # use Preferences in case of error + value = Preferences.getEditor(option) + + return value