summaryrefslogtreecommitdiffstats
path: root/src/common/cli
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/cli')
-rw-r--r--src/common/cli/Makefile.am7
-rw-r--r--src/common/cli/cli.pro6
-rw-r--r--src/common/cli/cli_global.cpp37
-rw-r--r--src/common/cli/cli_global.h33
-rw-r--r--src/common/cli/cli_log.cpp74
-rw-r--r--src/common/cli/cli_log.h33
-rw-r--r--src/common/cli/cli_main.cpp208
-rw-r--r--src/common/cli/cli_main.h82
-rw-r--r--src/common/cli/cli_pfile.cpp47
-rw-r--r--src/common/cli/cli_purl.cpp9
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"