diff --git a/util/CMakeLists.txt b/util/CMakeLists.txt --- a/util/CMakeLists.txt +++ b/util/CMakeLists.txt @@ -54,8 +54,12 @@ ) install( FILES kdevplatform_shell_environment.sh DESTINATION bin PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) -install( FILES kdev_format_source DESTINATION bin PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) +########### kdev_format_source executable ############### + +add_executable(kdev_format_source kdev_format_source.cpp) +target_link_libraries(kdev_format_source Qt5::Core) +install(TARGETS kdev_format_source DESTINATION bin) ########### install files ############### diff --git a/util/kdev_format_source b/util/kdev_format_source deleted file mode 100644 --- a/util/kdev_format_source +++ /dev/null @@ -1,132 +0,0 @@ -#!/bin/bash - -# Author: David Nolden -# This script is made available under the GPLv2 licence. -# -# This script formats a given source-file automatically by -# using formatting scripts as defined in specific meta-information -# "format_sources" files contained in the file system hierarchy. -# -# The rules within a "format_sources" file apply to all subdirectories, -# and follow this syntax: -# Each line defines a list of wildcards followed by a colon and the formatting-command. -# Example: "*.cpp *.h : my_custom_formatting_script.sh $TMPFILE" -# -# The file must be terminated by a trailing newline. -# -# If no colon and no wildcards are given, the command is -# used for everything, equivalently to the "*" wildcard. -# -# The contents is processed in linear order, and the first matching command is used. - -ORIGFILE=$1 -TMPFILE=$2 - -if ! [ "$ORIGFILE" ]; then - echo "Usage: $(basename $0) [FILE] [TEMPFILE]" - echo "" - echo "Where FILE represents the original location of the formatted contents," - echo "and TEMPFILE is used as the actual, potentially different," - echo "contents of the file." - exit -fi - -ORIGFILE=$(readlink -f $ORIGFILE) - -if ! [ $TMPFILE ]; then - echo "No tempfile given, formatting the original file" - TMPFILE=$ORIGFILE -else - TMPFILE=$(readlink -f $TMPFILE) -fi - -# Helper: Returns the relative path from a given source directory to a target path -function relativePath { - source=$1 - target=$2 - - common_part=$source - back= - while [ "${target#$common_part}" = "${target}" ]; do - common_part=$(dirname $common_part) - back="../${back}" - done - - echo ${back}${target#$common_part/} -} - -# Go to the directory of the original file, and start searching for "format_sources" files upwards -cd $(dirname $ORIGFILE) - -while ! [ "$(pwd)" == "/" ]; do - - if [ -e "format_sources" ]; then - echo "found $(readlink -f format_sources)" - - # Read line by line - while read line - do -# echo "Line: $line" - # Split by the ":" which is the delimiter between wildcards - IFS="\:" - array= - pos=0 - - # remove leading whitespace - line="${line#"${line%%[![:space:]]*}"}" - - if [[ "$line" == \#* ]] || ! [ "$line" ]; then - # Ignore lines starting with # - # Those can be used for comments. - # Also ignore empty lines - continue - fi - - for item in $line; - do - array[$pos]=$item - pos=$(($pos+1)) - done - - if [ $pos == "2" ]; then - # We found the correct syntax with "wildcards : command" - WILDCARDS=${array[0]} - COMMAND=${array[1]} - - MATCHED=0 - -# echo "wildcards: $WILDCARDS" - - RELATIVE_ORIGFILE=$(relativePath $(pwd) $ORIGFILE) -# echo "relative path: $RELATIVE_ORIGFILE" - - IFS=" " - set -f # This disables the wildcard expansion, we don't want it - for WILDCARD in $WILDCARDS; do - set +f - # This if-command does wildcard matching -# echo "matching $RELATIVE_ORIGFILE and $WILDCARD" - if [[ "$RELATIVE_ORIGFILE" == $WILDCARD ]]; then - echo "matched $RELATIVE_ORIGFILE with wildcard $WILDCARD, using command \"$COMMAND\"" - eval $COMMAND - exit - fi - set -f - done - set +f - fi - - if [ $pos == "1" ]; then - # We found the simple syntax without wildcards, and only with the command - COMMAND=${array[0]} - echo "matched without wildcard, using command $COMMAND" - eval $COMMAND - exit - fi - - done < format_sources - fi - - - cd .. -done diff --git a/util/kdev_format_source.cpp b/util/kdev_format_source.cpp new file mode 100644 --- /dev/null +++ b/util/kdev_format_source.cpp @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include + +inline QTextStream& qStdOut() +{ + static QTextStream r{stdout}; + return r; +} + +int main(int argc, char** argv) +{ + static const QString formatFileName = QStringLiteral("format_sources"); + + if (argc == 1) { + qStdOut() << "Usage:" << argv[0] << "ORIGFILE [TMPFILE]\n\n"; + qStdOut() << "Where ORIGFILE represents the original location of the formatted contents,\n"; + qStdOut() << "and TMPFILE is used as the actual, potentially different,\n"; + qStdOut() << "contents of the file.\n"; + return EXIT_FAILURE; + } + + QFileInfo origFileInfo(argv[1]); + if (!origFileInfo.exists()) { + qStdOut() << "orig file \"" << origFileInfo.absoluteFilePath() << "\" does not exits\n"; + return EXIT_FAILURE; + } + + QString origFilePath = origFileInfo.canonicalFilePath(); + QString tempFilePath; + + if (argc > 2) + tempFilePath = QFileInfo(argv[2]).canonicalFilePath(); + else { + tempFilePath = origFilePath; + qStdOut() << "no temp file given, formatting the original file\n"; + } + + QDir srcDir(origFileInfo.canonicalPath()); + while (!srcDir.isRoot()) { + if (!srcDir.exists(formatFileName)) { + srcDir.cdUp(); + continue; + } + + QDir::setCurrent(srcDir.canonicalPath()); + + qStdOut() << "found \"" << formatFileName << "\"\n"; + + QFile formatFile(formatFileName); + if (!formatFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + qStdOut() << "unable to open \"" << formatFileName << "\"\n"; + return EXIT_FAILURE; + } + + int line_number = 0; + bool matched = false; + QString line; + QString command; + QString wildcard; + + while (!formatFile.atEnd()) { + ++line_number; + + line = formatFile.readLine().trimmed(); + if (line.isEmpty() || line.startsWith('#')) + continue; + + QStringList elems = line.split(':'); + + // We found the simple syntax without wildcards, and only with the command + if (elems.size() == 1) { + wildcard.clear(); + command = elems[0].trimmed(); + matched = true; + break; + } + // We found the correct syntax with "wildcards : command" + else if (elems.size() == 2) { + QStringList wildcards = elems[0].split(' ', QString::SkipEmptyParts); + if (wildcards.isEmpty()) { + qStdOut() << formatFileName << ":" << line_number + << ": error: empty wildcard, skip the line\n"; + } + + foreach(wildcard, wildcards) { + wildcard = wildcard.trimmed(); + if (QDir::match(srcDir.canonicalPath() + "/" + wildcard, origFilePath)) { + command = elems[1].trimmed(); + matched = true; + break; + } + } + + if (matched) + break; + } + // We found the incorrect correct syntax + else { + qStdOut() << formatFileName << ":" << line_number + << ": error: too many delimiters (':'), skip the line\n"; + continue; + } + } + + if (matched && !command.isEmpty()) { + if (wildcard.isEmpty()) + qStdOut() << "matched without wildcard"; + else + qStdOut() << "matched \"" << origFilePath << "\" with wildcard \"" << wildcard << "\""; + + qStdOut() << ", using command \"" << command << "\"\n"; + + command.replace(QStringLiteral("$ORIGFILE"), origFilePath); + command.replace(QStringLiteral("$TMPFILE"), tempFilePath); + + // Do force flush for stream before running command. + // Otherwise command's output can be shown before text, + // printed in previous code. + qStdOut().flush(); + + int execResult = QProcess::execute(command); + + if (execResult == -2) { + qStdOut() << "command \"" + command + "\" failed to start\n"; + return EXIT_FAILURE; + } + else if (execResult == -1) { + qStdOut() << "command \"" + command + "\" crashed\n"; + return EXIT_FAILURE; + } + } + + break; + } + + return EXIT_SUCCESS; +}