Commit 0721a22b authored by Ronan Abhamon's avatar Ronan Abhamon

feat(Cli): Cli is now a static object + clean code

parent e43fb27a
...@@ -69,12 +69,12 @@ ...@@ -69,12 +69,12 @@
<translation>show app version</translation> <translation>show app version</translation>
</message> </message>
<message> <message>
<source>commandLineCliHelp</source> <source>commandLineOptionCliHelp</source>
<translation>displays the help menu to use Linphone with the CLI.</translation> <translation>displays the help menu to use Linphone with the CLI</translation>
</message> </message>
<message> <message>
<source>commandLineDescription</source> <source>commandLineDescription</source>
<translation>send aan order to the application towards a command line.</translation> <translation>send an order to the application towards a command line</translation>
</message> </message>
</context> </context>
<context> <context>
......
...@@ -69,12 +69,12 @@ ...@@ -69,12 +69,12 @@
<translation>affiche la version de l&apos;application</translation> <translation>affiche la version de l&apos;application</translation>
</message> </message>
<message> <message>
<source>commandLineCliHelp</source> <source>commandLineOptionCliHelp</source>
<translation>affiche le menu d&apos;aide pour l&apos;utilisation de Linphone en CLI.</translation> <translation>affiche le menu d&apos;aide pour l&apos;utilisation de Linphone en CLI</translation>
</message> </message>
<message> <message>
<source>commandLineDescription</source> <source>commandLineDescription</source>
<translation>envoie un ordre à l&apos;application Linphone, voir --cli-help pour plus de détails.</translation> <translation>envoie un ordre à l&apos;application Linphone, voir --cli-help pour plus de détails</translation>
</message> </message>
</context> </context>
<context> <context>
......
...@@ -100,9 +100,8 @@ App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::U ...@@ -100,9 +100,8 @@ App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::U
mParser->showHelp(); mParser->showHelp();
} }
if(mParser->isSet("cli-help")){ if (mParser->isSet("cli-help")) {
mCli = new Cli(this); Cli::showHelp();
mCli->showHelp();
::exit(EXIT_SUCCESS); ::exit(EXIT_SUCCESS);
} }
...@@ -168,11 +167,10 @@ void App::initContentApp () { ...@@ -168,11 +167,10 @@ void App::initContentApp () {
setQuitOnLastWindowClosed(false); setQuitOnLastWindowClosed(false);
// Deal with received messages and CLI. // Deal with received messages and CLI.
mCli = new Cli(this);
QObject::connect(this, &App::receivedMessage, this, [this](int, const QByteArray &byteArray) { QObject::connect(this, &App::receivedMessage, this, [this](int, const QByteArray &byteArray) {
QString command(byteArray); QString command(byteArray);
qInfo() << QStringLiteral("Received command from other application: `%1`.").arg(command); qInfo() << QStringLiteral("Received command from other application: `%1`.").arg(command);
mCli->executeCommand(command); Cli::executeCommand(command);
}); });
// Add plugins directory. // Add plugins directory.
...@@ -190,7 +188,7 @@ void App::initContentApp () { ...@@ -190,7 +188,7 @@ void App::initContentApp () {
const QString commandArgument = getCommandArgument(); const QString commandArgument = getCommandArgument();
if (!commandArgument.isEmpty()) { if (!commandArgument.isEmpty()) {
Cli::CommandFormat format; Cli::CommandFormat format;
mCli->executeCommand(commandArgument, &format); Cli::executeCommand(commandArgument, &format);
if (format == Cli::UriFormat) if (format == Cli::UriFormat)
mustBeIconified = true; mustBeIconified = true;
} }
...@@ -254,8 +252,7 @@ QString App::getCommandArgument () { ...@@ -254,8 +252,7 @@ QString App::getCommandArgument () {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void App::executeCommand (const QString &command) { void App::executeCommand (const QString &command) {
Q_CHECK_PTR(mCli); Cli::executeCommand(command);
mCli->executeCommand(command);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -333,10 +330,10 @@ void App::createParser () { ...@@ -333,10 +330,10 @@ void App::createParser () {
mParser = new QCommandLineParser(); mParser = new QCommandLineParser();
mParser->setApplicationDescription(tr("applicationDescription")); mParser->setApplicationDescription(tr("applicationDescription"));
mParser->addPositionalArgument("command",tr("commandLineDescription"),"[command]"); mParser->addPositionalArgument("command", tr("commandLineDescription"), "[command]");
mParser->addOptions({ mParser->addOptions({
{ { "h", "help" }, tr("commandLineOptionHelp") }, { { "h", "help" }, tr("commandLineOptionHelp") },
{ "cli-help", tr("commandLineCliHelp") }, { "cli-help", tr("commandLineOptionCliHelp") },
{ { "v", "version" }, tr("commandLineOptionVersion") }, { { "v", "version" }, tr("commandLineOptionVersion") },
{ "config", tr("commandLineOptionConfig"), tr("commandLineOptionConfigArg") }, { "config", tr("commandLineOptionConfig"), tr("commandLineOptionConfigArg") },
#ifndef Q_OS_MACOS #ifndef Q_OS_MACOS
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
class QCommandLineParser; class QCommandLineParser;
class QSystemTrayIcon; class QSystemTrayIcon;
class Cli;
class DefaultTranslator; class DefaultTranslator;
class App : public SingleApplication { class App : public SingleApplication {
...@@ -143,8 +142,6 @@ private: ...@@ -143,8 +142,6 @@ private:
Colors *mColors = nullptr; Colors *mColors = nullptr;
QSystemTrayIcon *mSystemTrayIcon = nullptr; QSystemTrayIcon *mSystemTrayIcon = nullptr;
Cli *mCli = nullptr;
}; };
#endif // APP_H_ #endif // APP_H_
...@@ -133,12 +133,93 @@ static void cliInitiateConference (QHash<QString, QString> &args) { ...@@ -133,12 +133,93 @@ static void cliInitiateConference (QHash<QString, QString> &args) {
// TODO: Set the view to the "waiting call view". // TODO: Set the view to the "waiting call view".
} }
// =============================================================================
// Helpers.
// =============================================================================
static QString splitWord (QString word, int &curPos, const int lineLength, const QString &padding) {
QString out;
out += word.mid(0, lineLength - curPos) + "\n" + padding;
curPos = padding.length();
word = word.mid(lineLength - curPos);
while (word.length() > lineLength - curPos) {
out += word.mid(0, lineLength - curPos);
word = word.mid(lineLength - curPos);
out += "\n" + padding;
}
out += word;
curPos = word.length() + padding.length();
return out;
}
static QString indentedWord (QString word, int &curPos, const int lineLength, const QString &padding) {
QString out;
if (curPos + word.length() > lineLength) {
if (padding.length() + word.length() > lineLength) {
out += splitWord(word, curPos, lineLength, padding);
} else {
out += QStringLiteral("\n");
out += padding + word;
curPos = padding.length();
}
} else {
out += word;
curPos += word.length();
}
return out;
}
static string multilineIndent (const QString &str, int indentationNumber = 0) {
static const int lineLength(80);
static const QRegExp spaceRegexp("(\\s)");
const QString padding(indentationNumber * 2, ' ');
QString out = padding;
int indentedTextCurPos = padding.length();
int spacePos = 0;
int wordPos = spacePos;
QString word;
while ((spacePos = spaceRegexp.indexIn(str, spacePos)) != -1) {
word = str.mid(wordPos, spacePos - wordPos);
out += indentedWord(word, indentedTextCurPos, lineLength, padding);
switch (str[spacePos].unicode()) {
case '\n':
out += "\n" + padding;
indentedTextCurPos = padding.length();
break;
case '\t': // TAB as space.
case ' ':
if (indentedTextCurPos == lineLength) {
out += "\n" + padding;
indentedTextCurPos = padding.length();
} else {
out += " ";
indentedTextCurPos += 1;
}
break;
default:
break;
}
spacePos += 1;
wordPos = spacePos;
}
word = str.mid(wordPos);
out += indentedWord(word, indentedTextCurPos, lineLength, padding);
out += "\n";
return ::Utils::appStringToCoreString(out);
}
// ============================================================================= // =============================================================================
Cli::Command::Command ( Cli::Command::Command (
const QString &functionName, const QString &functionName,
const QString &functionDescription, const char *functionDescription,
const QString &cliDescription, const char *cliDescription,
Cli::Function function, Cli::Function function,
const QHash<QString, Cli::Argument> &argsScheme const QHash<QString, Cli::Argument> &argsScheme
) : ) :
...@@ -201,47 +282,25 @@ void Cli::Command::executeUri (const shared_ptr<linphone::Address> &address) con ...@@ -201,47 +282,25 @@ void Cli::Command::executeUri (const shared_ptr<linphone::Address> &address) con
QRegExp Cli::mRegExpArgs("(?:(?:([\\w-]+)\\s*)=\\s*(?:\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|([^\\s]+)\\s*))"); QRegExp Cli::mRegExpArgs("(?:(?:([\\w-]+)\\s*)=\\s*(?:\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"|([^\\s]+)\\s*))");
QRegExp Cli::mRegExpFunctionName("^\\s*([a-z-]+)\\s*"); QRegExp Cli::mRegExpFunctionName("^\\s*([a-z-]+)\\s*");
Cli::Cli (QObject *parent) : QObject(parent) { QMap<QString, Cli::Command> Cli::mCommands = {
addCommand("show", tr("showFunctionDescription"), tr("showCliDescription"), ::cliShow); createCommand("show", QT_TR_NOOP("showFunctionDescription"), QT_TR_NOOP("showCliDescription"), ::cliShow),
addCommand("call", tr("callFunctionDescription"), tr("callCliDescription"), ::cliCall, { createCommand("call", QT_TR_NOOP("callFunctionDescription"), QT_TR_NOOP("callCliDescription"), ::cliCall, {
{ "sip-address", {} } { "sip-address", {} }
}); }),
addCommand("initiate-conference", tr("initiateConferenceFunctionDescription"), tr("initiateConferenceCliDescription"), ::cliInitiateConference, { createCommand("initiate-conference", QT_TR_NOOP("initiateConferenceFunctionDescription"), QT_TR_NOOP("initiateConferenceCliDescription"), ::cliInitiateConference, {
{ "sip-address", {} }, { "conference-id", {} } { "sip-address", {} }, { "conference-id", {} }
}); }),
addCommand("join-conference", tr("joinConferenceFunctionDescription"), tr("joinConferenceCliDescription"), ::cliJoinConference, { createCommand("join-conference", QT_TR_NOOP("joinConferenceFunctionDescription"), QT_TR_NOOP("joinConferenceCliDescription"), ::cliJoinConference, {
{ "sip-address", {} }, { "conference-id", {} }, { "display-name", {} } { "sip-address", {} }, { "conference-id", {} }, { "display-name", {} }
}); }),
addCommand("join-conference-as", tr("joinConferenceAsFunctionDescription"), tr("joinConferenceAsCliDescription"), ::cliJoinConferenceAs, { createCommand("join-conference-as", QT_TR_NOOP("joinConferenceAsFunctionDescription"), QT_TR_NOOP("joinConferenceAsCliDescription"), ::cliJoinConferenceAs, {
{ "sip-address", {} }, { "conference-id", {} }, { "guest-sip-address", {} } { "sip-address", {} }, { "conference-id", {} }, { "guest-sip-address", {} }
}); })
} };
// -----------------------------------------------------------------------------
void Cli::addCommand (
const QString &functionName,
const QString &functionDescription,
const QString &cliDescription,
Function function,
const QHash<QString, Argument> &argsScheme
) {
if (mCommands.contains(functionName)) {
qWarning() << QStringLiteral("Command already exists: `%1`.").arg(functionName);
return;
}
mCommands[functionName] = Cli::Command(
functionName,
functionDescription,
cliDescription,
function,
argsScheme
);
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void Cli::executeCommand (const QString &command, CommandFormat *format) const { void Cli::executeCommand (const QString &command, CommandFormat *format) {
shared_ptr<linphone::Address> address = linphone::Factory::get()->createAddress( shared_ptr<linphone::Address> address = linphone::Factory::get()->createAddress(
::Utils::appStringToCoreString(command) ::Utils::appStringToCoreString(command)
); );
...@@ -284,107 +343,37 @@ void Cli::executeCommand (const QString &command, CommandFormat *format) const { ...@@ -284,107 +343,37 @@ void Cli::executeCommand (const QString &command, CommandFormat *format) const {
mCommands[functionName].executeUri(address); mCommands[functionName].executeUri(address);
} }
QString splitWord(QString word, int &curPos, const int lineLength, const QString &padding) { void Cli::showHelp () {
QString out; cout << multilineIndent(tr("linphoneCliDescription"), 0) <<
out += word.mid(0,lineLength - curPos) + "\n" + padding; endl <<
curPos = padding.length(); "Usage: " <<
word = word.mid(lineLength - curPos); endl <<
while(word.length() > lineLength - curPos) { multilineIndent(tr("uriCommandLineSyntax"), 0) <<
out += word.mid(0,lineLength - curPos); multilineIndent(tr("cliCommandLineSyntax"), 0) <<
word = word.mid(lineLength - curPos); endl <<
out += "\n" + padding; multilineIndent(tr("commandsName")) << endl;
}
out += word; for (const auto &method : mCommands.keys())
curPos = word.length() + padding.length(); cout << multilineIndent(tr(mCommands[method].getCliDescription()), 1) <<
return out; multilineIndent(tr(mCommands[method].getFunctionDescription()), 2) <<
} endl;
QString indentedWord(QString word, int &curPos, const int lineLength, const QString &padding){
QString out;
if (curPos + word.length() > lineLength ) {
if (padding.length() + word.length() > lineLength) {
out += splitWord(word, curPos, lineLength, padding);
} else {
out += QStringLiteral("\n");
out += padding + word;
curPos = padding.length();
}
} else {
out += word;
curPos += word.length();
}
return out;
} }
static string multilineIndent (const QString &str, int indentationNumber = 0) { // -----------------------------------------------------------------------------
static const int lineLength(80);
static const QRegExp spaceRegexp("(\\s)");
const QString padding(indentationNumber * 2, ' ');
QString out = padding;
int indentedTextCurPos = padding.length();
int spacePos = 0;
int wordPos = spacePos;
QString word;
while ((spacePos = spaceRegexp.indexIn(str, spacePos)) != -1) {
word = str.mid(wordPos,spacePos-wordPos);
out += indentedWord(word, indentedTextCurPos, lineLength, padding);
switch (str[spacePos].unicode()) {
case '\n':
out += "\n" + padding;
indentedTextCurPos = padding.length();
break;
case '\t': //tabulated as a space
case ' ':
if (indentedTextCurPos == lineLength) {
out += "\n" + padding;
indentedTextCurPos = padding.length();
} else {
out += " ";
indentedTextCurPos += 1;
}
break;
case '\r':
case '\f':
break;
default :
break;
}
spacePos += 1;
wordPos = spacePos;
}
word = str.mid(wordPos);
out += indentedWord(word, indentedTextCurPos,lineLength, padding);
out += "\n";
return ::Utils::appStringToCoreString(out);
}
void Cli::showHelp() { pair<QString, Cli::Command> Cli::createCommand (
cout << multilineIndent(tr("linphoneCliDescription"),0); const QString &functionName,
cout << "\n" << "Usage : " << "\n"; const char *functionDescription,
cout << multilineIndent(tr("uriCommandLineSyntax"),0); const char *cliDescription,
cout <<multilineIndent(tr("cliCommandLineSyntax"),0); Function function,
cout << "\n"; const QHash<QString, Argument> &argsScheme
cout << multilineIndent(tr("commandsName")); ) {
return { functionName, Cli::Command(functionName, functionDescription, cliDescription, function, argsScheme) };
cout << "\n";
for (const auto &method : mCommands.keys()) {
cout << multilineIndent(mCommands[method].getCliDescription(),1);
cout << multilineIndent(mCommands[method].getFunctionDescription(),2);
cout << "\n";
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
QString Cli::parseFunctionName (const QString &command) const { QString Cli::parseFunctionName (const QString &command) {
mRegExpFunctionName.indexIn(command); mRegExpFunctionName.indexIn(command);
if (mRegExpFunctionName.pos(1) == -1) { if (mRegExpFunctionName.pos(1) == -1) {
qWarning() << QStringLiteral("Unable to parse function name of command: `%1`.").arg(command); qWarning() << QStringLiteral("Unable to parse function name of command: `%1`.").arg(command);
...@@ -402,7 +391,7 @@ QString Cli::parseFunctionName (const QString &command) const { ...@@ -402,7 +391,7 @@ QString Cli::parseFunctionName (const QString &command) const {
return functionName; return functionName;
} }
QHash<QString, QString> Cli::parseArgs (const QString &command) const { QHash<QString, QString> Cli::parseArgs (const QString &command) {
QHash<QString, QString> args; QHash<QString, QString> args;
int pos = 0; int pos = 0;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <memory> #include <memory>
#include <QHash> #include <QHash>
#include <QMap>
#include <QObject> #include <QObject>
// ============================================================================= // =============================================================================
...@@ -58,8 +59,8 @@ class Cli : public QObject { ...@@ -58,8 +59,8 @@ class Cli : public QObject {
Command () = default; Command () = default;
Command ( Command (
const QString &functionName, const QString &functionName,
const QString &functionDescription, const char *functionDescription,
const QString &cliDescription, const char *cliDescription,
Function function, Function function,
const QHash<QString, Argument> &argsScheme const QHash<QString, Argument> &argsScheme
); );
...@@ -67,25 +68,23 @@ class Cli : public QObject { ...@@ -67,25 +68,23 @@ class Cli : public QObject {
void execute (QHash<QString, QString> &args) const; void execute (QHash<QString, QString> &args) const;
void executeUri (const std::shared_ptr<linphone::Address> &address) const; void executeUri (const std::shared_ptr<linphone::Address> &address) const;
QString getFunctionDescription() { const char *getFunctionDescription () const {
return mFunctionDescription; return mFunctionDescription;
} }
QString getCliDescription() { const char *getCliDescription () const {
return mCliDescription; return mCliDescription;
} }
private: private:
QString mFunctionDescription;
QString mCliDescription;
QString mFunctionName; QString mFunctionName;
const char *mFunctionDescription;
const char *mCliDescription;
Function mFunction = nullptr; Function mFunction = nullptr;
QHash<QString, Argument> mArgsScheme; QHash<QString, Argument> mArgsScheme;
}; };
public: public:
Cli (QObject *parent = Q_NULLPTR);
~Cli () = default; ~Cli () = default;
enum CommandFormat { enum CommandFormat {
...@@ -94,23 +93,25 @@ public: ...@@ -94,23 +93,25 @@ public:
UriFormat UriFormat
}; };
void executeCommand (const QString &command, CommandFormat *format = nullptr) const; static void executeCommand (const QString &command, CommandFormat *format = nullptr);
void showHelp(); static void showHelp ();
private: private:
void addCommand ( Cli ();
static std::pair<QString, Command> createCommand (
const QString &functionName, const QString &functionName,
const QString &functionDescription, const char *functionDescription,
const QString &cliDescription, const char *cliDescription,
Function function, Function function,
const QHash<QString, Argument> &argsScheme = QHash<QString, Argument>() const QHash<QString, Argument> &argsScheme = QHash<QString, Argument>()
); );
QString parseFunctionName (const QString &command) const; static QString parseFunctionName (const QString &command);
QHash<QString, QString> parseArgs (const QString &command) const; static QHash<QString, QString> parseArgs (const QString &command);
QHash<QString, Command> mCommands; static QMap<QString, Command> mCommands;
static QRegExp mRegExpArgs; static QRegExp mRegExpArgs;
static QRegExp mRegExpFunctionName; static QRegExp mRegExpFunctionName;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment