forked from qt-creator/qt-creator
Git: Support tree argument for Grep
Change-Id: Ic7dfcd8bad98223d68725f1a0c1f103ad8ea4e0f Reviewed-by: Eike Ziller <eike.ziller@theqtcompany.com> Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
This commit is contained in:
committed by
Orgad Shaneh
parent
fcdb286cec
commit
84f2875f6d
@@ -27,21 +27,26 @@
|
|||||||
#include "gitclient.h"
|
#include "gitclient.h"
|
||||||
#include "gitplugin.h"
|
#include "gitplugin.h"
|
||||||
|
|
||||||
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <coreplugin/progressmanager/progressmanager.h>
|
#include <coreplugin/progressmanager/progressmanager.h>
|
||||||
#include <coreplugin/vcsmanager.h>
|
#include <coreplugin/vcsmanager.h>
|
||||||
#include <texteditor/findinfiles.h>
|
#include <texteditor/findinfiles.h>
|
||||||
#include <vcsbase/vcscommand.h>
|
#include <vcsbase/vcscommand.h>
|
||||||
#include <vcsbase/vcsbaseconstants.h>
|
#include <vcsbase/vcsbaseconstants.h>
|
||||||
|
|
||||||
|
#include <utils/fancylineedit.h>
|
||||||
#include <utils/filesearch.h>
|
#include <utils/filesearch.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/runextensions.h>
|
#include <utils/runextensions.h>
|
||||||
#include <utils/synchronousprocess.h>
|
#include <utils/synchronousprocess.h>
|
||||||
|
#include <utils/textfileformat.h>
|
||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
#include <QFutureWatcher>
|
#include <QFutureWatcher>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QRegularExpressionValidator>
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
@@ -49,6 +54,13 @@
|
|||||||
namespace Git {
|
namespace Git {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
class GitGrepParameters
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QString ref;
|
||||||
|
bool isEnabled = false;
|
||||||
|
};
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
using VcsBase::VcsCommand;
|
using VcsBase::VcsCommand;
|
||||||
@@ -56,6 +68,7 @@ using VcsBase::VcsCommand;
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const char EnableGitGrep[] = "EnableGitGrep";
|
const char EnableGitGrep[] = "EnableGitGrep";
|
||||||
|
const char GitGrepRef[] = "GitGrepRef";
|
||||||
|
|
||||||
class GitGrepRunner : public QObject
|
class GitGrepRunner : public QObject
|
||||||
{
|
{
|
||||||
@@ -78,8 +91,10 @@ public:
|
|||||||
static const QLatin1String resetColor("\x1b[m");
|
static const QLatin1String resetColor("\x1b[m");
|
||||||
FileSearchResult single;
|
FileSearchResult single;
|
||||||
const int lineSeparator = line.indexOf(QChar::Null);
|
const int lineSeparator = line.indexOf(QChar::Null);
|
||||||
single.fileName = m_directory + QLatin1Char('/')
|
QString filePath = line.left(lineSeparator);
|
||||||
+ line.left(lineSeparator);
|
if (!m_ref.isEmpty() && filePath.startsWith(m_ref))
|
||||||
|
filePath.remove(0, m_ref.length());
|
||||||
|
single.fileName = m_directory + QLatin1Char('/') + filePath;
|
||||||
const int textSeparator = line.indexOf(QChar::Null, lineSeparator + 1);
|
const int textSeparator = line.indexOf(QChar::Null, lineSeparator + 1);
|
||||||
single.lineNumber = line.mid(lineSeparator + 1, textSeparator - lineSeparator - 1).toInt();
|
single.lineNumber = line.mid(lineSeparator + 1, textSeparator - lineSeparator - 1).toInt();
|
||||||
QString text = line.mid(textSeparator + 1);
|
QString text = line.mid(textSeparator + 1);
|
||||||
@@ -130,6 +145,11 @@ public:
|
|||||||
else
|
else
|
||||||
arguments << QLatin1String("-F");
|
arguments << QLatin1String("-F");
|
||||||
arguments << m_parameters.text;
|
arguments << m_parameters.text;
|
||||||
|
GitGrepParameters params = m_parameters.extensionParameters.value<GitGrepParameters>();
|
||||||
|
if (!params.ref.isEmpty()) {
|
||||||
|
arguments << params.ref;
|
||||||
|
m_ref = params.ref + QLatin1Char(':');
|
||||||
|
}
|
||||||
arguments << QLatin1String("--") << m_parameters.nameFilters;
|
arguments << QLatin1String("--") << m_parameters.nameFilters;
|
||||||
GitClient *client = GitPlugin::instance()->client();
|
GitClient *client = GitPlugin::instance()->client();
|
||||||
QScopedPointer<VcsCommand> command(client->createCommand(m_directory));
|
QScopedPointer<VcsCommand> command(client->createCommand(m_directory));
|
||||||
@@ -166,6 +186,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
FutureInterfaceType m_fi;
|
FutureInterfaceType m_fi;
|
||||||
QString m_directory;
|
QString m_directory;
|
||||||
|
QString m_ref;
|
||||||
const TextEditor::FileFindParameters &m_parameters;
|
const TextEditor::FileFindParameters &m_parameters;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -180,9 +201,21 @@ static bool validateDirectory(const QString &path)
|
|||||||
|
|
||||||
GitGrep::GitGrep()
|
GitGrep::GitGrep()
|
||||||
{
|
{
|
||||||
m_widget = new QCheckBox(tr("&Use Git Grep"));
|
m_widget = new QWidget;
|
||||||
m_widget->setToolTip(tr("Use Git Grep for searching. This includes only files "
|
auto layout = new QHBoxLayout(m_widget);
|
||||||
"that are managed by source control."));
|
layout->setMargin(0);
|
||||||
|
m_enabledCheckBox = new QCheckBox(tr("&Use Git Grep"));
|
||||||
|
m_enabledCheckBox->setToolTip(tr("Use Git Grep for searching. This includes only files "
|
||||||
|
"that are managed by Git."));
|
||||||
|
layout->addWidget(m_enabledCheckBox);
|
||||||
|
m_treeLineEdit = new FancyLineEdit;
|
||||||
|
m_treeLineEdit->setPlaceholderText(
|
||||||
|
tr("Tree: add reference here or leave empty to search through the file system)"));
|
||||||
|
m_treeLineEdit->setToolTip(
|
||||||
|
tr("Reference can be HEAD, tag, local or remote branch, or a commit hash."));
|
||||||
|
const QRegularExpression refExpression(QLatin1String("[\\w/]*"));
|
||||||
|
m_treeLineEdit->setValidator(new QRegularExpressionValidator(refExpression, this));
|
||||||
|
layout->addWidget(m_treeLineEdit);
|
||||||
TextEditor::FindInFiles *findInFiles = TextEditor::FindInFiles::instance();
|
TextEditor::FindInFiles *findInFiles = TextEditor::FindInFiles::instance();
|
||||||
QTC_ASSERT(findInFiles, return);
|
QTC_ASSERT(findInFiles, return);
|
||||||
connect(findInFiles, &TextEditor::FindInFiles::pathChanged,
|
connect(findInFiles, &TextEditor::FindInFiles::pathChanged,
|
||||||
@@ -202,6 +235,14 @@ QString GitGrep::title() const
|
|||||||
return tr("Git Grep");
|
return tr("Git Grep");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString GitGrep::toolTip() const
|
||||||
|
{
|
||||||
|
const QString ref = m_treeLineEdit->text();
|
||||||
|
if (!ref.isEmpty())
|
||||||
|
return tr("Ref: %1\n%2").arg(ref);
|
||||||
|
return QLatin1String("%1");
|
||||||
|
}
|
||||||
|
|
||||||
QWidget *GitGrep::widget() const
|
QWidget *GitGrep::widget() const
|
||||||
{
|
{
|
||||||
return m_widget;
|
return m_widget;
|
||||||
@@ -209,27 +250,32 @@ QWidget *GitGrep::widget() const
|
|||||||
|
|
||||||
bool GitGrep::isEnabled() const
|
bool GitGrep::isEnabled() const
|
||||||
{
|
{
|
||||||
return m_widget->isEnabled() && m_widget->isChecked();
|
return m_widget->isEnabled() && m_enabledCheckBox->isChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GitGrep::isEnabled(const TextEditor::FileFindParameters ¶meters) const
|
bool GitGrep::isEnabled(const TextEditor::FileFindParameters ¶meters) const
|
||||||
{
|
{
|
||||||
return parameters.extensionParameters.toBool();
|
return parameters.extensionParameters.value<GitGrepParameters>().isEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant GitGrep::parameters() const
|
QVariant GitGrep::parameters() const
|
||||||
{
|
{
|
||||||
return isEnabled();
|
GitGrepParameters params;
|
||||||
|
params.isEnabled = isEnabled();
|
||||||
|
params.ref = m_treeLineEdit->text();
|
||||||
|
return qVariantFromValue(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GitGrep::readSettings(QSettings *settings)
|
void GitGrep::readSettings(QSettings *settings)
|
||||||
{
|
{
|
||||||
m_widget->setChecked(settings->value(QLatin1String(EnableGitGrep), false).toBool());
|
m_enabledCheckBox->setChecked(settings->value(QLatin1String(EnableGitGrep), false).toBool());
|
||||||
|
m_treeLineEdit->setText(settings->value(QLatin1String(GitGrepRef)).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GitGrep::writeSettings(QSettings *settings) const
|
void GitGrep::writeSettings(QSettings *settings) const
|
||||||
{
|
{
|
||||||
settings->setValue(QLatin1String(EnableGitGrep), m_widget->isChecked());
|
settings->setValue(QLatin1String(EnableGitGrep), m_enabledCheckBox->isChecked());
|
||||||
|
settings->setValue(QLatin1String(GitGrepRef), m_treeLineEdit->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
QFuture<FileSearchResultList> GitGrep::executeSearch(
|
QFuture<FileSearchResultList> GitGrep::executeSearch(
|
||||||
@@ -238,5 +284,37 @@ QFuture<FileSearchResultList> GitGrep::executeSearch(
|
|||||||
return Utils::runAsync(GitGrepRunner::run, parameters);
|
return Utils::runAsync(GitGrepRunner::run, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IEditor *GitGrep::openEditor(const SearchResultItem &item,
|
||||||
|
const TextEditor::FileFindParameters ¶meters)
|
||||||
|
{
|
||||||
|
GitGrepParameters params = parameters.extensionParameters.value<GitGrepParameters>();
|
||||||
|
if (!params.isEnabled || params.ref.isEmpty() || item.path.isEmpty())
|
||||||
|
return nullptr;
|
||||||
|
const QString path = QDir::fromNativeSeparators(item.path.first());
|
||||||
|
QByteArray content;
|
||||||
|
GitClient *client = GitPlugin::instance()->client();
|
||||||
|
const QString topLevel = parameters.additionalParameters.toString();
|
||||||
|
const QString relativePath = QDir(topLevel).relativeFilePath(path);
|
||||||
|
if (!client->synchronousShow(topLevel, params.ref + QLatin1String(":./") + relativePath,
|
||||||
|
&content, nullptr)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (content.isEmpty())
|
||||||
|
return nullptr;
|
||||||
|
QByteArray fileContent;
|
||||||
|
if (TextFileFormat::readFileUTF8(path, 0, &fileContent, 0) == TextFileFormat::ReadSuccess) {
|
||||||
|
if (fileContent == content)
|
||||||
|
return nullptr; // open the file for read/write
|
||||||
|
}
|
||||||
|
QString title = tr("Git Show %1:%2").arg(params.ref).arg(relativePath);
|
||||||
|
IEditor *editor = EditorManager::openEditorWithContents(Id(), &title, content, title,
|
||||||
|
EditorManager::DoNotSwitchToDesignMode);
|
||||||
|
editor->gotoLine(item.lineNumber, item.textMarkPos);
|
||||||
|
editor->document()->setTemporary(true);
|
||||||
|
return editor;
|
||||||
|
}
|
||||||
|
|
||||||
} // Internal
|
} // Internal
|
||||||
} // Git
|
} // Git
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(Git::Internal::GitGrepParameters)
|
||||||
|
|||||||
@@ -28,10 +28,12 @@
|
|||||||
|
|
||||||
#include <texteditor/basefilefind.h>
|
#include <texteditor/basefilefind.h>
|
||||||
|
|
||||||
#include <utils/fileutils.h>
|
#include <QCoreApplication>
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QCheckBox)
|
QT_FORWARD_DECLARE_CLASS(QCheckBox)
|
||||||
|
|
||||||
|
namespace Utils { class FancyLineEdit; }
|
||||||
|
|
||||||
namespace Git {
|
namespace Git {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -43,6 +45,7 @@ public:
|
|||||||
GitGrep();
|
GitGrep();
|
||||||
~GitGrep() override;
|
~GitGrep() override;
|
||||||
QString title() const override;
|
QString title() const override;
|
||||||
|
QString toolTip() const override;
|
||||||
QWidget *widget() const override;
|
QWidget *widget() const override;
|
||||||
bool isEnabled() const override;
|
bool isEnabled() const override;
|
||||||
bool isEnabled(const TextEditor::FileFindParameters ¶meters) const override;
|
bool isEnabled(const TextEditor::FileFindParameters ¶meters) const override;
|
||||||
@@ -51,9 +54,13 @@ public:
|
|||||||
void writeSettings(QSettings *settings) const override;
|
void writeSettings(QSettings *settings) const override;
|
||||||
QFuture<Utils::FileSearchResultList> executeSearch(
|
QFuture<Utils::FileSearchResultList> executeSearch(
|
||||||
const TextEditor::FileFindParameters ¶meters) override;
|
const TextEditor::FileFindParameters ¶meters) override;
|
||||||
|
Core::IEditor *openEditor(const Core::SearchResultItem &item,
|
||||||
|
const TextEditor::FileFindParameters ¶meters) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QCheckBox *m_widget;
|
QWidget *m_widget;
|
||||||
|
QCheckBox *m_enabledCheckBox;
|
||||||
|
Utils::FancyLineEdit *m_treeLineEdit;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -140,8 +140,11 @@ void BaseFileFind::runNewSearch(const QString &txt, FindFlags findFlags,
|
|||||||
d->m_currentFindSupport = 0;
|
d->m_currentFindSupport = 0;
|
||||||
if (d->m_filterCombo)
|
if (d->m_filterCombo)
|
||||||
updateComboEntries(d->m_filterCombo, true);
|
updateComboEntries(d->m_filterCombo, true);
|
||||||
|
QString tooltip = toolTip();
|
||||||
|
if (d->m_extension)
|
||||||
|
tooltip = tooltip.arg(d->m_extension->toolTip());
|
||||||
SearchResult *search = SearchResultWindow::instance()->startNewSearch(label(),
|
SearchResult *search = SearchResultWindow::instance()->startNewSearch(label(),
|
||||||
toolTip().arg(IFindFilter::descriptionForFindFlags(findFlags)),
|
tooltip.arg(IFindFilter::descriptionForFindFlags(findFlags)),
|
||||||
txt, searchMode, SearchResultWindow::PreserveCaseEnabled,
|
txt, searchMode, SearchResultWindow::PreserveCaseEnabled,
|
||||||
QString::fromLatin1("TextEditor"));
|
QString::fromLatin1("TextEditor"));
|
||||||
search->setTextToReplace(txt);
|
search->setTextToReplace(txt);
|
||||||
@@ -320,7 +323,11 @@ void BaseFileFind::updateComboEntries(QComboBox *combo, bool onTop)
|
|||||||
void BaseFileFind::openEditor(const SearchResultItem &item)
|
void BaseFileFind::openEditor(const SearchResultItem &item)
|
||||||
{
|
{
|
||||||
SearchResult *result = qobject_cast<SearchResult *>(sender());
|
SearchResult *result = qobject_cast<SearchResult *>(sender());
|
||||||
|
FileFindParameters parameters = result->userData().value<FileFindParameters>();
|
||||||
IEditor *openedEditor = 0;
|
IEditor *openedEditor = 0;
|
||||||
|
if (d->m_extension)
|
||||||
|
openedEditor = d->m_extension->openEditor(item, parameters);
|
||||||
|
if (!openedEditor) {
|
||||||
if (item.path.size() > 0) {
|
if (item.path.size() > 0) {
|
||||||
openedEditor = EditorManager::openEditorAt(QDir::fromNativeSeparators(item.path.first()),
|
openedEditor = EditorManager::openEditorAt(QDir::fromNativeSeparators(item.path.first()),
|
||||||
item.lineNumber,
|
item.lineNumber,
|
||||||
@@ -329,6 +336,7 @@ void BaseFileFind::openEditor(const SearchResultItem &item)
|
|||||||
} else {
|
} else {
|
||||||
openedEditor = EditorManager::openEditor(QDir::fromNativeSeparators(item.text));
|
openedEditor = EditorManager::openEditor(QDir::fromNativeSeparators(item.text));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (d->m_currentFindSupport)
|
if (d->m_currentFindSupport)
|
||||||
d->m_currentFindSupport->clearHighlights();
|
d->m_currentFindSupport->clearHighlights();
|
||||||
d->m_currentFindSupport = 0;
|
d->m_currentFindSupport = 0;
|
||||||
@@ -336,13 +344,10 @@ void BaseFileFind::openEditor(const SearchResultItem &item)
|
|||||||
return;
|
return;
|
||||||
// highlight results
|
// highlight results
|
||||||
if (IFindSupport *findSupport = Aggregation::query<IFindSupport>(openedEditor->widget())) {
|
if (IFindSupport *findSupport = Aggregation::query<IFindSupport>(openedEditor->widget())) {
|
||||||
if (result) {
|
|
||||||
FileFindParameters parameters = result->userData().value<FileFindParameters>();
|
|
||||||
d->m_currentFindSupport = findSupport;
|
d->m_currentFindSupport = findSupport;
|
||||||
d->m_currentFindSupport->highlightAll(parameters.text, parameters.flags);
|
d->m_currentFindSupport->highlightAll(parameters.text, parameters.flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void BaseFileFind::hideHighlightAll(bool visible)
|
void BaseFileFind::hideHighlightAll(bool visible)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,9 +41,10 @@ QT_END_NAMESPACE
|
|||||||
|
|
||||||
namespace Utils { class FileIterator; }
|
namespace Utils { class FileIterator; }
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
class IEditor;
|
||||||
|
class IFindSupport;
|
||||||
class SearchResult;
|
class SearchResult;
|
||||||
class SearchResultItem;
|
class SearchResultItem;
|
||||||
class IFindSupport;
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|
||||||
namespace TextEditor {
|
namespace TextEditor {
|
||||||
@@ -65,6 +66,7 @@ class TEXTEDITOR_EXPORT FileFindExtension : public QObject
|
|||||||
public:
|
public:
|
||||||
virtual ~FileFindExtension() {}
|
virtual ~FileFindExtension() {}
|
||||||
virtual QString title() const = 0;
|
virtual QString title() const = 0;
|
||||||
|
virtual QString toolTip() const = 0; // add %1 placeholder where the find flags should be put
|
||||||
virtual QWidget *widget() const = 0;
|
virtual QWidget *widget() const = 0;
|
||||||
virtual bool isEnabled() const = 0;
|
virtual bool isEnabled() const = 0;
|
||||||
virtual bool isEnabled(const FileFindParameters ¶meters) const = 0;
|
virtual bool isEnabled(const FileFindParameters ¶meters) const = 0;
|
||||||
@@ -73,6 +75,8 @@ public:
|
|||||||
virtual void writeSettings(QSettings *settings) const = 0;
|
virtual void writeSettings(QSettings *settings) const = 0;
|
||||||
virtual QFuture<Utils::FileSearchResultList> executeSearch(
|
virtual QFuture<Utils::FileSearchResultList> executeSearch(
|
||||||
const FileFindParameters ¶meters) = 0;
|
const FileFindParameters ¶meters) = 0;
|
||||||
|
virtual Core::IEditor *openEditor(const Core::SearchResultItem &item,
|
||||||
|
const FileFindParameters ¶meters) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TEXTEDITOR_EXPORT BaseFileFind : public Core::IFindFilter
|
class TEXTEDITOR_EXPORT BaseFileFind : public Core::IFindFilter
|
||||||
|
|||||||
Reference in New Issue
Block a user