// Copyright (C) 2017 xaizek <xaizek@posteo.net>
//
// This file is part of zograscope.
//
// zograscope is free software: you can redistribute it and/or modify
// it under the terms of version 3 of the GNU Affero General Public License as
// published by the Free Software Foundation.
//
// zograscope is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with zograscope. If not, see <http://www.gnu.org/licenses/>.
#ifndef ZOGRASCOPE_HIGHLIGHTER_HPP_
#define ZOGRASCOPE_HIGHLIGHTER_HPP_
#include <cstdint>
#include <memory>
#include <stack>
#include <unordered_map>
#include <vector>
#include <boost/utility/string_ref.hpp>
#include "ColorCane.hpp"
enum class State : std::uint8_t;
class Language;
class Node;
class Tree;
// Tree highlighter. Highlights either all at once or by line ranges.
class Highlighter
{
class ColorPicker;
// Single processing entry.
struct Entry
{
const Node *node; // Node to be processed.
bool moved; // Move status override for descendants.
State state; // State override for descendants.
bool propagateMoved; // Moved field should be passed to all descendants.
bool propagateState; // State field should be passed to all descendants.
};
public:
// Stores arguments for future reference. The original flag specifies
// whether this is an old version of a file (matters only for trees marked
// with results of comparison).
Highlighter(const Tree &tree, bool original = true);
// Tree can't be a temporary.
Highlighter(Tree &&tree, bool original = true) = delete;
// Stores arguments for future reference. The original flag specifies
// whether this is an old version of a file (matters only for trees marked
// with results of comparison).
Highlighter(const Node &root, const Language &lang, bool original = true,
int lineOffset = 1);
// No copying.
Highlighter(const Highlighter&) = delete;
// No assigning.
Highlighter & operator=(const Highlighter&) = delete;
// Destructs the highlighter.
virtual ~Highlighter();
private:
// Common implementation of two public constructors.
Highlighter(const Node &root, const Language &lang, bool original,
int lineOffset, int colOffset);
public:
// Specifies whether nodes should be labeled with references to identify
// matching pairs in both trees. Off by default.
void setPrintReferences(bool print);
// Specifies whether diffed updated identifiers should be enclosed in
// brackets. On by default.
void setPrintBrackets(bool print);
// Specifies whether unchanged parts diffables should have their original
// color. If not, they are colored as `PieceUpdated`. On by default.
void setTransparentDiffables(bool transparent);
// Prints lines in the range [from, from + n). Each line can be printed at
// most once, thus calls to this function need to increase `from` argument.
ColorCane print(int from, int n);
// Prints lines until the end.
ColorCane print();
private:
// Skips everything until target line is reached.
void skipUntil(int targetLine);
// Prints at most `n` lines.
void print(int n);
// Prints lines of spelling decreasing `n` on advancing through lines.
void printSpelling(int &n);
// Retrieves the next entry to be processed.
Entry getEntry();
// Advances processing to the next node. The entry here is the one that was
// returned by `getEntry()` earlier.
void advance(const Entry &entry);
// Formats spelling of a node into a colored string.
ColorCane getSpelling(const Entry &entry);
// Diffs labels of two nodes (specified one and its relative).
ColorCane diffSpelling(const Node &node, bool moved);
private:
const Language ⟨ // Language services.
ColorCane colorCane; // Temporary output buffer.
int line, col; // Current position.
int colOffset; // Horizontal offset.
std::unique_ptr<ColorPicker> colorPicker; // Highlighting state.
std::vector<boost::string_ref> olines; // Undiffed spelling.
std::vector<ColorCane> lines; // Possibly diffed spelling.
std::stack<Entry> toProcess; // State of tree traversal.
bool original; // Whether this is an old version.
const Node *current; // Node that's being processed.
std::unordered_map<const Node *, // Maps original updated node to
int> updates; // its id among all updated nodes.
bool printReferences; // Label nodes with pair ids.
bool printBrackets; // Bracket diffed identifiers.
bool transparentDiffables; // Leave unchanged parts of
// diffables with original color.
};
#endif // ZOGRASCOPE_HIGHLIGHTER_HPP_
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