Skip to content

Commit cce45e6

Browse files
committed
feat: support for ANSI color sequences(#338)
1 parent fe81965 commit cce45e6

File tree

12 files changed

+1091
-9
lines changed

12 files changed

+1091
-9
lines changed

src/settings/include/configuration.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,15 @@ class Configuration final : public Persistable<Configuration> {
491491
hideAnsiColorSequences_ = hide;
492492
}
493493

494+
bool displayAnsiColorSequences() const
495+
{
496+
return displayAnsiColorSequences_;
497+
}
498+
void setDisplayAnsiColorSequences( bool display )
499+
{
500+
displayAnsiColorSequences_ = display;
501+
}
502+
494503
int defaultEncodingMib() const
495504
{
496505
return defaultEncodingMib_;
@@ -500,7 +509,8 @@ class Configuration final : public Persistable<Configuration> {
500509
defaultEncodingMib_ = mib;
501510
}
502511

503-
std::map<QString, QString> darkPalette() const {
512+
std::map<QString, QString> darkPalette() const
513+
{
504514
return darkPalette_;
505515
}
506516

@@ -581,6 +591,7 @@ class Configuration final : public Persistable<Configuration> {
581591
bool optimizeForNotLatinEncodings_ = false;
582592

583593
bool hideAnsiColorSequences_ = false;
594+
bool displayAnsiColorSequences_ = false;
584595

585596
int defaultEncodingMib_ = -1;
586597

src/settings/src/configuration.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ void Configuration::retrieveFromStorage( QSettings& settings )
261261
= settings
262262
.value( "view.hideAnsiColorSequences", DefaultConfiguration.hideAnsiColorSequences_ )
263263
.toBool();
264+
displayAnsiColorSequences_ = settings
265+
.value( "view.displayAnsiColorSequences",
266+
DefaultConfiguration.displayAnsiColorSequences_ )
267+
.toBool();
264268

265269
useTextWrap_ = settings.value( "view.textWrap", DefaultConfiguration.useTextWrap() ).toBool();
266270

@@ -300,7 +304,7 @@ void Configuration::retrieveFromStorage( QSettings& settings )
300304
const auto mapping = settings.value( "shortcuts.mapping" ).toMap();
301305
for ( auto keys = mapping.begin(); keys != mapping.end(); ++keys ) {
302306
auto action = keys.key().toStdString();
303-
if (action == ShortcutAction::LogViewJumpToButtom) {
307+
if ( action == ShortcutAction::LogViewJumpToButtom ) {
304308
action = ShortcutAction::LogViewJumpToBottom;
305309
}
306310
shortcuts_.emplace( action, keys.value().toStringList() );
@@ -314,7 +318,7 @@ void Configuration::retrieveFromStorage( QSettings& settings )
314318
settings.setArrayIndex( static_cast<int>( shortcutIndex ) );
315319
auto action = settings.value( "action", "" ).toString();
316320
if ( !action.isEmpty() ) {
317-
if (action == ShortcutAction::LogViewJumpToButtom) {
321+
if ( action == ShortcutAction::LogViewJumpToButtom ) {
318322
action = ShortcutAction::LogViewJumpToBottom;
319323
}
320324
const auto keys = settings.value( "keys", QStringList() ).toStringList();
@@ -395,6 +399,7 @@ void Configuration::saveToStorage( QSettings& settings ) const
395399
settings.setValue( "view.scaleFactorRounding", scaleFactorRounding_ );
396400

397401
settings.setValue( "view.hideAnsiColorSequences", hideAnsiColorSequences_ );
402+
settings.setValue( "view.displayAnsiColorSequences", displayAnsiColorSequences_ );
398403

399404
settings.setValue( "defaultView.searchAutoRefresh", searchAutoRefresh_ );
400405
settings.setValue( "defaultView.searchIgnoreCase", searchIgnoreCase_ );

src/ui/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ add_library(
4646
${CMAKE_CURRENT_SOURCE_DIR}/include/decompressor.h
4747
${CMAKE_CURRENT_SOURCE_DIR}/include/fontutils.h
4848
${CMAKE_CURRENT_SOURCE_DIR}/include/colorlabelsmanager.h
49+
${CMAKE_CURRENT_SOURCE_DIR}/include/ANSI.h
50+
${CMAKE_CURRENT_SOURCE_DIR}/include/SGRParser.h
51+
${CMAKE_CURRENT_SOURCE_DIR}/include/ColorfulTextParser.h
4952
${CMAKE_CURRENT_SOURCE_DIR}/include/highlighteredit.ui
5053
${CMAKE_CURRENT_SOURCE_DIR}/include/highlightersetedit.ui
5154
${CMAKE_CURRENT_SOURCE_DIR}/include/highlightersdialog.ui
@@ -91,6 +94,8 @@ add_library(
9194
${CMAKE_CURRENT_SOURCE_DIR}/src/downloader.cpp
9295
${CMAKE_CURRENT_SOURCE_DIR}/src/decompressor.cpp
9396
${CMAKE_CURRENT_SOURCE_DIR}/src/colorlabelsmanager.cpp
97+
${CMAKE_CURRENT_SOURCE_DIR}/src/SGRParser.cpp
98+
${CMAKE_CURRENT_SOURCE_DIR}/src/ColorfulTextParser.cpp
9499
)
95100

96101
set_target_properties(klogg_ui PROPERTIES AUTOUIC ON)

src/ui/include/ANSI.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//
2+
// Created by marvin on 23-7-18.
3+
//
4+
#pragma once
5+
6+
#include <cstdint>
7+
8+
namespace ANSI {
9+
10+
enum SequenceStartCnt {
11+
HEAD_CNT = 2,
12+
};
13+
14+
// reference: https://www.ecma-international.org/publications-and-standards/standards/ecma-48/
15+
enum SequenceFirst {
16+
EXC = 0x1B, // Escape(转义)
17+
};
18+
19+
// reference: https://www.ecma-international.org/publications-and-standards/standards/ecma-48/
20+
enum SequenceSecond {
21+
PAD = 0x40, // 0x80 Padding Character(填充字符)
22+
HOP = 0x41, // 0x81 High Octet Preset(高字节前置)
23+
BPH = 0x42, // 0x82 Break Permitted Here(此处允许中断)
24+
NBH = 0x43, // 0x83 No Break Here(此处禁止中断)
25+
IND = 0x44, // 0x84 Index(索引)
26+
NEL = 0x45, // 0x85 Next Line(下一行)
27+
SSA = 0x46, // 0x86 Start of Selected Area(选择区域开始)
28+
ESA = 0x47, // 0x87 End of Selected Area(选择区域结束)
29+
HTS = 0x48, // 0x88 Horizontal Tab Set(水平制表设置)
30+
HTJ = 0x49, // 0x89 Horizontal Tab Justified(水平制表调整)
31+
VTS = 0x4A, // 0x8A Vertical Tab Set(垂直制表设置)
32+
PLD = 0x4B, // 0x8B Partial Line Forward(部分行前移)
33+
PLU = 0x4C, // 0x8C Partial Line Backward(部分行后移)
34+
RI = 0x4D, // 0x8D Reverse Line Feed(逆向馈行)
35+
SS2 = 0x4E, // 0x8E Single-Shift 2(单个移动2)
36+
SS3 = 0x4F, // 0x8F Single-Shift 3(单个移动3)
37+
DCS = 0x50, // 0x90 Device Control String(设备控制串)
38+
PU1 = 0x51, // 0x91 Private Use 1(私用1)
39+
PU2 = 0x52, // 0x92 Private Use 2(私用2)
40+
STS = 0x53, // 0x93 Set Transmit State(发送规则设置)
41+
CCH = 0x54, // 0x94 Cancel Character(取消字符)
42+
MW = 0x55, // 0x95 Message Waiting(消息等待)
43+
SPA = 0x56, // 0x96 Start of Protected Area(保护区域开始)
44+
EPA = 0x57, // 0x97 End of Protected Area(保护区域结束)
45+
SOS = 0x58, // 0x98 Start of String(串开始)
46+
SGC = 0x59, // 0x99 Single Graphic Char Intro(单个图形字符描述)
47+
SCI = 0x5A, // 0x9A Single Char Intro(单个字符描述)
48+
CSI = 0x5B, // 0x9B Control Sequence Intro(控制顺序描述)
49+
ST = 0x5C, // 0x9C String Terminator(串终止)
50+
OSC = 0x5D, // 0x9D OS Command(操作系统指令)
51+
PM = 0x5E, // 0x9E Private Message(私讯)
52+
APC = 0x5F, // 0x9F App Program Command(应用程序命令)
53+
54+
SECOND_BYTE_BEGIN = PAD,
55+
SECOND_BYTE_END = APC,
56+
};
57+
58+
// reference: https://www.ecma-international.org/publications-and-standards/standards/ecma-48/
59+
enum CSIParameterBytes {
60+
// ASCII: 0–9:;<=>?
61+
NUM_BEGIN = 0x30,
62+
NUM_END = 0x39,
63+
SUB_PARA_SEPARATOR = 0x3A,
64+
PARA_SEPARATOR = 0x3B,
65+
STANDARDIZATION_KEEP_BEGIN = 0x3C,
66+
STANDARDIZATION_KEEP_END = 0x3F,
67+
68+
CSI_PARAMETER_BEGIN = 0x30,
69+
CSI_PARAMETER_END = 0x3F,
70+
};
71+
72+
enum CSIIntermediateBytes {
73+
// ASCII: Space、!"#$%&'()*+,-./
74+
CSIIntermediateBegin = 0x20,
75+
CSIIntermediateEnd = 0x2F,
76+
};
77+
78+
enum CSIFinalBytes {
79+
// ASCII: @A–Z[\]^_`a–z{|}~
80+
SGR = 0x6D, // m
81+
82+
CSIFinalBegin = 0x40,
83+
CSIFinalEnd = 0x7E,
84+
85+
CSIFinalExperimentalBegin = 0x70,
86+
CSIFinalExperimentalEnd = CSIFinalEnd,
87+
};
88+
89+
enum class Return {
90+
PARSE_ERROR = -1,
91+
PARSE_SUCC = 0,
92+
};
93+
94+
} // namespace ANSI
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//
2+
// Created by marvin on 23-7-24.
3+
//
4+
5+
#pragma once
6+
7+
#include <vector>
8+
9+
#include <QString>
10+
11+
#include "SGRParser.h"
12+
#include "highlightedmatch.h"
13+
14+
struct TextColorAttr {
15+
ANSI::Color color;
16+
size_t start;
17+
size_t len;
18+
operator HighlightedMatch();
19+
};
20+
21+
struct ColorfulText {
22+
std::string text;
23+
std::vector<TextColorAttr> color;
24+
};
25+
26+
class CSIFilter {
27+
public:
28+
CSIFilter() = default;
29+
~CSIFilter() = default;
30+
31+
// ANSI: start, data
32+
using SGRSequence = std::pair<size_t, std::string>;
33+
34+
static std::vector<SGRSequence> filter( QString& stdText );
35+
static std::vector<SGRSequence> filter( std::string& stdText );
36+
};
37+
38+
class ColorfulTextParser {
39+
public:
40+
enum class Mode {
41+
MARKED_TEXT,
42+
ALL_TEXT,
43+
};
44+
45+
public:
46+
explicit ColorfulTextParser( const ANSI::TextAttribute& defaultAttr,
47+
const ANSI::TextAttribute& currentAttr );
48+
49+
// QString
50+
ColorfulText parse( QString strings, Mode mode = Mode::ALL_TEXT );
51+
52+
std::vector<ColorfulText> parse( const std::vector<QString>& strings,
53+
Mode mode = Mode::ALL_TEXT );
54+
55+
// std::string
56+
ColorfulText parse( std::string strings, Mode mode = Mode::ALL_TEXT );
57+
58+
std::vector<ColorfulText> parse( const std::vector<std::string>& strings,
59+
Mode mode = Mode::ALL_TEXT );
60+
61+
private:
62+
// std::string
63+
void markedStringToText( std::vector<ColorfulText>& textList,
64+
const std::vector<CSIFilter::SGRSequence>& sgrSeqs,
65+
std::string&& string );
66+
void allStringToText( std::vector<ColorfulText>& textList,
67+
const std::vector<CSIFilter::SGRSequence>& sgrSeqs,
68+
std::string&& string );
69+
70+
private:
71+
ANSI::TextAttribute currentTextAttr_;
72+
ANSI::SGRParser sgrParser_;
73+
};

0 commit comments

Comments
 (0)