xref: /llvm-project/llvm/include/llvm/LineEditor/LineEditor.h (revision e48c7fe49f8575b7737d07ac5a71d1fc924d37f7)
1 //===-- llvm/LineEditor/LineEditor.h - line editor --------------*- 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 LLVM_LINEEDITOR_LINEEDITOR_H
10 #define LLVM_LINEEDITOR_LINEEDITOR_H
11 
12 #include "llvm/ADT/StringRef.h"
13 #include <cstdio>
14 #include <memory>
15 #include <optional>
16 #include <string>
17 #include <utility>
18 #include <vector>
19 
20 namespace llvm {
21 
22 class LineEditor {
23 public:
24   /// Create a LineEditor object.
25   ///
26   /// \param ProgName The name of the current program. Used to form a default
27   /// prompt.
28   /// \param HistoryPath Path to the file in which to store history data, if
29   /// possible.
30   /// \param In The input stream used by the editor.
31   /// \param Out The output stream used by the editor.
32   /// \param Err The error stream used by the editor.
33   LineEditor(StringRef ProgName, StringRef HistoryPath = "", FILE *In = stdin,
34              FILE *Out = stdout, FILE *Err = stderr);
35   ~LineEditor();
36 
37   /// Reads a line.
38   ///
39   /// \return The line, or std::optional<std::string>() on EOF.
40   std::optional<std::string> readLine() const;
41 
42   void saveHistory();
43   void loadHistory();
44   void setHistorySize(int size);
45 
46   static std::string getDefaultHistoryPath(StringRef ProgName);
47 
48   /// The action to perform upon a completion request.
49   struct CompletionAction {
50     enum ActionKind {
51       /// Insert Text at the cursor position.
52       AK_Insert,
53       /// Show Completions, or beep if the list is empty.
54       AK_ShowCompletions
55     };
56 
57     ActionKind Kind;
58 
59     /// The text to insert.
60     std::string Text;
61 
62     /// The list of completions to show.
63     std::vector<std::string> Completions;
64   };
65 
66   /// A possible completion at a given cursor position.
67   struct Completion {
68     Completion() = default;
69     Completion(const std::string &TypedText, const std::string &DisplayText)
70         : TypedText(TypedText), DisplayText(DisplayText) {}
71 
72     /// The text to insert. If the user has already input some of the
73     /// completion, this should only include the rest of the text.
74     std::string TypedText;
75 
76     /// A description of this completion. This may be the completion itself, or
77     /// maybe a summary of its type or arguments.
78     std::string DisplayText;
79   };
80 
81   /// Set the completer for this LineEditor. A completer is a function object
82   /// which takes arguments of type StringRef (the string to complete) and
83   /// size_t (the zero-based cursor position in the StringRef) and returns a
84   /// CompletionAction.
85   template <typename T> void setCompleter(T Comp) {
86     Completer.reset(new CompleterModel<T>(Comp));
87   }
88 
89   /// Set the completer for this LineEditor to the given list completer.
90   /// A list completer is a function object which takes arguments of type
91   /// StringRef (the string to complete) and size_t (the zero-based cursor
92   /// position in the StringRef) and returns a std::vector<Completion>.
93   template <typename T> void setListCompleter(T Comp) {
94     Completer.reset(new ListCompleterModel<T>(Comp));
95   }
96 
97   /// Use the current completer to produce a CompletionAction for the given
98   /// completion request. If the current completer is a list completer, this
99   /// will return an AK_Insert CompletionAction if each completion has a common
100   /// prefix, or an AK_ShowCompletions CompletionAction otherwise.
101   ///
102   /// \param Buffer The string to complete
103   /// \param Pos The zero-based cursor position in the StringRef
104   CompletionAction getCompletionAction(StringRef Buffer, size_t Pos) const;
105 
106   const std::string &getPrompt() const { return Prompt; }
107   void setPrompt(const std::string &P) { Prompt = P; }
108 
109   // Public so callbacks in LineEditor.cpp can use it.
110   struct InternalData;
111 
112 private:
113   std::string Prompt;
114   std::string HistoryPath;
115   std::unique_ptr<InternalData> Data;
116 
117   struct CompleterConcept {
118     virtual ~CompleterConcept();
119     virtual CompletionAction complete(StringRef Buffer, size_t Pos) const = 0;
120   };
121 
122   struct ListCompleterConcept : CompleterConcept {
123     ~ListCompleterConcept() override;
124     CompletionAction complete(StringRef Buffer, size_t Pos) const override;
125     static std::string getCommonPrefix(const std::vector<Completion> &Comps);
126     virtual std::vector<Completion> getCompletions(StringRef Buffer,
127                                                    size_t Pos) const = 0;
128   };
129 
130   template <typename T>
131   struct CompleterModel : CompleterConcept {
132     CompleterModel(T Value) : Value(Value) {}
133     CompletionAction complete(StringRef Buffer, size_t Pos) const override {
134       return Value(Buffer, Pos);
135     }
136     T Value;
137   };
138 
139   template <typename T>
140   struct ListCompleterModel : ListCompleterConcept {
141     ListCompleterModel(T Value) : Value(std::move(Value)) {}
142     std::vector<Completion> getCompletions(StringRef Buffer,
143                                            size_t Pos) const override {
144       return Value(Buffer, Pos);
145     }
146     T Value;
147   };
148 
149   std::unique_ptr<const CompleterConcept> Completer;
150 };
151 
152 }
153 
154 #endif
155