nymea-zigbee/zigbee-cli/terminalcommander.cpp

146 lines
3.3 KiB
C++

#include "terminalcommander.h"
#include "loggingcategory.h"
#include <QStringList>
static char **commandCompletion(const char* text, int start, int end);
static char *commandCompletionGenerator(const char *text, int state);
static TerminalCommander *s_instance = nullptr;
TerminalCommander *TerminalCommander::instance()
{
if (!s_instance)
s_instance = new TerminalCommander();
return s_instance;
}
QStringList TerminalCommander::commands() const
{
return m_commands;
}
TerminalCommander::TerminalCommander(QObject *parent) :
QThread(parent)
{
m_commands.append("start");
m_commands.append("stop");
m_commands.append("explode");
}
TerminalCommander::~TerminalCommander()
{
mutex.lock();
m_abort = true;
mutex.unlock();
wait();
}
void TerminalCommander::printToTerminal(const QString &message)
{
rl_printf("%s", message.toStdString().data());
}
void TerminalCommander::stopProcess()
{
mutex.lock();
m_abort = true;
mutex.unlock();
}
void TerminalCommander::run()
{
m_abort = false;
rl_attempted_completion_function = commandCompletion;
rl_set_prompt(QString("%1[zigbee]%2 ").arg(terminalColorBoldGray).arg(terminalColorNormal).toStdString().data());
rl_redisplay();
rl_bind_key('\t',rl_complete);
while (true) {
char *buffer = readline(QString("%1[zigbee]%2 ").arg(terminalColorBoldGray).arg(terminalColorNormal).toStdString().data());
rl_bind_key('\t',rl_complete);
if (buffer) {
if (!QString(buffer).isEmpty()) {
QStringList tokens = QString(buffer).split(" ");
emit commandReceived(tokens);
add_history(buffer);
free(buffer);
}
}
}
if (m_abort)
return;
msleep(10);
}
void TerminalCommander::rl_printf(const char *fmt, ...)
{
va_list args;
bool save_input;
char *saved_line;
int saved_point;
save_input = !RL_ISSTATE(RL_STATE_DONE);
if (save_input) {
saved_point = rl_point;
saved_line = rl_copy_text(0, rl_end);
rl_save_prompt();
rl_replace_line("", 0);
rl_redisplay();
}
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
if (save_input) {
rl_restore_prompt();
rl_replace_line(saved_line, 0);
rl_point = saved_point;
rl_redisplay();
free(saved_line);
}
}
char **commandCompletion(const char *text, int start, int end)
{
Q_UNUSED(end)
rl_completion_append_character = '\0';
char **matches = (char **) NULL;
if (start == 0) {
matches = rl_completion_matches ((char *) text, &commandCompletionGenerator);
}
return matches;
}
char *commandCompletionGenerator(const char *text, int state)
{
//qCDebug(dcZigbee) << text << state << TerminalCommander::instance()->commands();
static int list_index, len;
const char *name;
if (!state) {
list_index = 0;
len = strlen(text);
}
while (list_index < TerminalCommander::instance()->commands().count() && (name = TerminalCommander::instance()->commands().at(list_index).toStdString().data())) {
list_index++;
if (strncmp (name, text, len) == 0) return strdup (name);
}
// If no names matched, then return NULL.
return ((char *) NULL);
}