gitconsole.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "gitconsole.h"
  2. #include <QProcess>
  3. #include <gitrepository.h>
  4. #include <QTimer>
  5. struct Autocomplete {
  6. Autocomplete() {
  7. m_gitCommands
  8. << "git add"
  9. << "git mv"
  10. << "git reset"
  11. << "git rm"
  12. << "git grep"
  13. << "git log"
  14. << "git show"
  15. << "git status"
  16. << "git branch"
  17. << "git checkout"
  18. << "git commit"
  19. << "git diff"
  20. << "git rebase"
  21. << "git tag"
  22. << "git fetch"
  23. << "git pull"
  24. << "git clean"
  25. << "git reflog"
  26. << "git push"
  27. << "git submodule"
  28. << "git cherry-pick"
  29. << "git revert"
  30. << "git remote"
  31. << "git config"
  32. << "git clean"
  33. << "git stash";
  34. qSort(m_gitCommands);
  35. }
  36. QList<QString> listMatches(const QString& text, QString& commonPart) {
  37. QList<QString> matches;
  38. foreach(QString command, m_gitCommands) {
  39. if(command.startsWith(text)) {
  40. matches.append(command);
  41. }
  42. }
  43. if(matches.count() > 1) {
  44. int i = 0;
  45. for(; i < qMax(matches.first().length(), matches.last().length()); i++) {
  46. if(matches.first().at(i) != matches.last().at(i)) {
  47. break;
  48. }
  49. }
  50. commonPart = matches.first().mid(0, i);
  51. }
  52. return matches;
  53. }
  54. QList<QString> m_gitCommands;
  55. };
  56. namespace {
  57. Autocomplete completer;
  58. }
  59. GitConsole::GitConsole(QObject *parent) : QObject(parent)
  60. ,m_process(new QProcess(this))
  61. ,m_busy(false)
  62. ,m_recentIndex(-1)
  63. {
  64. connect(m_process, &QProcess::readyRead, this, &GitConsole::onOutputReady);
  65. connect(m_process, SIGNAL(finished(int)), this, SLOT(onFinished(int)));
  66. }
  67. GitConsole::~GitConsole()
  68. {
  69. if(m_process && m_process->state() != QProcess::NotRunning) {
  70. m_process->terminate();
  71. }
  72. }
  73. void GitConsole::exec(const QString& command)
  74. {
  75. m_recentIndex = -1;
  76. if(!command.startsWith("git ")) {
  77. emit commandError();
  78. emit commandLog(QString("<b>$&nbsp;") + command.toHtmlEscaped() + QString("</b><br/>"), false);
  79. emit commandLog(tr("Only <b>git</b> command is accetable").append("<br/>"), true);
  80. return;
  81. }
  82. qDebug() << "Execute:" << command << "in" << m_process->workingDirectory();
  83. m_process->start(command);
  84. emit commandLog(QString("<b>$&nbsp;") + command.toHtmlEscaped() + QString("</b><br/>"), false);
  85. setBusy(true);
  86. if(m_recentContainer.count() <= 0 || m_recentContainer.first() != command) {
  87. m_recentContainer.push_front(command);
  88. }
  89. }
  90. void GitConsole::setRepository(GitRepository *repo)
  91. {
  92. m_repo = repo;
  93. m_process->setWorkingDirectory(m_repo->path());
  94. }
  95. void GitConsole::onFinished(int exitCode)
  96. {
  97. if(exitCode != 0 ) {
  98. emit commandError();
  99. }
  100. QByteArray log = m_process->readAllStandardOutput();
  101. log += m_process->readAllStandardError();
  102. emit commandLog(QString::fromUtf8(log).toHtmlEscaped().replace("\n","<br/>"), true);
  103. setBusy(false);
  104. }
  105. void GitConsole::onOutputReady()
  106. {
  107. // QByteArray log = m_process->readAll();
  108. }
  109. void GitConsole::recentUp()
  110. {
  111. if(m_recentContainer.count() <= 0) {
  112. return;
  113. }
  114. if(m_recentIndex >= (m_recentContainer.count() - 2)) {
  115. m_recentIndex = m_recentContainer.count() - 2;
  116. }
  117. emit recentChanged(m_recentContainer.at(++m_recentIndex));
  118. }
  119. void GitConsole::recentDown()
  120. {
  121. if(m_recentContainer.count() <= 0) {
  122. return;
  123. }
  124. if(m_recentIndex <= 0) {
  125. m_recentIndex = -1;
  126. emit recentChanged(QString());
  127. return;
  128. }
  129. emit recentChanged(m_recentContainer.at(--m_recentIndex));
  130. }
  131. void GitConsole::requestAutocomplete(const QString& current)
  132. {
  133. QString commonPart;
  134. QList<QString> matches = completer.listMatches(current.trimmed(), commonPart);
  135. if(matches.count() == 1) {
  136. emit autocomplete(matches.first());
  137. return;
  138. }
  139. if(matches.count() <= 0) {
  140. return;
  141. }
  142. emit autocomplete(commonPart);
  143. }
  144. void GitConsole::requestPredictions(QString current)
  145. {
  146. QString commonPart;
  147. current = current.trimmed();
  148. QList<QString> matches = completer.listMatches(current, commonPart);
  149. if((!current.isEmpty() && matches.count() > 1) || (matches.count() == 1 && current != matches.first())) {
  150. emit predict(completer.listMatches(current, commonPart));
  151. return;
  152. }
  153. emit predict(QList<QString>());
  154. }