xaizek / zograscope (License: AGPLv3 only) (since 2018-12-07)
Mainly a syntax-aware diff that also provides a number of additional tools.
Commit 45886d9ceff669995726196950e889d0e6a6a798

Color background of moved diffable as moved
Otherwise they stand out among other moved modes.
Author: xaizek
Author date (UTC): 2022-07-19 15:57
Committer name: xaizek
Committer date (UTC): 2022-07-19 17:22
Parent(s): c825d9010621cb3d215c661516cff0e4e14fe648
Signing key: 99DC5E4DB05F6BE2
Tree: f362bddddd97224c94c9c95a1b7911dd770c9c40
File Lines added Lines deleted
src/Highlighter.cpp 15 10
src/Highlighter.hpp 2 2
tests/Printer.cpp 8 8
File src/Highlighter.cpp changed (mode: 100644) (index 58a4057..4b78fad)
... ... Highlighter::skipUntil(int targetLine)
249 249 if (++line == targetLine) { if (++line == targetLine) {
250 250 current = node; current = node;
251 251 colorPicker->advancedLine(); colorPicker->advancedLine();
252 lines = getSpelling(*node, entry.state).splitIntoLines();
252 lines = getSpelling(entry).splitIntoLines();
253 253 olines.erase(olines.begin(), olines.begin() + i); olines.erase(olines.begin(), olines.begin() + i);
254 254 lines.erase(lines.begin(), lines.begin() + i); lines.erase(lines.begin(), lines.begin() + i);
255 255 return; return;
 
... ... Highlighter::print(int n)
299 299
300 300 advance(entry); advance(entry);
301 301
302 lines = getSpelling(*node, entry.state).splitIntoLines();
302 lines = getSpelling(entry).splitIntoLines();
303 303 split(node->spelling, '\n', olines); split(node->spelling, '\n', olines);
304 304 current = node; current = node;
305 305
 
... ... getHighlight(const Node &node, int moved, State state, const Language &lang)
456 456 } }
457 457
458 458 ColorCane ColorCane
459 Highlighter::getSpelling(const Node &node, State state)
459 Highlighter::getSpelling(const Entry &entry)
460 460 { {
461 const bool diffable = isDiffable(node, state, lang);
462 if (!diffable && state != State::Updated) {
461 const Node &node = *entry.node;
462
463 const bool diffable = isDiffable(node, entry.state, lang);
464 if (!diffable && entry.state != State::Updated) {
463 465 ColorCane cc; ColorCane cc;
464 466 cc.append(node.spelling, &node); cc.append(node.spelling, &node);
465 467 return cc; return cc;
 
... ... Highlighter::getSpelling(const Node &node, State state)
467 469
468 470 ColorCane cc; ColorCane cc;
469 471 if (diffable) { if (diffable) {
470 cc = diffSpelling(node);
472 cc = diffSpelling(node, entry.moved);
471 473 } else { } else {
472 474 cc.append(node.spelling, &node, ColorGroup::Updated); cc.append(node.spelling, &node, ColorGroup::Updated);
473 475 } }
 
... ... isDiffable(const Node &node, State state, const Language &lang)
493 495 } }
494 496
495 497 ColorCane ColorCane
496 Highlighter::diffSpelling(const Node &node)
498 Highlighter::diffSpelling(const Node &node, bool moved)
497 499 { {
498 500 // XXX: some kind of caching would be nice since we're doing the same thing // XXX: some kind of caching would be nice since we're doing the same thing
499 501 // for both original and updated nodes. // for both original and updated nodes.
 
... ... Highlighter::diffSpelling(const Node &node)
556 558 }; };
557 559
558 560 // Unchanged parts are highlighted using this color group. // Unchanged parts are highlighted using this color group.
559 ColorGroup def = transparentDiffables || !surround
560 ? ColorGroup::None
561 : ColorGroup::PieceUpdated;
561 ColorGroup def = ColorGroup::None;
562 if (moved) {
563 def = ColorGroup::Moved;
564 } else if (!transparentDiffables && surround) {
565 def = ColorGroup::PieceUpdated;
566 }
562 567
563 568 for (const auto &x : diff.getSes().getSequence()) { for (const auto &x : diff.getSes().getSequence()) {
564 569 switch (x.second.type) { switch (x.second.type) {
File src/Highlighter.hpp changed (mode: 100644) (index 3672e07..f61428f)
... ... private:
108 108 // returned by `getEntry()` earlier. // returned by `getEntry()` earlier.
109 109 void advance(const Entry &entry); void advance(const Entry &entry);
110 110 // Formats spelling of a node into a colored string. // Formats spelling of a node into a colored string.
111 ColorCane getSpelling(const Node &node, State state);
111 ColorCane getSpelling(const Entry &entry);
112 112 // Diffs labels of two nodes (specified one and its relative). // Diffs labels of two nodes (specified one and its relative).
113 ColorCane diffSpelling(const Node &node);
113 ColorCane diffSpelling(const Node &node, bool moved);
114 114
115 115 private: private:
116 116 const Language ⟨ // Language services. const Language ⟨ // Language services.
File tests/Printer.cpp changed (mode: 100644) (index bf7dd22..d0b5c24)
... ... TEST_CASE("Inner diffing does not mess up column tracking", "[printer]")
123 123 REQUIRE(printed == expected); REQUIRE(printed == expected);
124 124 } }
125 125
126 TEST_CASE("Comment contents is not marked as updated on move", "[printer]")
126 TEST_CASE("Comment contents is marked as moved on move", "[printer]")
127 127 { {
128 128 std::string printed = compareAndPrint(parseC( std::string printed = compareAndPrint(parseC(
129 129 R"(void f() { R"(void f() {
 
... ... R"(void f() {
138 138 )"), true); )"), true);
139 139
140 140 std::string expected = normalizeText(R"( std::string expected = normalizeText(R"(
141 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
142 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
143 1 void f() { | 1 void f() {
144 - {+++} 2 {+{+}
145 2 /* {-This-} is bad. */ {#~#} 3 /* {+Failure+} is bad. */
146 - {+++} 4 {+}+}
147 3 } | 5 }
141 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
142 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
143 1 void f() { | 1 void f() {
144 - {+++} 2 {+{+}
145 2 {:/* :}{-This-}{: is bad. */:} {#~#} 3 {:/* :}{+Failure+}{: is bad. */:}
146 - {+++} 4 {+}+}
147 3 } | 5 }
148 148 )"); )");
149 149
150 150 REQUIRE(printed == expected); REQUIRE(printed == expected);
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/zograscope

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/zograscope

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master