blob: 07fef158973c5486ef014497ced390d6ed2ab256 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#pragma once
#include <cctype>
#include <clocale>
#include <cstddef>
#include <memory>
#include <string>
#include <vector>
#include <sstream>
#include "string_ref.h"
namespace lsp
{
/// Holds text and knows how to lay it out. Multiple blocks can be grouped to
/// form a document. Blocks include their own trailing newlines, std::string_ref
/// should trim them if need be.
class Block
{
public:
virtual void renderMarkdown(std::ostringstream& OS) const = 0;
virtual void renderPlainText(std::ostringstream& OS) const = 0;
virtual std::unique_ptr<Block> clone() const = 0;
std::string_ref asMarkdown() const;
std::string_ref asPlainText() const;
virtual bool isRuler() const
{
return false;
}
virtual ~Block() = default;
};
/// Represents parts of the markup that can contain strings, like inline code,
/// code block or plain text.
/// One must introduce different paragraphs to create separate blocks.
class Paragraph : public Block
{
public:
void renderMarkdown(std::ostringstream& OS) const override;
void renderPlainText(std::ostringstream& OS) const override;
std::unique_ptr<Block> clone() const override;
/// Append plain text to the end of the string.
Paragraph& appendText(std::string_ref const& Text);
/// Append inline code, this translates to the ` block in markdown.
/// \p Preserve indicates the code span must be apparent even in plaintext.
Paragraph& appendCode(std::string_ref const& Code, bool Preserve = false);
/// Ensure there is space between the surrounding chunks.
/// Has no effect at the beginning or end of a paragraph.
Paragraph& appendSpace();
private:
struct Chunk
{
enum
{
PlainText,
InlineCode,
} Kind = PlainText;
// Preserve chunk markers in plaintext.
bool Preserve = false;
std::string_ref Contents;
// Whether this chunk should be surrounded by whitespace.
// Consecutive SpaceAfter and SpaceBefore will be collapsed into one space.
// Code spans don't usually set this: their spaces belong "inside" the span.
bool SpaceBefore = false;
bool SpaceAfter = false;
};
std::vector<Chunk> Chunks;
};
/// Represents a sequence of one or more documents. Knows how to print them in a
/// list like format, e.g. by prepending with "- " and indentation.
class BulletList : public Block
{
public:
void renderMarkdown(std::ostringstream& OS) const override;
void renderPlainText(std::ostringstream& OS) const override;
std::unique_ptr<Block> clone() const override;
class Document& addItem();
private:
std::vector<class Document> Items;
};
/// A format-agnostic representation for structured text. Allows rendering into
/// markdown and plaintext.
class Document
{
public:
Document() = default;
Document(Document const& Other)
{
*this = Other;
}
Document& operator=(Document const&);
Document(Document&&) = default;
Document& operator=(Document&&) = default;
void append(Document Other);
/// Adds a semantical block that will be separate from others.
Paragraph& addParagraph();
/// Inserts a horizontal separator to the document.
void addRuler();
/// Adds a block of code. This translates to a ``` block in markdown. In plain
/// text representation, the code block will be surrounded by newlines.
void addCodeBlock(std::string_ref Code, std::string_ref Language = "cpp");
/// Heading is a special type of paragraph that will be prepended with \p
/// Level many '#'s in markdown.
Paragraph& addHeading(size_t Level);
BulletList& addBulletList();
/// Doesn't contain any trailing newlines.
/// We try to make the markdown human-readable, e.g. avoid extra escaping.
/// At least one client (coc.nvim) displays the markdown verbatim!
std::string_ref asMarkdown() const;
/// Doesn't contain any trailing newlines.
std::string_ref asPlainText() const;
private:
std::vector<std::unique_ptr<Block>> Children;
};
} // namespace lsp
|