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