mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 02:48:49 +00:00
Implemented syntax highlighter (#220)
* Implemented syntaxHighLighter * removed PseudoWidget.ui * buildfix * reverted r2-submodule * Added nowrap to the pseudocodeWidget * changed color of functions in the pseudocode highlighter
This commit is contained in:
parent
f59e5bbc01
commit
4330b7ddaa
@ -78,6 +78,7 @@ SOURCES += \
|
||||
dialogs/SaveProjectDialog.cpp \
|
||||
utils/TempConfig.cpp \
|
||||
utils/SvgIconEngine.cpp \
|
||||
utils/SyntaxHighlighter.cpp \
|
||||
widgets/PseudocodeWidget.cpp \
|
||||
widgets/VisualNavbar.cpp \
|
||||
widgets/GraphView.cpp \
|
||||
@ -131,6 +132,7 @@ HEADERS += \
|
||||
dialogs/SaveProjectDialog.h \
|
||||
utils/TempConfig.h \
|
||||
utils/SvgIconEngine.h \
|
||||
utils/SyntaxHighlighter.h \
|
||||
widgets/PseudocodeWidget.h \
|
||||
widgets/VisualNavbar.h \
|
||||
widgets/GraphView.h \
|
||||
@ -165,7 +167,6 @@ FORMS += \
|
||||
widgets/SidebarWidget.ui \
|
||||
widgets/HexdumpWidget.ui \
|
||||
dialogs/SaveProjectDialog.ui \
|
||||
widgets/PseudocodeWidget.ui \
|
||||
dialogs/preferences/PreferencesDialog.ui \
|
||||
dialogs/preferences/GeneralOptionsWidget.ui
|
||||
|
||||
|
102
src/utils/SyntaxHighlighter.cpp
Normal file
102
src/utils/SyntaxHighlighter.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include "SyntaxHighlighter.h"
|
||||
|
||||
SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent)
|
||||
: QSyntaxHighlighter(parent)
|
||||
, commentStartExpression("/\\*")
|
||||
, commentEndExpression("\\*/")
|
||||
{
|
||||
HighlightingRule rule;
|
||||
QStringList keywordPatterns;
|
||||
|
||||
//C language keywords
|
||||
keywordPatterns << "\\bauto\\b" << "\\bdouble\\b" << "\\bint\\b"
|
||||
<< "\\bstruct\\b" << "\\bbreak\\b" << "\\belse\\b"
|
||||
<< "\\blong\\b" << "\\switch\\b" << "\\bcase\\b"
|
||||
<< "\\benum\\b" << "\\bregister\\b" << "\\btypedef\\b"
|
||||
<< "\\bchar\\b" << "\\bextern\\b" << "\\breturn\\b"
|
||||
<< "\\bunion\\b" << "\\bconst\\b" << "\\bfloat\\b"
|
||||
<< "\\bshort\\b" << "\\bunsigned\\b" << "\\bcontinue\\b"
|
||||
<< "\\bfor\\b" << "\\bsigned\\b" << "\\bvoid\\b"
|
||||
<< "\\bdefault\\b" << "\\bgoto\\b" << "\\bsizeof\\b"
|
||||
<< "\\bvolatile\\b" << "\\bdo\\b" << "\\bif\\b"
|
||||
<< "\\static\\b" << "\\while\\b";
|
||||
//Special words
|
||||
keywordPatterns << "\\bloc_*\\b" << "\\bsym.*\\b";
|
||||
|
||||
QTextCharFormat keywordFormat;
|
||||
keywordFormat.setForeground(Qt::red);
|
||||
keywordFormat.setFontWeight(QFont::Bold);
|
||||
|
||||
for( const auto& pattern : keywordPatterns )
|
||||
{
|
||||
rule.pattern.setPattern(pattern);
|
||||
rule.format = keywordFormat;
|
||||
highlightingRules.append(rule);
|
||||
}
|
||||
|
||||
//Functions
|
||||
rule.pattern.setPattern("\\b[A-Za-z0-9_]+(?=\\()");
|
||||
rule.format.clearBackground();
|
||||
rule.format.clearForeground();
|
||||
rule.format.setFontItalic(true);
|
||||
rule.format.setForeground(Qt::darkCyan);
|
||||
highlightingRules.append(rule);
|
||||
|
||||
//single-line comment
|
||||
rule.pattern.setPattern("//[^\n]*");
|
||||
rule.format.clearBackground();
|
||||
rule.format.clearForeground();
|
||||
rule.format.setForeground(Qt::gray);
|
||||
highlightingRules.append(rule);
|
||||
|
||||
//quotation
|
||||
rule.pattern.setPattern("\".*\"");
|
||||
rule.format.clearBackground();
|
||||
rule.format.clearForeground();
|
||||
rule.format.setForeground(Qt::darkGreen);
|
||||
highlightingRules.append(rule);
|
||||
|
||||
multiLineCommentFormat.setForeground(Qt::gray);
|
||||
}
|
||||
|
||||
void SyntaxHighlighter::highlightBlock(const QString&text)
|
||||
{
|
||||
for( const auto& it : highlightingRules )
|
||||
{
|
||||
auto matchIterator = it.pattern.globalMatch(text);
|
||||
while (matchIterator.hasNext())
|
||||
{
|
||||
const auto match = matchIterator.next();
|
||||
setFormat(match.capturedStart(), match.capturedLength(), it.format);
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentBlockState(0);
|
||||
|
||||
int startIndex = 0;
|
||||
if (previousBlockState() != 1)
|
||||
{
|
||||
startIndex = text.indexOf(commentStartExpression);
|
||||
}
|
||||
|
||||
while (startIndex >= 0)
|
||||
{
|
||||
const auto match = commentEndExpression.match(text, startIndex);
|
||||
const int endIndex = match.capturedStart();
|
||||
int commentLength = 0;
|
||||
|
||||
if (endIndex == -1)
|
||||
{
|
||||
setCurrentBlockState(1);
|
||||
commentLength = text.length() - startIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
commentLength = endIndex - startIndex
|
||||
+ match.capturedLength();
|
||||
}
|
||||
|
||||
setFormat(startIndex, commentLength, multiLineCommentFormat);
|
||||
startIndex = text.indexOf(commentStartExpression, startIndex + commentLength);
|
||||
}
|
||||
}
|
34
src/utils/SyntaxHighlighter.h
Normal file
34
src/utils/SyntaxHighlighter.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <QSyntaxHighlighter>
|
||||
#include <QVector>
|
||||
#include <QTextDocument>
|
||||
#include <QRegularExpression>
|
||||
#include <QTextCharFormat>
|
||||
|
||||
|
||||
class SyntaxHighlighter : public QSyntaxHighlighter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SyntaxHighlighter(QTextDocument *parent = nullptr);
|
||||
virtual ~SyntaxHighlighter() = default;
|
||||
|
||||
protected:
|
||||
void highlightBlock(const QString &text) override;
|
||||
|
||||
private:
|
||||
struct HighlightingRule
|
||||
{
|
||||
QRegularExpression pattern;
|
||||
QTextCharFormat format;
|
||||
};
|
||||
|
||||
QVector<HighlightingRule> highlightingRules;
|
||||
|
||||
QRegularExpression commentStartExpression;
|
||||
QRegularExpression commentEndExpression;
|
||||
|
||||
QTextCharFormat multiLineCommentFormat;
|
||||
};
|
@ -1,18 +1,23 @@
|
||||
#include "PseudocodeWidget.h"
|
||||
#include "ui_PseudocodeWidget.h"
|
||||
|
||||
#include <QTextEdit>
|
||||
|
||||
#include "utils/Configuration.h"
|
||||
#include "utils/Helpers.h"
|
||||
#include "utils/SyntaxHighlighter.h"
|
||||
#include "utils/TempConfig.h"
|
||||
|
||||
PseudocodeWidget::PseudocodeWidget(QWidget *parent, Qt::WindowFlags flags) :
|
||||
QDockWidget(parent, flags),
|
||||
ui(new Ui::PseudocodeWidget)
|
||||
PseudocodeWidget::PseudocodeWidget(QWidget *parent, Qt::WindowFlags flags)
|
||||
: QDockWidget(parent, flags)
|
||||
, textEditWidget(new QTextEdit(this))
|
||||
, syntaxHighLighter( new SyntaxHighlighter(textEditWidget->document()))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
textEditWidget->setParent(this);
|
||||
setWidget(textEditWidget);
|
||||
setupFonts();
|
||||
colorsUpdatedSlot();
|
||||
textEditWidget->setReadOnly(true);
|
||||
textEditWidget->setLineWrapMode(QTextEdit::NoWrap);
|
||||
|
||||
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdated()));
|
||||
connect(Config(), SIGNAL(colorsUpdated()), this, SLOT(colorsUpdatedSlot()));
|
||||
@ -27,8 +32,6 @@ PseudocodeWidget::PseudocodeWidget(QWidget *parent, Qt::WindowFlags flags) :
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
connect(Core(), SIGNAL(seekChanged(RVA)), this, SLOT(on_seekChanged(RVA)));
|
||||
connect(Core(), SIGNAL(raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType)), this, SLOT(raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType)));
|
||||
connect(this, &QDockWidget::visibilityChanged, this, [](bool visibility) {
|
||||
@ -62,12 +65,13 @@ void PseudocodeWidget::on_seekChanged(RVA addr)
|
||||
|
||||
void PseudocodeWidget::refresh(RVA addr)
|
||||
{
|
||||
QString decompiledCode = Core()->getDecompiledCode(addr);
|
||||
const QString& decompiledCode = Core()->getDecompiledCode(addr);
|
||||
if (decompiledCode.length() == 0)
|
||||
{
|
||||
decompiledCode = tr("Cannot decompile at") + " " + RAddressString(addr) + " " + tr("(Not a function?)");
|
||||
textEditWidget->setText(tr("Cannot decompile at") + " " + RAddressString(addr) + " " + tr("(Not a function?)"));
|
||||
return;
|
||||
}
|
||||
ui->pseudocodeTextBrowser->setText(decompiledCode);
|
||||
textEditWidget->setText(decompiledCode);
|
||||
}
|
||||
|
||||
void PseudocodeWidget::refreshPseudocode()
|
||||
@ -86,7 +90,7 @@ void PseudocodeWidget::raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType
|
||||
void PseudocodeWidget::setupFonts()
|
||||
{
|
||||
QFont font = Config()->getFont();
|
||||
ui->pseudocodeTextBrowser->setFont(font);
|
||||
textEditWidget->setFont(font);
|
||||
}
|
||||
|
||||
void PseudocodeWidget::fontsUpdated()
|
||||
@ -96,8 +100,9 @@ void PseudocodeWidget::fontsUpdated()
|
||||
|
||||
void PseudocodeWidget::colorsUpdatedSlot()
|
||||
{
|
||||
QString styleSheet = QString("QTextBrowser { background-color: %1; color: %2; }")
|
||||
const QString textEditClassName(textEditWidget->metaObject()->className());
|
||||
QString styleSheet = QString(textEditClassName + " { background-color: %1; color: %2; }")
|
||||
.arg(ConfigColor("gui.background").name())
|
||||
.arg(ConfigColor("btext").name());
|
||||
ui->pseudocodeTextBrowser->setStyleSheet(styleSheet);
|
||||
textEditWidget->setStyleSheet(styleSheet);
|
||||
}
|
||||
|
@ -4,13 +4,11 @@
|
||||
#include <QDockWidget>
|
||||
#include <memory>
|
||||
|
||||
#include "ui_PseudocodeWidget.h"
|
||||
#include "cutter.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class PseudocodeWidget;
|
||||
}
|
||||
|
||||
class QTextEdit;
|
||||
class SyntaxHighlighter;
|
||||
|
||||
class PseudocodeWidget : public QDockWidget
|
||||
{
|
||||
@ -21,20 +19,20 @@ public:
|
||||
explicit PseudocodeWidget(QWidget *parent = nullptr, Qt::WindowFlags flags = 0);
|
||||
~PseudocodeWidget();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::PseudocodeWidget> ui;
|
||||
void refresh(RVA addr);
|
||||
void setupFonts();
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void on_seekChanged(RVA addr);
|
||||
void raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type);
|
||||
void fontsUpdated();
|
||||
void colorsUpdatedSlot();
|
||||
void refreshPseudocode();
|
||||
|
||||
private:
|
||||
void refresh(RVA addr);
|
||||
void setupFonts();
|
||||
|
||||
private:
|
||||
QTextEdit* textEditWidget;
|
||||
SyntaxHighlighter* syntaxHighLighter;
|
||||
};
|
||||
|
||||
#endif // PSEUDOCODEWIDGET_H
|
||||
|
@ -1,27 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PseudocodeWidget</class>
|
||||
<widget class="QDockWidget" name="PseudocodeWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>686</width>
|
||||
<height>646</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="toolTipDuration">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<widget class="QTextBrowser" name="pseudocodeTextBrowser">
|
||||
<property name="lineWrapMode">
|
||||
<enum>QTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
Reference in New Issue
Block a user