#include "gitconsole.h" #include #include #include struct Autocomplete { Autocomplete() { m_gitCommands << "git add" << "git mv" << "git reset" << "git rm" << "git grep" << "git log" << "git show" << "git status" << "git branch" << "git checkout" << "git commit" << "git diff" << "git rebase" << "git tag" << "git fetch" << "git pull" << "git clean" << "git reflog" << "git push" << "git submodule" << "git cherry-pick" << "git revert" << "git remote" << "git config" << "git clean" << "git stash"; qSort(m_gitCommands); } QList listMatches(const QString& text, QString& commonPart) { QList matches; foreach(QString command, m_gitCommands) { if(command.startsWith(text)) { matches.append(command); } } if(matches.count() > 1) { int i = 0; for(; i < qMax(matches.first().length(), matches.last().length()); i++) { if(matches.first().at(i) != matches.last().at(i)) { break; } } commonPart = matches.first().mid(0, i); } return matches; } QList m_gitCommands; }; namespace { Autocomplete completer; } GitConsole::GitConsole(QObject *parent) : QObject(parent) ,m_process(new QProcess(this)) ,m_busy(false) ,m_recentIndex(-1) { connect(m_process, &QProcess::readyRead, this, &GitConsole::onOutputReady); connect(m_process, SIGNAL(finished(int)), this, SLOT(onFinished(int))); } GitConsole::~GitConsole() { if(m_process && m_process->state() != QProcess::NotRunning) { m_process->terminate(); } } void GitConsole::exec(const QString& command) { m_recentIndex = -1; if(!command.startsWith("git ")) { emit commandError(); emit commandLog(QString("$ ") + command.toHtmlEscaped() + QString("
"), false); emit commandLog(tr("Only git command is accetable").append("
"), true); return; } qDebug() << "Execute:" << command << "in" << m_process->workingDirectory(); m_process->start(command); emit commandLog(QString("$ ") + command.toHtmlEscaped() + QString("
"), false); setBusy(true); if(m_recentContainer.count() <= 0 || m_recentContainer.first() != command) { m_recentContainer.push_front(command); } } void GitConsole::setRepository(GitRepository *repo) { m_repo = repo; m_process->setWorkingDirectory(m_repo->path()); } void GitConsole::onFinished(int exitCode) { if(exitCode != 0 ) { emit commandError(); } QByteArray log = m_process->readAllStandardOutput(); log += m_process->readAllStandardError(); emit commandLog(QString::fromUtf8(log).toHtmlEscaped().replace("\n","
"), true); setBusy(false); } void GitConsole::onOutputReady() { // QByteArray log = m_process->readAll(); } void GitConsole::recentUp() { if(m_recentContainer.count() <= 0) { return; } if(m_recentIndex >= (m_recentContainer.count() - 2)) { m_recentIndex = m_recentContainer.count() - 2; } emit recentChanged(m_recentContainer.at(++m_recentIndex)); } void GitConsole::recentDown() { if(m_recentContainer.count() <= 0) { return; } if(m_recentIndex <= 0) { m_recentIndex = -1; emit recentChanged(QString()); return; } emit recentChanged(m_recentContainer.at(--m_recentIndex)); } void GitConsole::requestAutocomplete(const QString& current) { QString commonPart; QList matches = completer.listMatches(current.trimmed(), commonPart); if(matches.count() == 1) { emit autocomplete(matches.first()); return; } if(matches.count() <= 0) { return; } emit autocomplete(commonPart); } void GitConsole::requestPredictions(QString current) { QString commonPart; current = current.trimmed(); QList matches = completer.listMatches(current, commonPart); if((!current.isEmpty() && matches.count() > 1) || (matches.count() == 1 && current != matches.first())) { emit predict(completer.listMatches(current, commonPart)); return; } emit predict(QList()); }