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