diff options
author | Michele Calgaro <michele.calgaro@yahoo.it> | 2023-07-14 13:14:08 +0900 |
---|---|---|
committer | Michele Calgaro <michele.calgaro@yahoo.it> | 2023-07-14 13:14:08 +0900 |
commit | 63d63ad52bcd74acf73002073700a06b52e63ecb (patch) | |
tree | b63acba90386829df957281bb78639bc9f2e5b32 /src/IndentHandler.cpp | |
parent | 74e91ff8c198d22f07d943d96528c9c2d3eb629c (diff) | |
download | universal-indent-gui-tqt-63d63ad52bcd74acf73002073700a06b52e63ecb.tar.gz universal-indent-gui-tqt-63d63ad52bcd74acf73002073700a06b52e63ecb.zip |
Added logic to call the indenter and update the preview
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
Diffstat (limited to 'src/IndentHandler.cpp')
-rw-r--r-- | src/IndentHandler.cpp | 540 |
1 files changed, 232 insertions, 308 deletions
diff --git a/src/IndentHandler.cpp b/src/IndentHandler.cpp index 5e74706..40ebe3f 100644 --- a/src/IndentHandler.cpp +++ b/src/IndentHandler.cpp @@ -30,6 +30,7 @@ #include "UiGuiSettings.h" #include "TemplateBatchScript.h" +#include <tqaction.h> #include <tqapplication.h> #include <tqcheckbox.h> #include <tqcombobox.h> @@ -44,19 +45,15 @@ #include <tqpopupmenu.h> #include <tqprocess.h> #include <tqspinbox.h> +#include <tqstringlist.h> +#include <tqtextcodec.h> +#include <tqtextstream.h> #include <tqtoolbox.h> #include <tqtoolbutton.h> #include <tqtooltip.h> //--- #include <tqsettings.h> -//--- #include <tqstringlist.h> //--- #include <tqbytearray.h> -//--- #include <tqtextstream.h> -//--- #include <tqtextcodec.h> //--- #include <tqtscript.h> -//--- #include <tqdesktopservices.h> -//--- #include <tqaction.h> -//--- #include <tqcontextmenuevent.h> -//--- #include <tqtdebug.h> // \defgroup grp_Indenter All concerning handling of the indenter. @@ -306,32 +303,32 @@ TQString IndentHandler::generateShellScript(const TQString &configFilename) return shellScript; } -//--- /* -//--- \brief Format \a sourceCode by calling the indenter. -//--- -//--- The \a inputFileExtension has to be given as parameter so the called indenter -//--- can identify the programming language if needed. -//--- */ -//--- TQString IndentHandler::callIndenter(TQString sourceCode, TQString inputFileExtension) -//--- { -//--- if (m_indenterExecutableSuffix == ".js") -//--- { -//--- return callJavaScriptIndenter(sourceCode); -//--- } -//--- else -//--- { -//--- return callExecutableIndenter(sourceCode, inputFileExtension); -//--- } -//--- } -//--- -//--- /* -//--- \brief Format \a sourceCode by calling the interpreted JavaScript code of the indenter. -//--- -//--- The \a inputFileExtension has to be given as parameter so the called indenter -//--- can identify the programming language if needed. -//--- */ -//--- TQString IndentHandler::callJavaScriptIndenter(TQString sourceCode) -//--- { +/* + \brief Format \a sourceCode by calling the indenter. + + The \a inputFileExtension has to be given as parameter so the called indenter + can identify the programming language if needed. + */ +TQString IndentHandler::callIndenter(const TQString &sourceCode, const TQString &inputFileExtension) +{ + if (m_indenterExecutableSuffix == ".js") + { + return callJavaScriptIndenter(sourceCode); + } + else + { + return callExecutableIndenter(sourceCode, inputFileExtension); + } +} + +/* + \brief Format \a sourceCode by calling the interpreted JavaScript code of the indenter. + + The \a inputFileExtension has to be given as parameter so the called indenter + can identify the programming language if needed. + */ +TQString IndentHandler::callJavaScriptIndenter(const TQString &sourceCode) +{ //--- TQScriptEngine engine; //--- //--- engine.globalObject().setProperty("unformattedCode", sourceCode); @@ -346,263 +343,190 @@ TQString IndentHandler::generateShellScript(const TQString &configFilename) //--- //--- TQScriptValue value = engine.evaluate(jsDecoderCode); //--- return value.toString(); -//--- } -//--- -//--- /* -//--- \brief Format \a sourceCode by calling the binary executable of the indenter. -//--- -//--- The \a inputFileExtension has to be given as parameter so the called indenter -//--- can identify the programming language if needed. -//--- */ -//--- TQString IndentHandler::callExecutableIndenter(TQString sourceCode, TQString inputFileExtension) -//--- { -//--- Q_ASSERT_X(!m_inputFileName.isEmpty(), "callIndenter", "m_inputFileName is empty"); -//--- // Q_ASSERT_X( !m_outputFileName.isEmpty(), "callIndenter", "m_outputFileName is empty" ); -//--- Q_ASSERT_X(!m_indenterFileName.isEmpty(), "callIndenter", "m_indenterFileName is empty"); -//--- -//--- if (m_indenterFileName.isEmpty()) -//--- { -//--- return ""; -//--- } -//--- -//--- TQString formattedSourceCode; -//--- TQString indenterCompleteCallString; -//--- TQString parameterInputFile; -//--- TQString parameterOuputFile; -//--- TQString parameterParameterFile; -//--- TQProcess indentProcess; -//--- TQString processReturnString; -//--- -//--- // Generate the parameter string that will be saved to the indenters config file -//--- TQString parameterString = getParameterString(); -//--- -//--- if (!m_globalConfigFilename.isEmpty()) -//--- { -//--- saveConfigFile(m_tempDirectoryStr + "/" + m_globalConfigFilename, parameterString); -//--- } -//--- -//--- // Only add a dot to file extension if the string is not empty -//--- if (!inputFileExtension.isEmpty()) -//--- { -//--- inputFileExtension = "." + inputFileExtension; -//--- } -//--- -//--- // Delete any previously used input src file and create a new input src file. -//--- TQFile::remove(m_tempDirectoryStr + "/" + m_inputFileName + inputFileExtension); -//--- TQFile inputSrcFile(m_tempDirectoryStr + "/" + m_inputFileName + inputFileExtension); -//--- // Write the source code to the input file for the indenter -//--- if (inputSrcFile.open(TQFile::ReadWrite | TQFile::Text)) -//--- { -//--- inputSrcFile.write(sourceCode.toUtf8()); -//--- inputSrcFile.close(); -//--- tqDebug() << __LINE__ << " " << __FUNCTION__ << ": Wrote to be indented source code to file " << -//--- inputSrcFile.fileName(); -//--- } -//--- else -//--- { -//--- qCritical() << __LINE__ << " " << __FUNCTION__ << -//--- ": Couldn't write to be indented source code to file " << inputSrcFile.fileName(); -//--- } -//--- -//--- // Set the input file for the to be called indenter. -//--- if (m_inputFileParameter.trimmed() == "<" || m_inputFileParameter == "stdin") -//--- { -//--- parameterInputFile = ""; -//--- indentProcess.setStandardInputFile(inputSrcFile.fileName()); -//--- } -//--- else -//--- { -//--- parameterInputFile = " " + m_inputFileParameter + m_inputFileName + inputFileExtension; -//--- } -//--- -//--- // Set the output file for the to be called indenter. -//--- if (m_outputFileParameter != "none" && m_outputFileParameter != "stdout") -//--- { -//--- parameterOuputFile = " " + m_outputFileParameter + m_outputFileName + inputFileExtension; -//--- } -//--- -//--- // If the config file name is empty it is assumed that all parameters are sent via command line -//--- // call -//--- if (m_globalConfigFilename.isEmpty()) -//--- { -//--- parameterParameterFile = " " + parameterString; -//--- } -//--- // if needed add the parameter to the indenter call string where the config file can be found -//--- else if (m_useCfgFileParameter != "none") -//--- { -//--- parameterParameterFile = " " + m_useCfgFileParameter + "\"" + m_tempDirectoryStr + "/" + -//--- m_globalConfigFilename + "\""; -//--- } -//--- -//--- // Assemble indenter call string for parameters according to the set order. -//--- if (m_parameterOrder == "ipo") -//--- { -//--- indenterCompleteCallString = parameterInputFile + parameterParameterFile + parameterOuputFile; -//--- } -//--- else if (m_parameterOrder == "pio") -//--- { -//--- indenterCompleteCallString = parameterParameterFile + parameterInputFile + parameterOuputFile; -//--- } -//--- else if (m_parameterOrder == "poi") -//--- { -//--- indenterCompleteCallString = parameterParameterFile + parameterOuputFile + parameterInputFile; -//--- } -//--- else -//--- { -//--- indenterCompleteCallString = parameterInputFile + parameterOuputFile + parameterParameterFile; -//--- } -//--- -//--- // If no indenter executable call string could be created before, show an error message. -//--- if (m_indenterExecutableCallString.isEmpty()) -//--- { -//--- m_errorMessageDialog->showMessage(tr("No indenter executable"), tr( -//--- "There exists no indenter executable with the name \"%1\" in the directory \"%2\" nor in the global environment.").arg( -//--- m_indenterFileName).arg(m_indenterDirectoryStr)); -//--- return sourceCode; -//--- } -//--- -//--- // Generate the indenter call string either for win32 or other systems. -//--- indenterCompleteCallString = m_indenterExecutableCallString + indenterCompleteCallString; -//--- -//--- // errors and standard outputs from the process call are merged together -//--- //indentProcess.setReadChannelMode(TQProcess::MergedChannels); -//--- -//--- // Set the directory where the indenter will be executed for the process' environment as PWD. -//--- TQStringList env = indentProcess.environment(); -//--- env << "PWD=" + TQFileInfo(m_tempDirectoryStr).absFilePath(); -//--- indentProcess.setEnvironment(env); -//--- -//--- // Set the directory for the indenter execution -//--- indentProcess.setWorkingDirectory(TQFileInfo(m_tempDirectoryStr).absFilePath()); -//--- -//--- tqDebug() << __LINE__ << " " << __FUNCTION__ << ": Will call the indenter in the directory " << -//--- indentProcess.workingDirectory() << " using this commandline call: " << -//--- indenterCompleteCallString; -//--- -//--- indentProcess.start(indenterCompleteCallString); -//--- -//--- processReturnString = ""; -//--- bool calledProcessSuccessfully = indentProcess.waitForFinished(10000); -//--- // test if there was an error during starting the process of the indenter -//--- if (!calledProcessSuccessfully) -//--- { -//--- processReturnString = "<html><body>"; -//--- processReturnString += tr("<b>Returned error message:</b> ") + indentProcess.errorString() + -//--- "<br>"; -//--- -//--- switch (indentProcess.error()) -//--- { -//--- case TQProcess::FailedToStart: -//--- { -//--- processReturnString += tr("<b>Reason could be:</b> ") + -//--- "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.<br>"; -//--- break; -//--- } -//--- -//--- case TQProcess::Crashed: -//--- { -//--- processReturnString += "The process crashed some time after starting successfully.<br>"; -//--- break; -//--- } -//--- -//--- case TQProcess::Timedout: -//--- { -//--- processReturnString += -//--- "The called indenter did not response for over 10 seconds, so aborted its execution.<br>"; -//--- break; -//--- } -//--- -//--- case TQProcess::WriteError: -//--- { -//--- processReturnString += -//--- "An error occurred when attempting to write to the process. For example, the process may not be running, or it may have closed its input channel.<br>"; -//--- break; -//--- } -//--- -//--- case TQProcess::ReadError: -//--- { -//--- processReturnString += -//--- "An error occurred when attempting to read from the process. For example, the process may not be running.<br>"; -//--- break; -//--- } -//--- -//--- case TQProcess::UnknownError: -//--- { -//--- processReturnString += -//--- "An unknown error occurred. This is the default return value of error().<br>"; -//--- break; -//--- } -//--- -//--- default: -//--- { -//--- break; -//--- } -//--- } -//--- processReturnString += tr("<br><b>Callstring was:</b> ") + encodeToHTML( -//--- indenterCompleteCallString); -//--- processReturnString += tr("<br><br><b>Indenter output was:</b><pre>") + "<br>" + "(STDOUT):" + -//--- encodeToHTML(indentProcess.readAllStandardOutput()) + "<br>" + "(STDERR):" + -//--- encodeToHTML(indentProcess.readAllStandardError()) + "<br>" + "</pre></html></body>"; -//--- tqWarning() << __LINE__ << " " << __FUNCTION__ << processReturnString; -//--- TQApplication::restoreOverrideCursor(); -//--- m_errorMessageDialog->showMessage(tr("Error calling Indenter"), processReturnString); -//--- } -//--- -//--- // If the indenter returned an error code != 0 show its output. -//--- if (indentProcess.exitCode() != 0) -//--- { -//--- TQString exitCode; -//--- exitCode.setNum(indentProcess.exitCode()); -//--- processReturnString = tr("<b>Indenter returned with exit code:</b> ") + exitCode + "<br>" + tr( -//--- "<b>Indent console output was:</b> ") + "<br>" + "(STDOUT):" + encodeToHTML( -//--- indentProcess.readAllStandardOutput()) + "<br>" + "(STDERR):" + encodeToHTML( -//--- indentProcess.readAllStandardError()) + "<br>" + tr("<br><b>Callstring was:</b> ") + -//--- encodeToHTML(indenterCompleteCallString) + "</html></body>"; -//--- tqWarning() << __LINE__ << " " << __FUNCTION__ << processReturnString; -//--- TQApplication::restoreOverrideCursor(); -//--- m_errorMessageDialog->showMessage(tr("Indenter returned error"), processReturnString); -//--- } -//--- -//--- // Only get the formatted source code, if calling the indenter did succeed. -//--- if (calledProcessSuccessfully) -//--- { -//--- // If the indenter results are written to stdout, read them from there... -//--- if (indentProcess.exitCode() == 0 && m_outputFileParameter == "stdout") -//--- { -//--- formattedSourceCode = indentProcess.readAllStandardOutput(); -//--- tqDebug() << __LINE__ << " " << __FUNCTION__ << ": Read indenter output from StdOut."; -//--- } -//--- // ... else read the output file generated by the indenter call. -//--- else -//--- { -//--- TQFile outSrcFile(m_tempDirectoryStr + "/" + m_outputFileName + inputFileExtension); -//--- if (outSrcFile.open(TQFile::ReadOnly | TQFile::Text)) -//--- { -//--- TQTextStream outSrcStrm(&outSrcFile); -//--- outSrcStrm.setCodec(TQTextCodec::codecForName("UTF-8")); -//--- formattedSourceCode = outSrcStrm.readAll(); -//--- outSrcFile.close(); -//--- tqDebug() << __LINE__ << " " << __FUNCTION__ << ": Read indenter output from file " << -//--- outSrcFile.fileName(); -//--- } -//--- else -//--- { -//--- qCritical() << __LINE__ << " " << __FUNCTION__ << -//--- ": Couldn't read indenter output from file " << outSrcFile.fileName(); -//--- } -//--- } -//--- } -//--- else -//--- { -//--- return sourceCode; -//--- } -//--- -//--- // Delete the temporary input and output files. -//--- TQFile::remove(m_tempDirectoryStr + "/" + m_outputFileName + inputFileExtension); -//--- TQFile::remove(m_tempDirectoryStr + "/" + m_inputFileName + inputFileExtension); -//--- -//--- return formattedSourceCode; -//--- } +return ""; +} + +/* + \brief Format \a sourceCode by calling the binary executable of the indenter. + + The \a inputFileExt has to be given as parameter so the called indenter + can identify the programming language if needed. + */ +TQString IndentHandler::callExecutableIndenter(const TQString &sourceCode, const TQString &inputFileExt) +{ + if (m_indenterFileName.isEmpty() || inputFileExt.isEmpty()) + { + return TQString::null; + } + + TQString indenterCompleteCallString; + TQString parameterInputFile; + TQString parameterOuputFile; + TQString parameterParameterFile; + TQProcess indentProcess; + + TQObject::connect(&indentProcess, SIGNAL(processExited()), this, SLOT(indenterProcessFinished())); + + // Generate the parameter string that will be saved to the indenters config file + TQString parameterString = getParameterString(); + + if (!m_globalConfigFilename.isEmpty()) + { + saveConfigFile(m_tempDirectoryStr + "/" + m_globalConfigFilename, parameterString); + } + + // Only add a dot to file extension if the string is not empty + TQString inputFileExtension = "." + inputFileExt; + + // Delete any previously used input src file and create a new input src file. + TQFile::remove(m_tempDirectoryStr + "/" + m_inputFileName + inputFileExtension); + TQFile inputSrcFile(m_tempDirectoryStr + "/" + m_inputFileName + inputFileExtension); + // Write the source code to the input file for the indenter + if (inputSrcFile.open(IO_ReadWrite | IO_Translate)) + { + TQCString sourceCodeCString = sourceCode.utf8(); + inputSrcFile.writeBlock(sourceCodeCString.data(), sourceCodeCString.length()); + inputSrcFile.close(); + // tqDebug("Wrote source code to be indented to file %s", inputSrcFile.name().local8Bit().data()); + } + else + { + tqDebug("Couldn't write to be indented source code to file %s", inputSrcFile.name().local8Bit().data()); + } + + // Set the input file for the indenter to be called. + if (m_inputFileParameter.stripWhiteSpace() == "<" || m_inputFileParameter == "stdin") + { + parameterInputFile = " < " + inputSrcFile.name(); + } + else + { + parameterInputFile = " " + m_inputFileParameter + m_inputFileName + inputFileExtension; + } + + // Set the output file for the to be called indenter. + if (m_outputFileParameter != "none" && m_outputFileParameter != "stdout") + { + parameterOuputFile = " " + m_outputFileParameter + m_outputFileName + inputFileExtension; + } + + // If the config file name is empty it is assumed that all parameters are sent via command line + // call + if (m_globalConfigFilename.isEmpty()) + { + parameterParameterFile = " " + parameterString; + } + // if needed add the parameter to the indenter call string where the config file can be found + else if (m_useCfgFileParameter != "none") + { + parameterParameterFile = " " + m_useCfgFileParameter + m_tempDirectoryStr + "/" + + m_globalConfigFilename; + } + + // Assemble indenter call string for parameters according to the set order. + if (m_parameterOrder == "ipo") + { + indenterCompleteCallString = parameterInputFile + parameterParameterFile + parameterOuputFile; + } + else if (m_parameterOrder == "pio") + { + indenterCompleteCallString = parameterParameterFile + parameterInputFile + parameterOuputFile; + } + else if (m_parameterOrder == "poi") + { + indenterCompleteCallString = parameterParameterFile + parameterOuputFile + parameterInputFile; + } + else + { + indenterCompleteCallString = parameterInputFile + parameterOuputFile + parameterParameterFile; + } + + // If no indenter executable call string could be created before, show an error message. + if (m_indenterExecutableCallString.isEmpty()) + { + m_errorMessageDialog->showMessage(tr("No indenter executable"), tr( + "There exists no indenter executable with the name \"%1\" in the directory \"%2\" nor in the global environment.").arg( + m_indenterFileName).arg(m_indenterDirectoryStr)); + return sourceCode; + } + + // Generate the indenter call string either for win32 or other systems. + indenterCompleteCallString = m_indenterExecutableCallString + indenterCompleteCallString; + + // errors and standard outputs from the process call are merged together + //indentProcess.setReadChannelMode(TQProcess::MergedChannels); + + // Set the directory for the indenter execution + indentProcess.setWorkingDirectory(TQFileInfo(m_tempDirectoryStr).absFilePath()); + + // tqDebug(TQString("Will call the indenter in the directory ") + indentProcess.workingDirectory().path() + + // " using this commandline call: " + indenterCompleteCallString); + + indentProcess.clearArguments(); + TQStringList arguments = TQStringList::split(" ", indenterCompleteCallString); + for (const TQString &argument : arguments) + { + indentProcess.addArgument(argument); + } + + m_indenterProcessFinished = false; + indentProcess.start(); + int counter = 100; // roughtly 10s at 100ms interval + while (!m_indenterProcessFinished && counter > 0) + { + usleep(100 * 1000); + tqApp->processEvents(); + --counter; + } + + TQString formattedSourceCode = sourceCode; + bool calledProcessSuccessfully = indentProcess.normalExit(); + // test if there was an error during starting the process of the indenter + if (!calledProcessSuccessfully || indentProcess.exitStatus() != 0) + { + TQString processReturnString = "<html><body>"; + processReturnString += tr("<b>Returned error code:</b> ") + + TQString::number(indentProcess.exitStatus()) + "<br/>"; + processReturnString += tr("<br/><b>Call string:</b><br/>") + + encodeToHTML(indenterCompleteCallString) + "<br/>"; + processReturnString += tr("<br/><b>Process standard output:</b><br/>") + + encodeToHTML(TQString(indentProcess.readStdout())) + "<br/>"; + processReturnString += tr("<br/><b>Process error output:</b><br/>") + + encodeToHTML(TQString(indentProcess.readStderr())) + "<br/>"; + TQApplication::restoreOverrideCursor(); + m_errorMessageDialog->showMessage(tr("Error calling Indenter"), processReturnString); + } + else + { + if (m_outputFileParameter == "stdout") + { + formattedSourceCode = TQString(indentProcess.readStdout()); + } + // ... else read the output file generated by the indenter call. + else + { + TQFile outSrcFile(m_tempDirectoryStr + "/" + m_outputFileName + inputFileExtension); + if (outSrcFile.open(IO_ReadOnly | IO_Translate)) + { + TQTextStream outSrcStrm(&outSrcFile); + outSrcStrm.setCodec(TQTextCodec::codecForName("UTF-8")); + formattedSourceCode = outSrcStrm.read(); + outSrcFile.close(); + // tqDebug("Read indenter output from file " + outSrcFile.name()); + } + else + { + tqDebug("Couldn't read indenter output from file " + outSrcFile.name()); + } + } + } + + // Delete the temporary input and output files. + TQFile::remove(m_tempDirectoryStr + "/" + m_outputFileName + inputFileExtension); + TQFile::remove(m_tempDirectoryStr + "/" + m_inputFileName + inputFileExtension); + + return formattedSourceCode; +} /* \brief Generates and returns a string with all parameters needed to call the indenter. @@ -767,7 +691,7 @@ bool IndentHandler::loadConfigFile(const TQString &filePathName) // Search for name of each numeric parameter and set the value found behind it. for(const ParamNumeric &pNumeric : m_paramNumerics) { - int index = cfgFileData.find(pNumeric.paramCallName, 0, false); + int index = cfgFileData.find(pNumeric.paramCallName, 0); // parameter was found in config file if (index != -1) { @@ -1784,22 +1708,22 @@ void IndentHandler::handleChangedIndenterSettings() emit(indenterSettingsChanged()); } -//--- /*! -//--- \brief Converts characters < > and & in the \a text to HTML codes < > and &. -//--- */ -//--- TQString IndentHandler::encodeToHTML(const TQString &text) -//--- { -//--- TQString htmlText = text; -//--- htmlText.replace("&", "&"); -//--- htmlText.replace("<", "<"); -//--- htmlText.replace(">", ">"); -//--- htmlText.replace('"', """); -//--- htmlText.replace("'", "'"); -//--- htmlText.replace("^", "ˆ"); -//--- htmlText.replace("~", "˜"); -//--- htmlText.replace("€", "€"); -//--- htmlText.replace("©", "©"); -//--- return htmlText; -//--- } +/*! + \brief Converts characters < > and & in the \a text to HTML codes < > and &. + */ +TQString IndentHandler::encodeToHTML(const TQString &text) +{ + TQString htmlText = text; + htmlText.replace("&", "&"); + htmlText.replace("<", "<"); + htmlText.replace(">", ">"); + htmlText.replace('"', """); + htmlText.replace("'", "'"); + htmlText.replace("^", "ˆ"); + htmlText.replace("~", "˜"); + htmlText.replace("€", "€"); + htmlText.replace("©", "©"); + return htmlText; +} #include "IndentHandler.moc" |