diff options
Diffstat (limited to 'src/common/cli')
-rw-r--r-- | src/common/cli/Makefile.am | 7 | ||||
-rw-r--r-- | src/common/cli/cli.pro | 6 | ||||
-rw-r--r-- | src/common/cli/cli_global.cpp | 37 | ||||
-rw-r--r-- | src/common/cli/cli_global.h | 33 | ||||
-rw-r--r-- | src/common/cli/cli_log.cpp | 74 | ||||
-rw-r--r-- | src/common/cli/cli_log.h | 33 | ||||
-rw-r--r-- | src/common/cli/cli_main.cpp | 208 | ||||
-rw-r--r-- | src/common/cli/cli_main.h | 82 | ||||
-rw-r--r-- | src/common/cli/cli_pfile.cpp | 47 | ||||
-rw-r--r-- | src/common/cli/cli_purl.cpp | 9 |
10 files changed, 536 insertions, 0 deletions
diff --git a/src/common/cli/Makefile.am b/src/common/cli/Makefile.am new file mode 100644 index 0000000..2225bc0 --- /dev/null +++ b/src/common/cli/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = -I$(top_srcdir)/src $(all_includes) +METASOURCES = AUTO + +noinst_LTLIBRARIES = libcli.la +libcli_la_LDFLAGS = $(all_libraries) +libcli_la_SOURCES = cli_purl.cpp cli_pfile.cpp cli_global.cpp cli_log.cpp \ + cli_main.cpp diff --git a/src/common/cli/cli.pro b/src/common/cli/cli.pro new file mode 100644 index 0000000..20bb3b7 --- /dev/null +++ b/src/common/cli/cli.pro @@ -0,0 +1,6 @@ +STOPDIR = ../../.. +include($${STOPDIR}/lib.pro) + +TARGET = cli +HEADERS += cli_global.h cli_log.h cli_main.h +SOURCES += cli_global.cpp cli_log.cpp cli_purl.cpp cli_pfile.cpp cli_main.cpp diff --git a/src/common/cli/cli_global.cpp b/src/common/cli/cli_global.cpp new file mode 100644 index 0000000..4d58bdd --- /dev/null +++ b/src/common/cli/cli_global.cpp @@ -0,0 +1,37 @@ +/*************************************************************************** + * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "cli_global.h" + +#include <qdir.h> + +#include "common/global/purl.h" +#include "cli_log.h" + +bool CLI::_force = false; +bool CLI::_isInteractive = false; +CLI::View *CLI::_view = 0; +CLI::MainBase *CLI::_main = 0; + +CLI::ExitCode CLI::errorExit(const QString &message, ExitCode code) +{ + Q_ASSERT( code!=OK ); + _view->log(Log::LineType::SoftError, message); + return code; +} + +CLI::ExitCode CLI::okExit(const QString &message) +{ + _view->log(Log::LineType::Information, message); + return OK; +} + +PURL::Directory CLI::runDirectory() +{ + return PURL::Directory(QDir::currentDirPath()); +} diff --git a/src/common/cli/cli_global.h b/src/common/cli/cli_global.h new file mode 100644 index 0000000..b90f36e --- /dev/null +++ b/src/common/cli/cli_global.h @@ -0,0 +1,33 @@ +/*************************************************************************** + * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef CLI_GLOBAL_H +#define CLI_GLOBAL_H + +#include <qstring.h> +namespace PURL { class Directory; } + +namespace CLI +{ + +class View; +class MainBase; +enum ExitCode { EXITING = 1, OK = 0, ARG_ERROR = -1, NOT_SUPPORTED_ERROR = -2, + FILE_ERROR = -3, EXEC_ERROR = -4 }; +extern ExitCode errorExit(const QString &message, ExitCode code); +extern ExitCode okExit(const QString &message); +extern PURL::Directory runDirectory(); + +extern bool _force; +extern bool _isInteractive; +extern View *_view; +extern MainBase *_main; + +} // namespace + +#endif diff --git a/src/common/cli/cli_log.cpp b/src/common/cli/cli_log.cpp new file mode 100644 index 0000000..603d5f8 --- /dev/null +++ b/src/common/cli/cli_log.cpp @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "cli_log.h" + +#include "common/global/global.h" +#include "cli_global.h" + +void CLI::View::doLog(Log::LineType type, const QString &text, Log::Action) +{ + QString s = text + "\n"; + switch (type.type()) { + case Log::LineType::Error: + case Log::LineType::SoftError: s = "Error: " + s; break; + case Log::LineType::Warning: s = "Warning: " + s; break; + default: break; + } +#if QT_VERSION<0x040000 + if ( type==Log::LineType::Error || type==Log::LineType::SoftError ) fprintf(stderr, "%s", s.latin1()); + else fprintf(stdout, "%s", s.latin1()); +#else + QByteArray ba = s.toLatin1(); + if ( type==Log::LineType::Error || type==Log::LineType::SoftError ) fprintf(stderr, "%s", ba.constData()); + else fprintf(stdout, "%s", ba.constData()); +#endif +} + +void CLI::View::doLog(Log::DebugLevel, const QString &text, Log::Action) +{ + QString s = text + "\n"; +#if QT_VERSION<0x040000 + fprintf(stdout, "%s", s.latin1()); +#else + QByteArray ba = s.toLatin1(); + fprintf(stdout, "%s", ba.constData()); +#endif +} + +void CLI::View::appendToLastLine(const QString &text) +{ +#if QT_VERSION<0x040000 + fprintf(stdout, "%s", text.latin1()); +#else + QByteArray ba = text.toLatin1(); + fprintf(stdout, "%s", ba.constData()); +#endif +} + +void CLI::View::sorry(const QString &message, const QString &details) +{ + if ( details.isEmpty() ) log(Log::LineType::Error, message, Log::Immediate); + else log(Log::LineType::Error, message + " (" + details + ")", Log::Immediate); +} + +bool CLI::View::askContinue(const QString &message) +{ + log(Log::LineType::Warning, message + " " + (_force ? i18n("*yes*") : i18n("*no*")), Log::Immediate); + if (_force) return true; + if ( !_isInteractive ) return false; // always fail + // #### TODO + return false; +} + +void CLI::View::logUserAbort() +{ + if ( !_isInteractive ) return; + return; + //Log::View::logUserAbort(); +} diff --git a/src/common/cli/cli_log.h b/src/common/cli/cli_log.h new file mode 100644 index 0000000..2fa83dc --- /dev/null +++ b/src/common/cli/cli_log.h @@ -0,0 +1,33 @@ +/*************************************************************************** + * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef CLI_LOG_H +#define CLI_LOG_H + +#include "common/global/log.h" + +namespace CLI +{ + +class View : public Log::View +{ +public: + virtual void appendToLastLine(const QString &text); + virtual void clear() {} + virtual void sorry(const QString &message, const QString &details); + virtual bool askContinue(const QString &message); + virtual void logUserAbort(); + +private: + virtual void doLog(Log::LineType type, const QString &text, Log::Action action); + virtual void doLog(Log::DebugLevel level, const QString &text, Log::Action action); +}; + +} // namespace + +#endif diff --git a/src/common/cli/cli_main.cpp b/src/common/cli/cli_main.cpp new file mode 100644 index 0000000..7d75dbb --- /dev/null +++ b/src/common/cli/cli_main.cpp @@ -0,0 +1,208 @@ +/*************************************************************************** + * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "cli_main.h" + +#include "cli_log.h" +#include "common/global/about.h" + +//----------------------------------------------------------------------------- +const CLI::CommandData *CLI::findCommandData(const QString &command) +{ + for (uint i=0; NORMAL_COMMAND_DATA[i].name; i++) + if ( NORMAL_COMMAND_DATA[i].name==command ) return &NORMAL_COMMAND_DATA[i]; + if ( !_isInteractive) return 0; + for (uint i=0; INTERACTIVE_COMMAND_DATA[i].name; i++) + if ( INTERACTIVE_COMMAND_DATA[i].name==command ) return &INTERACTIVE_COMMAND_DATA[i]; + return 0; +} + +CLI::ExitCode CLI::findCommand(const QString &s) +{ + if ( s.isEmpty() ) return errorExit(i18n("No command specified"), ARG_ERROR); + const CommandData *data = findCommandData(s); + if ( data==0 ) return errorExit(i18n("Unknown command: %1").arg(s), ARG_ERROR); + return OK; +} + +//----------------------------------------------------------------------------- +bool CLI::isPropertyList(const QString &s) +{ + for (uint i=0; PROPERTY_DATA[i].name; i++) + if ( s==PROPERTY_DATA[i].list ) return true; + return false; +} + +bool CLI::isProperty(const QString &s) +{ + for (uint i=0; PROPERTY_DATA[i].name; i++) + if ( s==PROPERTY_DATA[i].name ) return true; + return false; +} + +//----------------------------------------------------------------------------- +const KCmdLineOptions STANDARD_OPTIONS[] = { + { "c", 0, 0 }, + { "command <name>", I18N_NOOP("Perform the requested command."), 0 }, + { "command-list", I18N_NOOP("Return the list of recognized commands."), 0 }, + { "debug", I18N_NOOP("Display debug messages."), 0 }, + { "extra-debug", I18N_NOOP("Display extra debug messages."), 0 }, + { "max-debug", I18N_NOOP("Display all debug messages."), 0 }, + { "lowlevel-debug", I18N_NOOP("Display low level debug messages."), 0 }, + { "quiet", I18N_NOOP("Do not display messages."), 0 }, + KCmdLineLastOption +}; + +const KCmdLineOptions FORCE_OPTIONS[] = { + { "f", 0, 0 }, + { "force", I18N_NOOP("Overwrite files and answer \"yes\" to questions."), 0 }, + KCmdLineLastOption +}; + +const KCmdLineOptions INTERACTIVE_OPTIONS[] = { + { "i", 0, 0 }, + { "cli", I18N_NOOP("Interactive mode"), 0 }, + KCmdLineLastOption +}; + +CLI::OptionList::OptionList(Properties properties) +{ + init(properties); +} + +CLI::OptionList::OptionList(Properties properties, const KCmdLineOptions *options) +{ + init(properties); + for (uint i=0; options[i].name; i++) append(options[i]); +} + +void CLI::OptionList::init(Properties properties) +{ + for (uint i=0; STANDARD_OPTIONS[i].name; i++) append(STANDARD_OPTIONS[i]); + if ( properties & HasForce ) for (uint i=0; FORCE_OPTIONS[i].name; i++) append(FORCE_OPTIONS[i]); + if ( properties & HasInteractiveMode ) for (uint i=0; INTERACTIVE_OPTIONS[i].name; i++) append(INTERACTIVE_OPTIONS[i]); +} + +CLI::ExitCode CLI::commandList() +{ + Log::KeyList keys(i18n("Supported commands:")); + for (uint i=0; NORMAL_COMMAND_DATA[i].name; i++) + keys.append(NORMAL_COMMAND_DATA[i].name, i18n(NORMAL_COMMAND_DATA[i].help)); + if (_isInteractive) { + for (uint i=0; INTERACTIVE_COMMAND_DATA[i].name; i++) + keys.append(INTERACTIVE_COMMAND_DATA[i].name, i18n(INTERACTIVE_COMMAND_DATA[i].help)); + } + keys.display(*_view); + return OK; +} + +CLI::ExitCode CLI::propertyList() +{ + Log::KeyList keys; + for (uint i=0; PROPERTY_DATA[i].name; i++) + keys.append(PROPERTY_DATA[i].name, i18n(PROPERTY_DATA[i].help)); + keys.display(*_view); + return OK; +} + +//----------------------------------------------------------------------------- +CLI::MainBase::MainBase(Properties properties) + : QObject(0, "main"), _properties(properties) +{ + Q_ASSERT( _main==0 ); + _main = this; + _view = new View; + setView(_view); +} + +void CLI::MainBase::init() +{ + _args = KCmdLineArgs::parsedArgs(); + if ( _properties & HasInteractiveMode ) _isInteractive = _args->isSet("cli"); + if ( _properties & HasForce ) _force = _args->isSet("force"); + FOR_EACH(Log::DebugLevel, level) if ( _args->isSet(level.key()) ) _view->setDebugLevel(level); +} + +CLI::OptionList CLI::MainBase::optionList(const char *fileDescription) const +{ + OptionList list(_properties, OPTIONS); + KCmdLineOptions opt; + for (uint i=0; PROPERTY_DATA[i].name; i++) { + opt.description = 0; + opt.def = 0; + if ( PROPERTY_DATA[i].help==0 ) { + Q_ASSERT( QString(PROPERTY_DATA[i].name)!=PROPERTY_DATA[i].optName ); + opt.name = PROPERTY_DATA[i].name; // alias + list.append(opt); + } else { + if ( PROPERTY_DATA[i].optName==0 ) continue; // interactive only + if ( PROPERTY_DATA[i].alias ) { + opt.name = PROPERTY_DATA[i].alias; + list.append(opt); + } + opt.name = PROPERTY_DATA[i].optName; + opt.description = PROPERTY_DATA[i].help; + list.append(opt); + if ( PROPERTY_DATA[i].list ) { + opt.name = PROPERTY_DATA[i].list; + opt.description = PROPERTY_DATA[i].listHelp; + list.append(opt); + } + } + } + if (fileDescription) { + opt.name = "+[file]"; + opt.description = fileDescription; + opt.def = 0; + } + list.append(opt); + return list; +} + +CLI::ExitCode CLI::MainBase::list(const QString &command) +{ + if ( command=="command-list" ) return commandList(); + if ( command=="property-list" ) return propertyList(); + return ARG_ERROR; +} + +CLI::ExitCode CLI::MainBase::doRun() +{ + init(); + + // process set options + for (uint i=0; PROPERTY_DATA[i].name; i++) { + if ( PROPERTY_DATA[i].optName==0 ) continue; // alias or interactive only + if ( !_args->isSet(PROPERTY_DATA[i].name) ) continue; + QString option = _args->getOption(PROPERTY_DATA[i].name); + ExitCode code = executeSetCommand(PROPERTY_DATA[i].name, option); + if ( code!=OK ) return code; + log(Log::LineType::Information, QString("%1: %2").arg(PROPERTY_DATA[i].name).arg(executeGetCommand(PROPERTY_DATA[i].name))); + } + + // process default lists + if ( _args->isSet("command-list") ) return list("command-list"); + for (uint i=0; PROPERTY_DATA[i].name; i++) { + if ( PROPERTY_DATA[i].list==0 ) continue; + if ( _args->isSet(PROPERTY_DATA[i].list) ) return list(PROPERTY_DATA[i].list); + } + + bool interactive; + ExitCode code = prepareRun(interactive); + if ( code!=OK || interactive ) return code; + + // find command + QString command = _args->getOption("command"); + code = findCommand(command); + if ( code!=OK ) return code; + + // execute command + code = prepareCommand(command); + if ( code!=OK ) return code; + return executeCommand(command); +} diff --git a/src/common/cli/cli_main.h b/src/common/cli/cli_main.h new file mode 100644 index 0000000..9b54c70 --- /dev/null +++ b/src/common/cli/cli_main.h @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#ifndef CLI_MAIN_H +#define CLI_MAIN_H + +#include "common/global/about.h" +#include "common/global/log.h" +#include "cli_global.h" + +namespace CLI +{ +//----------------------------------------------------------------------------- +enum Property { NoProperty = 0, HasForce = 1, HasInteractiveMode = 2 }; +Q_DECLARE_FLAGS(Properties, Property) +Q_DECLARE_OPERATORS_FOR_FLAGS(Properties) + +extern const KCmdLineOptions OPTIONS[]; +//----------------------------------------------------------------------------- +struct CommandData { + const char *name; + int properties; + const char *help; +}; +extern const CommandData NORMAL_COMMAND_DATA[]; +extern const CommandData INTERACTIVE_COMMAND_DATA[]; +extern const CommandData *findCommandData(const QString &command); +extern ExitCode findCommand(const QString &s); +extern ExitCode commandList(); + +//----------------------------------------------------------------------------- +struct PropertyData +{ + const char *name, *optName, *alias, *help, *list, *listHelp; +}; +extern const PropertyData PROPERTY_DATA[]; +extern bool isPropertyList(const QString &s); +extern bool isProperty(const QString &s); +extern ExitCode propertyList(); + +//----------------------------------------------------------------------------- +class OptionList : public Piklab::OptionList +{ +public: + OptionList(Properties properties); + OptionList(Properties properties, const KCmdLineOptions *options); + +private: + void init(Properties properties); +}; + +//----------------------------------------------------------------------------- +class MainBase : public QObject, public Log::Base +{ +Q_OBJECT +public: + MainBase(Properties properties); + virtual OptionList optionList(const char *fileDescription) const; + virtual ExitCode doRun(); + virtual ExitCode list(const QString &listName); + virtual ExitCode prepareCommand(const QString &command) = 0; + virtual ExitCode executeCommand(const QString &command) = 0; + virtual ExitCode executeSetCommand(const QString &property, const QString &value) = 0; + virtual QString executeGetCommand(const QString &property) = 0; + +protected: + Properties _properties; + KCmdLineArgs *_args; + +private: + virtual ExitCode prepareRun(bool &interactive) = 0; + virtual void init(); +}; + +} // namespace + +#endif diff --git a/src/common/cli/cli_pfile.cpp b/src/common/cli/cli_pfile.cpp new file mode 100644 index 0000000..96add3a --- /dev/null +++ b/src/common/cli/cli_pfile.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "common/global/pfile.h" + +#include <qfile.h> + +//----------------------------------------------------------------------------- +bool PURL::File::openForWrite() +{ + close(); + _file->setName(url().filepath()); + if ( !_file->open(IO_WriteOnly) ) { + _error = i18n("Could not open file for writing."); + _log.sorry(_error, i18n("File: %1").arg(_file->name())); + return false; + } + return true; +} + +bool PURL::File::close() +{ + _file->close(); + return ( uint(_file->status())==IO_Ok ); +} + +bool PURL::File::openForRead() +{ + close(); + _file->setName(_url.filepath()); + if ( !_file->open(IO_ReadOnly) ) { + _error = i18n("Could not open file for reading."); + _log.sorry(_error, i18n("File: %1").arg(_file->name())); + return false; + } + return true; +} + +bool PURL::File::remove() +{ + return _file->remove(); +} diff --git a/src/common/cli/cli_purl.cpp b/src/common/cli/cli_purl.cpp new file mode 100644 index 0000000..e52c977 --- /dev/null +++ b/src/common/cli/cli_purl.cpp @@ -0,0 +1,9 @@ +/*************************************************************************** + * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ +#include "common/global/purl.h" |