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