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 @@
<translation>show app version</translation>
</message>
<message>
<source>commandLineCliHelp</source>
<translation>displays the help menu to use Linphone with the CLI.</translation>
<source>commandLineOptionCliHelp</source>
<translation>displays the help menu to use Linphone with the CLI</translation>
</message>
<message>
<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>
</context>
<context>
......
......@@ -69,12 +69,12 @@
<translation>affiche la version de l&apos;application</translation>
</message>
<message>
<source>commandLineCliHelp</source>
<translation>affiche le menu d&apos;aide pour l&apos;utilisation de Linphone en CLI.</translation>
<source>commandLineOptionCliHelp</source>
<translation>affiche le menu d&apos;aide pour l&apos;utilisation de Linphone en CLI</translation>
</message>
<message>
<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>
</context>
<context>
......
......@@ -100,9 +100,8 @@ App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::U
mParser->showHelp();
}
if(mParser->isSet("cli-help")){
mCli = new Cli(this);
mCli->showHelp();
if (mParser->isSet("cli-help")) {
Cli::showHelp();
::exit(EXIT_SUCCESS);
}
......@@ -168,11 +167,10 @@ void App::initContentApp () {
setQuitOnLastWindowClosed(false);
// Deal with received messages and CLI.
mCli = new Cli(this);
QObject::connect(this, &App::receivedMessage, this, [this](int, const QByteArray &byteArray) {
QString command(byteArray);
qInfo() << QStringLiteral("Received command from other application: `%1`.").arg(command);
mCli->executeCommand(command);
Cli::executeCommand(command);
});
// Add plugins directory.
......@@ -190,7 +188,7 @@ void App::initContentApp () {
const QString commandArgument = getCommandArgument();
if (!commandArgument.isEmpty()) {
Cli::CommandFormat format;
mCli->executeCommand(commandArgument, &format);
Cli::executeCommand(commandArgument, &format);
if (format == Cli::UriFormat)
mustBeIconified = true;
}
......@@ -254,8 +252,7 @@ QString App::getCommandArgument () {
// -----------------------------------------------------------------------------
void App::executeCommand (const QString &command) {
Q_CHECK_PTR(mCli);
mCli->executeCommand(command);
Cli::executeCommand(command);
}
// -----------------------------------------------------------------------------
......@@ -333,10 +330,10 @@ void App::createParser () {
mParser = new QCommandLineParser();
mParser->setApplicationDescription(tr("applicationDescription"));
mParser->addPositionalArgument("command",tr("commandLineDescription"),"[command]");
mParser->addPositionalArgument("command", tr("commandLineDescription"), "[command]");
mParser->addOptions({
{ { "h", "help" }, tr("commandLineOptionHelp") },
{ "cli-help", tr("commandLineCliHelp") },
{ "cli-help", tr("commandLineOptionCliHelp") },
{ { "v", "version" }, tr("commandLineOptionVersion") },
{ "config", tr("commandLineOptionConfig"), tr("commandLineOptionConfigArg") },
#ifndef Q_OS_MACOS
......
......@@ -37,7 +37,6 @@
class QCommandLineParser;
class QSystemTrayIcon;
class Cli;
class DefaultTranslator;
class App : public SingleApplication {
......@@ -143,8 +142,6 @@ private:
Colors *mColors = nullptr;
QSystemTrayIcon *mSystemTrayIcon = nullptr;
Cli *mCli = nullptr;
};
#endif // APP_H_
......@@ -133,12 +133,93 @@ static void cliInitiateConference (QHash<QString, QString> &args) {
// 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 (
const QString &functionName,
const QString &functionDescription,
const QString &cliDescription,
const char *functionDescription,
const char *cliDescription,
Cli::Function function,
const QHash<QString, Cli::Argument> &argsScheme
) :
......@@ -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::mRegExpFunctionName("^\\s*([a-z-]+)\\s*");
Cli::Cli (QObject *parent) : QObject(parent) {
addCommand("show", tr("showFunctionDescription"), tr("showCliDescription"), ::cliShow);
addCommand("call", tr("callFunctionDescription"), tr("callCliDescription"), ::cliCall, {
QMap<QString, Cli::Command> Cli::mCommands = {
createCommand("show", QT_TR_NOOP("showFunctionDescription"), QT_TR_NOOP("showCliDescription"), ::cliShow),
createCommand("call", QT_TR_NOOP("callFunctionDescription"), QT_TR_NOOP("callCliDescription"), ::cliCall, {
{ "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", {} }
});
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", {} }
});
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", {} }
});
}
// -----------------------------------------------------------------------------
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(
::Utils::appStringToCoreString(command)
);
......@@ -284,107 +343,37 @@ void Cli::executeCommand (const QString &command, CommandFormat *format) const {
mCommands[functionName].executeUri(address);
}
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;
}
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;
void Cli::showHelp () {
cout << multilineIndent(tr("linphoneCliDescription"), 0) <<
endl <<
"Usage: " <<
endl <<
multilineIndent(tr("uriCommandLineSyntax"), 0) <<
multilineIndent(tr("cliCommandLineSyntax"), 0) <<
endl <<
multilineIndent(tr("commandsName")) << endl;
for (const auto &method : mCommands.keys())
cout << multilineIndent(tr(mCommands[method].getCliDescription()), 1) <<
multilineIndent(tr(mCommands[method].getFunctionDescription()), 2) <<
endl;
}
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() {
cout << multilineIndent(tr("linphoneCliDescription"),0);
cout << "\n" << "Usage : " << "\n";
cout << multilineIndent(tr("uriCommandLineSyntax"),0);
cout <<multilineIndent(tr("cliCommandLineSyntax"),0);
cout << "\n";
cout << multilineIndent(tr("commandsName"));
cout << "\n";
for (const auto &method : mCommands.keys()) {
cout << multilineIndent(mCommands[method].getCliDescription(),1);
cout << multilineIndent(mCommands[method].getFunctionDescription(),2);
cout << "\n";
}
pair<QString, Cli::Command> Cli::createCommand (
const QString &functionName,
const char *functionDescription,
const char *cliDescription,
Function function,
const QHash<QString, Argument> &argsScheme
) {
return { functionName, Cli::Command(functionName, functionDescription, cliDescription, function, argsScheme) };
}
// -----------------------------------------------------------------------------
QString Cli::parseFunctionName (const QString &command) const {
QString Cli::parseFunctionName (const QString &command) {
mRegExpFunctionName.indexIn(command);
if (mRegExpFunctionName.pos(1) == -1) {
qWarning() << QStringLiteral("Unable to parse function name of command: `%1`.").arg(command);
......@@ -402,7 +391,7 @@ QString Cli::parseFunctionName (const QString &command) const {
return functionName;
}
QHash<QString, QString> Cli::parseArgs (const QString &command) const {
QHash<QString, QString> Cli::parseArgs (const QString &command) {
QHash<QString, QString> args;
int pos = 0;
......
......@@ -26,6 +26,7 @@
#include <memory>
#include <QHash>
#include <QMap>
#include <QObject>
// =============================================================================
......@@ -58,8 +59,8 @@ class Cli : public QObject {
Command () = default;
Command (
const QString &functionName,
const QString &functionDescription,
const QString &cliDescription,
const char *functionDescription,
const char *cliDescription,
Function function,
const QHash<QString, Argument> &argsScheme
);
......@@ -67,25 +68,23 @@ class Cli : public QObject {
void execute (QHash<QString, QString> &args) const;
void executeUri (const std::shared_ptr<linphone::Address> &address) const;
QString getFunctionDescription() {
const char *getFunctionDescription () const {
return mFunctionDescription;
}
QString getCliDescription() {
const char *getCliDescription () const {
return mCliDescription;
}
private:
QString mFunctionDescription;
QString mCliDescription;
QString mFunctionName;
const char *mFunctionDescription;
const char *mCliDescription;
Function mFunction = nullptr;
QHash<QString, Argument> mArgsScheme;
};
public:
Cli (QObject *parent = Q_NULLPTR);
~Cli () = default;
enum CommandFormat {
......@@ -94,23 +93,25 @@ public:
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:
void addCommand (
Cli ();
static std::pair<QString, Command> createCommand (
const QString &functionName,
const QString &functionDescription,
const QString &cliDescription,
const char *functionDescription,
const char *cliDescription,
Function function,
const QHash<QString, Argument> &argsScheme = QHash<QString, Argument>()
);
QString parseFunctionName (const QString &command) const;
QHash<QString, QString> parseArgs (const QString &command) const;
static QString parseFunctionName (const QString &command);
static QHash<QString, QString> parseArgs (const QString &command);
QHash<QString, Command> mCommands;
static QMap<QString, Command> mCommands;
static QRegExp mRegExpArgs;
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