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