132 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
//===--- Markup.h -------------------------------------------*- C++-*------===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// A model of formatted text that can be rendered to plaintext or markdown.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_MARKUP_H
 | 
						|
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_MARKUP_H
 | 
						|
 | 
						|
#include "llvm/Support/raw_ostream.h"
 | 
						|
#include <cstddef>
 | 
						|
#include <memory>
 | 
						|
#include <string>
 | 
						|
#include <vector>
 | 
						|
 | 
						|
namespace clang {
 | 
						|
namespace clangd {
 | 
						|
namespace markup {
 | 
						|
 | 
						|
/// Holds text and knows how to lay it out. Multiple blocks can be grouped to
 | 
						|
/// form a document. Blocks include their own trailing newlines, container
 | 
						|
/// should trim them if need be.
 | 
						|
class Block {
 | 
						|
public:
 | 
						|
  virtual void renderMarkdown(llvm::raw_ostream &OS) const = 0;
 | 
						|
  virtual void renderPlainText(llvm::raw_ostream &OS) const = 0;
 | 
						|
  virtual std::unique_ptr<Block> clone() const = 0;
 | 
						|
  std::string asMarkdown() const;
 | 
						|
  std::string 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(llvm::raw_ostream &OS) const override;
 | 
						|
  void renderPlainText(llvm::raw_ostream &OS) const override;
 | 
						|
  std::unique_ptr<Block> clone() const override;
 | 
						|
 | 
						|
  /// Append plain text to the end of the string.
 | 
						|
  Paragraph &appendText(llvm::StringRef 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(llvm::StringRef 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 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(llvm::raw_ostream &OS) const override;
 | 
						|
  void renderPlainText(llvm::raw_ostream &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(const Document &Other) { *this = Other; }
 | 
						|
  Document &operator=(const Document &);
 | 
						|
  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 Code, std::string 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 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
 | 
						|
 | 
						|
#endif
 |