Home | History | Annotate | Download | only in LineEditor
      1 //===-- llvm/LineEditor/LineEditor.h - line editor --------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef LLVM_LINEEDITOR_LINEEDITOR_H
     11 #define LLVM_LINEEDITOR_LINEEDITOR_H
     12 
     13 #include "llvm/ADT/Optional.h"
     14 #include "llvm/ADT/StringRef.h"
     15 #include <cstdio>
     16 #include <memory>
     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   LineEditor(StringRef ProgName, StringRef HistoryPath = "", FILE *In = stdin,
     35              FILE *Out = stdout, FILE *Err = stderr);
     36   ~LineEditor();
     37 
     38   /// Reads a line.
     39   ///
     40   /// \return The line, or llvm::Optional<std::string>() on EOF.
     41   llvm::Optional<std::string> readLine() const;
     42 
     43   void saveHistory();
     44   void loadHistory();
     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() {}
     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