forked from OSchip/llvm-project
[clangd] Introduce bulletlists
Reviewers: sammccall Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D71422
This commit is contained in:
parent
e34801c8e6
commit
a000f2e53f
|
@ -149,6 +149,21 @@ private:
|
|||
std::string Contents;
|
||||
std::string Language;
|
||||
};
|
||||
|
||||
// Inserts two spaces after each `\n` to indent each line. First line is not
|
||||
// indented.
|
||||
std::string indentLines(llvm::StringRef Input) {
|
||||
assert(!Input.endswith("\n") && "Input should've been trimmed.");
|
||||
std::string IndentedR;
|
||||
// We'll add 2 spaces after each new line.
|
||||
IndentedR.reserve(Input.size() + Input.count('\n') * 2);
|
||||
for (char C : Input) {
|
||||
IndentedR += C;
|
||||
if (C == '\n')
|
||||
IndentedR.append(" ");
|
||||
}
|
||||
return IndentedR;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::string Block::asMarkdown() const {
|
||||
|
@ -193,6 +208,24 @@ void Paragraph::renderPlainText(llvm::raw_ostream &OS) const {
|
|||
OS << '\n';
|
||||
}
|
||||
|
||||
void BulletList::renderMarkdown(llvm::raw_ostream &OS) const {
|
||||
for (auto &D : Items) {
|
||||
// Instead of doing this we might prefer passing Indent to children to get
|
||||
// rid of the copies, if it turns out to be a bottleneck.
|
||||
OS << "- " << indentLines(D.asMarkdown()) << '\n';
|
||||
}
|
||||
// We need a new line after list to terminate it in markdown.
|
||||
OS << '\n';
|
||||
}
|
||||
|
||||
void BulletList::renderPlainText(llvm::raw_ostream &OS) const {
|
||||
for (auto &D : Items) {
|
||||
// Instead of doing this we might prefer passing Indent to children to get
|
||||
// rid of the copies, if it turns out to be a bottleneck.
|
||||
OS << "- " << indentLines(D.asPlainText()) << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
Paragraph &Paragraph::appendText(std::string Text) {
|
||||
Text = canonicalizeSpaces(std::move(Text));
|
||||
if (Text.empty())
|
||||
|
@ -215,6 +248,11 @@ Paragraph &Paragraph::appendCode(std::string Code) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
class Document &BulletList::addItem() {
|
||||
Items.emplace_back();
|
||||
return Items.back();
|
||||
}
|
||||
|
||||
Paragraph &Document::addParagraph() {
|
||||
Children.push_back(std::make_unique<Paragraph>());
|
||||
return *static_cast<Paragraph *>(Children.back().get());
|
||||
|
@ -234,6 +272,11 @@ std::string Document::asMarkdown() const {
|
|||
std::string Document::asPlainText() const {
|
||||
return renderBlocks(Children, &Block::renderPlainText);
|
||||
}
|
||||
|
||||
BulletList &Document::addBulletList() {
|
||||
Children.emplace_back(std::make_unique<BulletList>());
|
||||
return *static_cast<BulletList *>(Children.back().get());
|
||||
}
|
||||
} // namespace markup
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
|
|
@ -62,6 +62,19 @@ private:
|
|||
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(llvm::raw_ostream &OS) const override;
|
||||
void renderPlainText(llvm::raw_ostream &OS) 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 {
|
||||
|
@ -74,13 +87,16 @@ public:
|
|||
/// text representation, the code block will be surrounded by newlines.
|
||||
void addCodeBlock(std::string Code, std::string Language = "cpp");
|
||||
|
||||
BulletList &addBulletList();
|
||||
|
||||
/// Doesn't contain any trailing newlines.
|
||||
std::string asMarkdown() const;
|
||||
/// Doesn't contain any trailing newlines.
|
||||
std::string asPlainText() const;
|
||||
|
||||
private:
|
||||
std::vector<std::unique_ptr<Block>> Children;
|
||||
};
|
||||
|
||||
} // namespace markup
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
|
|
@ -186,6 +186,71 @@ foo)pt";
|
|||
EXPECT_EQ(D.asPlainText(), ExpectedPlainText);
|
||||
}
|
||||
|
||||
TEST(BulletList, Render) {
|
||||
BulletList L;
|
||||
// Flat list
|
||||
L.addItem().addParagraph().appendText("foo");
|
||||
EXPECT_EQ(L.asMarkdown(), "- foo");
|
||||
EXPECT_EQ(L.asPlainText(), "- foo");
|
||||
|
||||
L.addItem().addParagraph().appendText("bar");
|
||||
EXPECT_EQ(L.asMarkdown(), R"md(- foo
|
||||
- bar)md");
|
||||
EXPECT_EQ(L.asPlainText(), R"pt(- foo
|
||||
- bar)pt");
|
||||
|
||||
// Nested list, with a single item.
|
||||
Document &D = L.addItem();
|
||||
// First item with foo\nbaz
|
||||
D.addParagraph().appendText("foo");
|
||||
D.addParagraph().appendText("baz");
|
||||
|
||||
// Nest one level.
|
||||
Document &Inner = D.addBulletList().addItem();
|
||||
Inner.addParagraph().appendText("foo");
|
||||
|
||||
// Nest one more level.
|
||||
BulletList &InnerList = Inner.addBulletList();
|
||||
// Single item, baz\nbaz
|
||||
Document &DeepDoc = InnerList.addItem();
|
||||
DeepDoc.addParagraph().appendText("baz");
|
||||
DeepDoc.addParagraph().appendText("baz");
|
||||
EXPECT_EQ(L.asMarkdown(), R"md(- foo
|
||||
- bar
|
||||
- foo
|
||||
baz
|
||||
- foo
|
||||
- baz
|
||||
baz)md");
|
||||
EXPECT_EQ(L.asPlainText(), R"pt(- foo
|
||||
- bar
|
||||
- foo
|
||||
baz
|
||||
- foo
|
||||
- baz
|
||||
baz)pt");
|
||||
|
||||
// Termination
|
||||
Inner.addParagraph().appendText("after");
|
||||
EXPECT_EQ(L.asMarkdown(), R"md(- foo
|
||||
- bar
|
||||
- foo
|
||||
baz
|
||||
- foo
|
||||
- baz
|
||||
baz
|
||||
|
||||
after)md");
|
||||
EXPECT_EQ(L.asPlainText(), R"pt(- foo
|
||||
- bar
|
||||
- foo
|
||||
baz
|
||||
- foo
|
||||
- baz
|
||||
baz
|
||||
after)pt");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace markup
|
||||
} // namespace clangd
|
||||
|
|
Loading…
Reference in New Issue