xref: /freebsd/contrib/llvm-project/llvm/include/llvm/LineEditor/LineEditor.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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 
45   static std::string getDefaultHistoryPath(StringRef ProgName);
46 
47   /// The action to perform upon a completion request.
48   struct CompletionAction {
49     enum ActionKind {
50       /// Insert Text at the cursor position.
51       AK_Insert,
52       /// Show Completions, or beep if the list is empty.
53       AK_ShowCompletions
54     };
55 
56     ActionKind Kind;
57 
58     /// The text to insert.
59     std::string Text;
60 
61     /// The list of completions to show.
62     std::vector<std::string> Completions;
63   };
64 
65   /// A possible completion at a given cursor position.
66   struct Completion {
67     Completion() = default;
CompletionCompletion68     Completion(const std::string &TypedText, const std::string &DisplayText)
69         : TypedText(TypedText), DisplayText(DisplayText) {}
70 
71     /// The text to insert. If the user has already input some of the
72     /// completion, this should only include the rest of the text.
73     std::string TypedText;
74 
75     /// A description of this completion. This may be the completion itself, or
76     /// maybe a summary of its type or arguments.
77     std::string DisplayText;
78   };
79 
80   /// Set the completer for this LineEditor. A completer is a function object
81   /// which takes arguments of type StringRef (the string to complete) and
82   /// size_t (the zero-based cursor position in the StringRef) and returns a
83   /// CompletionAction.
setCompleter(T Comp)84   template <typename T> void setCompleter(T Comp) {
85     Completer.reset(new CompleterModel<T>(Comp));
86   }
87 
88   /// Set the completer for this LineEditor to the given list completer.
89   /// A list completer is a function object which takes arguments of type
90   /// StringRef (the string to complete) and size_t (the zero-based cursor
91   /// position in the StringRef) and returns a std::vector<Completion>.
setListCompleter(T Comp)92   template <typename T> void setListCompleter(T Comp) {
93     Completer.reset(new ListCompleterModel<T>(Comp));
94   }
95 
96   /// Use the current completer to produce a CompletionAction for the given
97   /// completion request. If the current completer is a list completer, this
98   /// will return an AK_Insert CompletionAction if each completion has a common
99   /// prefix, or an AK_ShowCompletions CompletionAction otherwise.
100   ///
101   /// \param Buffer The string to complete
102   /// \param Pos The zero-based cursor position in the StringRef
103   CompletionAction getCompletionAction(StringRef Buffer, size_t Pos) const;
104 
getPrompt()105   const std::string &getPrompt() const { return Prompt; }
setPrompt(const std::string & P)106   void setPrompt(const std::string &P) { Prompt = P; }
107 
108   // Public so callbacks in LineEditor.cpp can use it.
109   struct InternalData;
110 
111 private:
112   std::string Prompt;
113   std::string HistoryPath;
114   std::unique_ptr<InternalData> Data;
115 
116   struct CompleterConcept {
117     virtual ~CompleterConcept();
118     virtual CompletionAction complete(StringRef Buffer, size_t Pos) const = 0;
119   };
120 
121   struct ListCompleterConcept : CompleterConcept {
122     ~ListCompleterConcept() override;
123     CompletionAction complete(StringRef Buffer, size_t Pos) const override;
124     static std::string getCommonPrefix(const std::vector<Completion> &Comps);
125     virtual std::vector<Completion> getCompletions(StringRef Buffer,
126                                                    size_t Pos) const = 0;
127   };
128 
129   template <typename T>
130   struct CompleterModel : CompleterConcept {
CompleterModelCompleterModel131     CompleterModel(T Value) : Value(Value) {}
completeCompleterModel132     CompletionAction complete(StringRef Buffer, size_t Pos) const override {
133       return Value(Buffer, Pos);
134     }
135     T Value;
136   };
137 
138   template <typename T>
139   struct ListCompleterModel : ListCompleterConcept {
ListCompleterModelListCompleterModel140     ListCompleterModel(T Value) : Value(std::move(Value)) {}
getCompletionsListCompleterModel141     std::vector<Completion> getCompletions(StringRef Buffer,
142                                            size_t Pos) const override {
143       return Value(Buffer, Pos);
144     }
145     T Value;
146   };
147 
148   std::unique_ptr<const CompleterConcept> Completer;
149 };
150 
151 }
152 
153 #endif
154