1 //===-- Highlighter.h -------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_CORE_HIGHLIGHTER_H
10 #define LLDB_CORE_HIGHLIGHTER_H
11 
12 #include <utility>
13 #include <vector>
14 
15 #include "lldb/Utility/Stream.h"
16 #include "lldb/lldb-enumerations.h"
17 #include "llvm/ADT/StringRef.h"
18 
19 namespace lldb_private {
20 
21 /// Represents style that the highlighter should apply to the given source code.
22 /// Stores information about how every kind of token should be annotated.
23 struct HighlightStyle {
24 
25   /// A pair of strings that should be placed around a certain token. Usually
26   /// stores color codes in these strings (the suffix string is often used for
27   /// resetting the terminal attributes back to normal).
28   class ColorStyle {
29     std::string m_prefix;
30     std::string m_suffix;
31 
32   public:
33     ColorStyle() = default;
34     ColorStyle(llvm::StringRef prefix, llvm::StringRef suffix) {
35       Set(prefix, suffix);
36     }
37 
38     /// Applies this style to the given value.
39     /// \param s
40     ///     The stream to which the result should be appended.
41     /// \param value
42     ///     The value that we should place our strings around.
43     void Apply(Stream &s, llvm::StringRef value) const;
44 
45     /// Sets the prefix and suffix strings.
46     void Set(llvm::StringRef prefix, llvm::StringRef suffix);
47   };
48 
49   /// The style for the token which is below the cursor of the user. Note that
50   /// this style is overwritten by the SourceManager with the values of
51   /// stop-show-column-ansi-prefix/stop-show-column-ansi-suffix.
52   ColorStyle selected;
53 
54   /// Matches identifiers to variable or functions.
55   ColorStyle identifier;
56   /// Matches any string or character literals in the language: "foo" or 'f'
57   ColorStyle string_literal;
58   /// Matches scalar value literals like '42' or '0.1'.
59   ColorStyle scalar_literal;
60   /// Matches all reserved keywords in the language.
61   ColorStyle keyword;
62   /// Matches any comments in the language.
63   ColorStyle comment;
64   /// Matches commas: ','
65   ColorStyle comma;
66   /// Matches one colon: ':'
67   ColorStyle colon;
68   /// Matches any semicolon: ';'
69   ColorStyle semicolons;
70   /// Matches operators like '+', '-', '%', '&', '='
71   ColorStyle operators;
72 
73   /// Matches '{' or '}'
74   ColorStyle braces;
75   /// Matches '[' or ']'
76   ColorStyle square_brackets;
77   /// Matches '(' or ')'
78   ColorStyle parentheses;
79 
80   // C language specific options
81 
82   /// Matches directives to a preprocessor (if the language has any).
83   ColorStyle pp_directive;
84 
85   /// Returns a HighlightStyle that is based on vim's default highlight style.
86   static HighlightStyle MakeVimStyle();
87 };
88 
89 /// Annotates source code with color attributes.
90 class Highlighter {
91 public:
92   Highlighter() = default;
93   virtual ~Highlighter() = default;
94   Highlighter(const Highlighter &) = delete;
95   const Highlighter &operator=(const Highlighter &) = delete;
96 
97   /// Returns a human readable name for the selected highlighter.
98   virtual llvm::StringRef GetName() const = 0;
99 
100   /// Highlights the given line
101   /// \param options
102   ///     The highlight options.
103   /// \param line
104   ///     The user supplied line that needs to be highlighted.
105   /// \param cursor_pos
106   ///     The cursor position of the user in this line, starting at 0 (which
107   ///     means the cursor is on the first character in 'line').
108   /// \param previous_lines
109   ///     Any previous lines the user has written which we should only use
110   ///     for getting the context of the Highlighting right.
111   /// \param s
112   ///     The stream to which the highlighted version of the user string should
113   ///     be written.
114   virtual void Highlight(const HighlightStyle &options, llvm::StringRef line,
115                          llvm::Optional<size_t> cursor_pos,
116                          llvm::StringRef previous_lines, Stream &s) const = 0;
117 
118   /// Utility method for calling Highlight without a stream.
119   std::string Highlight(const HighlightStyle &options, llvm::StringRef line,
120                         llvm::Optional<size_t> cursor_pos,
121                         llvm::StringRef previous_lines = "") const;
122 };
123 
124 /// A default highlighter that only highlights the user cursor, but doesn't
125 /// do any other highlighting.
126 class DefaultHighlighter : public Highlighter {
127 public:
128   llvm::StringRef GetName() const override { return "none"; }
129 
130   void Highlight(const HighlightStyle &options, llvm::StringRef line,
131                  llvm::Optional<size_t> cursor_pos,
132                  llvm::StringRef previous_lines, Stream &s) const override;
133 };
134 
135 /// Manages the available highlighters.
136 class HighlighterManager {
137   DefaultHighlighter m_default;
138 
139 public:
140   /// Queries all known highlighter for one that can highlight some source code.
141   /// \param language_type
142   ///     The language type that the caller thinks the source code was given in.
143   /// \param path
144   ///     The path to the file the source code is from. Used as a fallback when
145   ///     the user can't provide a language.
146   /// \return
147   ///     The highlighter that wants to highlight the source code. Could be an
148   ///     empty highlighter that does nothing.
149   const Highlighter &getHighlighterFor(lldb::LanguageType language_type,
150                                        llvm::StringRef path) const;
151   const Highlighter &getDefaultHighlighter() const { return m_default; }
152 };
153 
154 } // namespace lldb_private
155 
156 #endif // LLDB_CORE_HIGHLIGHTER_H
157