Commit fe417d5c authored by Lisa's avatar Lisa

New logical organization for parsers. Structures and operations unified when...

New logical organization for parsers. Structures and operations unified when possible/simple enough.
parent 228f2891
......@@ -27,7 +27,9 @@ queryoperation.cpp
performoperation.cpp
apm.cpp
akabeioptions.cpp
cmdlineparsing.cpp
parser.cpp
akabeiparser.cpp
pakabeiparser.cpp
main.cpp)
add_subdirectory(tools)
......@@ -35,5 +37,8 @@ add_subdirectory(tools)
#qt4_automoc(${guzuta_SRCS})
kde4_add_executable(akabei ${apm_SRCS})
target_link_libraries(akabei ${KDE4_KDECORE_LIBRARY} ${KDE4_KIO_LIBRARY} ${AKABEICORE_LIBRARIES} ${AKABEICLIENT_LIBRARIES})
install(TARGETS akabei ${INSTALL_TARGETS_DEFAULT_ARGS})
kde4_add_executable(pakabei ${apm_SRCS})
target_link_libraries(pakabei ${KDE4_KDECORE_LIBRARY} ${KDE4_KIO_LIBRARY} ${AKABEICORE_LIBRARIES} ${AKABEICLIENT_LIBRARIES})
install(TARGETS pakabei ${INSTALL_TARGETS_DEFAULT_ARGS})
/*
* This file is part of the Chakra project
* Definitions for the operations and options objects
Copyright (C) 2011 Lisa Vitolo <shainer@chakra-project.org>
......@@ -98,9 +99,11 @@ AkabeiOperation::AkabeiOperation()
: m_name(APM::None)
{}
AkabeiOperation::AkabeiOperation(APM::OperationName n, QString cmd, KLocalizedString desc, bool a)
: m_name(n)
, m_command(cmd)
AkabeiOperation::AkabeiOperation(APM::OperationType t, APM::OperationName n, QString cmd, QString cmdLong, KLocalizedString desc, bool a)
: m_type(t)
, m_name(n)
, m_commandShort(cmd)
, m_commandLong(cmdLong)
, m_description(desc)
, m_freeArgs(a)
{}
......@@ -117,14 +120,24 @@ bool AkabeiOperation::isOptionSupported(APM::OptionName opt)
return m_options.contains(opt);
}
APM::OperationType AkabeiOperation::type() const
{
return m_type;
}
APM::OperationName AkabeiOperation::name() const
{
return m_name;
}
QString AkabeiOperation::command() const
QString AkabeiOperation::commandShort() const
{
return m_command;
return m_commandShort;
}
QString AkabeiOperation::commandLong() const
{
return m_commandLong;
}
KLocalizedString AkabeiOperation::description() const
......@@ -144,9 +157,22 @@ QList<APM::OptionName> AkabeiOperation::options() const
void AkabeiOperation::operator=(const AkabeiOperation& other)
{
this->m_type = other.m_type;
this->m_name = other.m_name;
this->m_command = other.m_command;
this->m_commandShort = other.m_commandShort;
this->m_commandLong = other.m_commandLong;
this->m_description = other.m_description;
this->m_freeArgs = other.m_freeArgs;
this->m_options = other.m_options;
}
int AkabeiOperation::length() const
{
int size = m_commandLong.size();
if (!m_commandShort.isEmpty()) {
size += DASH + COMMA + m_commandShort.size();
}
return size;
}
/*
* This file is part of the Chakra project
* Definition of the operations and options supported, and of the objects used
* to represent them.
* Header for the operations and options objects
Copyright (C) 2011 Lisa Vitolo <shainer@chakra-project.org>
......@@ -111,25 +110,38 @@ uint qHash(AkabeiOption const&);
class AkabeiOperation
{
private:
APM::OperationType m_type;
APM::OperationName m_name;
QString m_command;
QString m_commandShort;
QString m_commandLong;
KLocalizedString m_description;
bool m_freeArgs;
QList<APM::OptionName> m_options;
public:
AkabeiOperation();
AkabeiOperation(APM::OperationName, QString, KLocalizedString, bool a = false);
AkabeiOperation(APM::OperationType, APM::OperationName, QString, QString, KLocalizedString, bool a = false);
/**
* @returns the operation type
*/
APM::OperationType type() const;
/**
* @returns the symbolic name associated (unique)
*/
APM::OperationName name() const;
/**
* @returns the (only) command this operation is described by
* @returns the short command this operation is described by
* (unused in the new parser)
*/
QString commandShort() const;
/**
* @returns the long version of the command
*/
QString command() const;
QString commandLong() const;
/**
* @returns a localized description
......@@ -157,6 +169,12 @@ public:
*/
bool isOptionSupported(APM::OptionName opt);
/**
* @returns the number of characters in the printable version of this operation
* (again used only in the help message)
*/
int length() const;
void operator=(const AkabeiOperation &);
};
......
/*
* This file is part of the Chakra project
* Parses an akabei-style command line
Copyright (C) 2011 Lisa Vitolo <shainer@chakra-project.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 "akabeiparser.h"
AkabeiParser::AkabeiParser(int argc, char **argv, const KAboutData& about)
: CommandLineParser(argc, argv, about)
{
/* Special operations */
AkabeiOperation help(APM::NoType, APM::Help, "", "help", ki18n("Show an help message"));
AkabeiOperation version(APM::NoType, APM::Version, "", "version", ki18n("Show version information"));
AkabeiOperation license(APM::NoType, APM::License, "", "license", ki18n("Show license information"));
AkabeiOperation authors(APM::NoType, APM::Authors, "", "authors", ki18n("Show information about the authors"));
m_acceptedOperations.insert("help", help);
m_acceptedOperations.insert("version", version);
m_acceptedOperations.insert("license", license);
m_acceptedOperations.insert("authors", authors);
}
void AkabeiParser::addOperation(APM::OperationType type, APM::OperationName name, QString command, QString commandLong, const char *desc, bool args)
{
AkabeiOperation operation(type, name, command, commandLong, ki18n(desc), args);
m_acceptedOperations.insert(commandLong, operation);
m_lastOperation = commandLong; /* saves the operation so we know where to add the option (see addConnectionWithOption) */
}
void AkabeiParser::addOption(APM::OptionName name, QString cmdShort, QString cmdLong, const char *desc, QString argname)
{
AkabeiOption option(name, cmdShort, cmdLong, ki18n(desc), argname);
m_acceptedOptions.insert(cmdShort, option);
m_acceptedOptions.insert(cmdLong, option);
}
void AkabeiParser::addConnectionWithOption(APM::OptionName name)
{
if (!m_lastOperation.isEmpty()) {
AkabeiOperation &op = m_acceptedOperations[m_lastOperation];
op.addConnectionWithOption(name);
}
}
void AkabeiParser::connectOptionWithEverything(APM::OptionName name)
{
foreach (const QString& cmd, m_acceptedOperations.keys()) {
AkabeiOperation &op = m_acceptedOperations[cmd];
op.addConnectionWithOption(name);
}
}
void AkabeiParser::parse()
{
doParse();
switch (m_operation.name()) {
case APM::Help:
CommandLineUtils::printHelpMessage(m_acceptedOperations.values(), m_acceptedOptions.values(), m_data);
break;
case APM::Version:
CommandLineUtils::printVersion(m_data);
break;
case APM::License:
CommandLineUtils::printLicenses(m_data);
break;
case APM::Authors:
CommandLineUtils::printAuthors(m_data);
default:
break;
}
}
void AkabeiParser::doParse()
{
bool foundOp = false;
bool isArgExpected = false;
AkabeiOption previousOption;
QString optionLit;
for (QStringList::iterator it = m_argv.begin(); it < m_argv.end(); it++) {
QString arg = (*it);
/*
* This means a situation like (--ignore requires arg)
* --ignore arg1,arg2
* So in the previous iteration we were waiting for args to pop up.
*/
if (isArgExpected) {
/* The option wasn't added, so we add it now */
previousOption.addArguments(arg);
m_options.insert(previousOption.name(), previousOption);
isArgExpected = false;
continue;
}
/* Leaves out the dashes */
if (arg.startsWith("--")) {
optionLit = arg.mid(2);
} else if (arg.startsWith("-")) {
optionLit = arg.mid(1);
}
/* If there actually were dashes... */
if (!optionLit.isEmpty()) {
if (!m_acceptedOptions.contains(optionLit)) {
throw UnknownOptionException(optionLit);
}
/* Takes the argument from our structure to have all the info in one go */
AkabeiOption& option = m_acceptedOptions[optionLit];
if (option.hasArgs()) {
isArgExpected = true;
previousOption = option;
continue;
}
m_options.insert(option.name(), option);
} else { /* the first normal string is an operation, the next generic arguments */
if (!foundOp) {
if (!m_acceptedOperations.contains(arg)) {
throw UnknownOperationException(arg);
}
m_operation = m_acceptedOperations[arg];
foundOp = true;
} else {
m_args.append(arg);
}
}
}
/* We waited without success for the argument to appear */
if (isArgExpected) {
throw OptionArgExpectedException(optionLit);
}
/* An operation was never found */
if (!foundOp) {
throw MissingOperationException();
}
/* Checks if all the options are in-context */
foreach (const AkabeiOption& opt, m_options.values()) {
if (!m_operation.isOptionSupported(opt.name())) {
throw OptionOutOfContextException(opt.commandLong());
}
}
/* Free arguments */
if ((!m_args.isEmpty() && !m_operation.hasFreeArgs())) {
throw ArgumentsOutOfContextException();
}
if (m_args.isEmpty() && m_operation.hasFreeArgs()) {
throw ExpectedArgumentsException();
}
}
/*
* Maps the current operation with the type associated
*/
APM::OperationType AkabeiParser::type()
{
if (m_options.contains(APM::Local)) {
return APM::QueryOperationType;
}
return m_operation.type();
}
/*
* Getters from the parsing results
*/
QList< APM::OperationName > AkabeiParser::operations()
{
QList<APM::OperationName> ops;
/*
* This happens because the two parsers aren't 100% compatibles
* in the operations returned.
*/
if (m_operation.name() == APM::UpgradeSystem) {
ops.append(APM::UpdateDatabases);
ops.append(APM::UpgradeSystem);
} else if (m_operation.name() == APM::Newest) {
ops.append(APM::UpdateDatabases);
ops.append(APM::Install);
} else {
ops.append(m_operation.name());
}
return ops;
}
QHash<APM::OptionName, QStringList> AkabeiParser::options()
{
QHash<APM::OptionName, QStringList> result;
foreach (APM::OptionName key, m_options.keys()) {
result.insert(key, m_options[key].arguments());
}
return result;
}
QStringList AkabeiParser::args()
{
return m_args;
}
\ No newline at end of file
/*
* This file is part of the Chakra project
* Classes that manage the akabei-style command line
Copyright (C) 2011 Lisa Vitolo <shainer@chakra-project.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 CMDLINEPARSING_H
#define CMDLINEPARSING_H
#include <QStringList>
#include <QHash>
#include "akabeioptions.h"
#include "parser.h"
class AkabeiParser : public CommandLineParser
{
public:
AkabeiParser(int, char**, const KAboutData&);
void addOperation(APM::OperationType type, APM::OperationName name, QString command, QString commandLong, const char *desc, bool args);
void addOption(APM::OptionName name, QString cmdShort, QString cmdLong, const char *desc, QString argname="");
void addConnectionWithOption(APM::OptionName name);
void connectOptionWithEverything(APM::OptionName name);
void parse();
APM::OperationType type();
QList<APM::OperationName> operations();
QHash<APM::OptionName, QStringList> options();
QStringList args();
private:
QString m_lastOperation;
QHash<QString, AkabeiOperation> m_acceptedOperations;
QHash<QString, AkabeiOption> m_acceptedOptions;
AkabeiOperation m_operation;
QHash<APM::OptionName, AkabeiOption> m_options;
QStringList m_args;
void doParse();
};
#endif
\ No newline at end of file
......@@ -15,8 +15,7 @@
#include <QtCore/QObject>
#include <QStringList>
#include "cmdlineparsing.h"
#include "akabeioptions.h"
#include "akabeienums.h"
class OperationManager : public QObject
{
......
This diff is collapsed.
/* This file is part of the Chakra project
Copyright (C) 2011 Lisa "shainer" Vitolo <shainer@chakra-project.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 _CMDLINE_H
#define _CMDLINE_H
#include <QString>
#include <QList>
#include <QHash>
#include <klocalizedstring.h>
#include <kcmdlineargs.h>
#include <exception>
namespace APM
{
enum OperationType {
NoType, DatabaseOperationType, QueryOperationType, RemoveOperationType, SyncOperationType, UpgradeOperationType, PerformOperationType
};
typedef enum OperationType OperationType;
enum OptionName {
QueryPackageFile, ShowLocal, ShowLess, InstallAsDeps, InstallAsExplicit,
SkipDependencyCheck, Force, DownloadOnly, OnlyNeeded, Ignore, IgnoreGroup, DatabaseOnly,
RemoveConfig, Recursive, RootDir, CacheDir, DBPath
};
typedef enum OptionName OptionName;
enum OperationName {
None,
UpdateDatabases, ShowChangelog, ShowInstalledAsDeps, ShowInstalledExplicitely, ShowPackagesOfGroup,
ShowPackagesOfGroupLocal, ShowInformationLocal, ShowInformation, CheckFiles, ShowOwner, ShowNotRequired, ShowUpgradeable,
Install, RemoveOldFromCache, RemoveAllCache, ListRepo, Search, UpdateSystem,
Remove, Cascade, Unneeded, SearchLocal, Perform,
DatabaseOperation, Upgrade, Help, Version
};
typedef enum OperationName OperationName;
};
/**
* \class AkabeiOption cmdline.h "cmdline.h"
* \brief Representation of a command line option
*/
class AkabeiOption
{
private:
void init(APM::OptionName, const char *, const char *, const char *, bool, QStringList);
public:
APM::OptionName name;
QByteArray commandShort, commandLong;
KLocalizedString description;
bool hasArg;
/*
* Args are required by some options like --ignore or --ignoregroup
*/
QStringList args;
AkabeiOption(APM::OptionName, const char *, const char *, const char *, bool);
AkabeiOption(APM::OptionName, const char *, const char *, const char *, bool, QStringList);
AkabeiOption() {}
};
typedef QList<AkabeiOption> AkabeiOptionList;
/**
* \class AkabeiOperation cmdline.h "cmdline.h"
* \brief Representation of a command line operation
*/
class AkabeiOperation
{
private:
void init(APM::OperationType, APM::OperationName, const char *, const char *, const char *, bool, QStringList);
public:
APM::OperationType type;
APM::OperationName name;
QByteArray commandShort, commandLong;
KLocalizedString description;
QHash<APM::OptionName, AkabeiOption> options; /* options that can be associated to this operation */
bool hasFreeArgs;
/*
* An example of free args is the list of packages following an install command
*/
QStringList freeArgs;
AkabeiOperation();
AkabeiOperation(APM::OperationType, APM::OperationName, const char *, const char *, const char *, bool);
AkabeiOperation(APM::OperationType, APM::OperationName, const char *, const char *, const char *, bool, QStringList);
/*
* Options checking
*/
void addOption(AkabeiOption &);
bool isOptionSupported(APM::OptionName);
};
typedef QList<AkabeiOperation> AkabeiOperationList;
class CmdLine
{
private:
APM::OperationType m_type;
QMap<APM::OperationName, AkabeiOperation> m_operations;
QHash<APM::OptionName, AkabeiOption> m_options;
QStringList m_freeArgs;
/* Database */
QMultiHash<APM::OperationType, AkabeiOperation> acceptedOperations;
AkabeiOptionList acceptedOptions;
QHash<QByteArray, APM::OperationType> typechars;
/* This is for the few operations that we need to access quickly later */
QHash<APM::OperationName, AkabeiOperation> specialOperations;
bool parsed;
void secondParse(QStringList, QSet<QByteArray> &);
bool freeArgsRequired();
public:
CmdLine();
void parse(int argc, char **argv);
APM::OperationType type();
QList<APM::OperationName> operations();
QHash<APM::OptionName, AkabeiOption> options();
QStringList freeArgs();
};
class CmdLineException : public std::exception
{
const char* message;
public:
CmdLineException(const char *m)
: message(m)
{}
virtual const char *what() const throw() {
return message;
}
};
#endif
This diff is collapsed.
This diff is collapsed.
/*
* This file is part of the Chakra project
Copyright (C) 2011 Lisa Vitolo <shainer@chakra-project.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 "pakabeiparser.h"
#include <QDebug>
CommandLine::CommandLine(QStringList &args)
: m_commands(args)
, m_index(0)
{}
bool CommandLine::isSet(const QString& command)
{
QString actualCom;
if (command.isEmpty()) {
return false;
}
if (command.size() == 1) {
actualCom = "-" + command;
} else {
actualCom = "--" + command;
}
m_index = m_commands.indexOf(actualCom);
if (m_index != -1) {
m_required.push_front(actualCom);
return true;
}
return false;
}
QString CommandLine::optArg()
{
if (m_index < m_commands.size() - 1) {
QString arg( m_commands[m_index + 1] );