blob: 0beaf1bb23a90b1bd1f559fcefd5d61a0a10c170 [file] [log] [blame]
//===-- llvm/LineEditor/LineEditor.h - line editor --------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LINEEDITOR_LINEEDITOR_H
#define LLVM_LINEEDITOR_LINEEDITOR_H
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
#include <cstdio>
#include <memory>
#include <string>
#include <utility>
#include <vector>
namespace llvm {
class LineEditor {
public:
/// Create a LineEditor object.
///
/// \param ProgName The name of the current program. Used to form a default
/// prompt.
/// \param HistoryPath Path to the file in which to store history data, if
/// possible.
/// \param In The input stream used by the editor.
/// \param Out The output stream used by the editor.
/// \param Err The error stream used by the editor.
LineEditor(StringRef ProgName, StringRef HistoryPath = "", FILE *In = stdin,
FILE *Out = stdout, FILE *Err = stderr);
~LineEditor();
/// Reads a line.
///
/// \return The line, or llvm::Optional<std::string>() on EOF.
llvm::Optional<std::string> readLine() const;
void saveHistory();
void loadHistory();
static std::string getDefaultHistoryPath(StringRef ProgName);
/// The action to perform upon a completion request.
struct CompletionAction {
enum ActionKind {
/// Insert Text at the cursor position.
AK_Insert,
/// Show Completions, or beep if the list is empty.
AK_ShowCompletions
};
ActionKind Kind;
/// The text to insert.
std::string Text;
/// The list of completions to show.
std::vector<std::string> Completions;
};
/// A possible completion at a given cursor position.
struct Completion {
Completion() {}
Completion(const std::string &TypedText, const std::string &DisplayText)
: TypedText(TypedText), DisplayText(DisplayText) {}
/// The text to insert. If the user has already input some of the
/// completion, this should only include the rest of the text.
std::string TypedText;
/// A description of this completion. This may be the completion itself, or
/// maybe a summary of its type or arguments.
std::string DisplayText;
};
/// Set the completer for this LineEditor. A completer is a function object
/// which takes arguments of type StringRef (the string to complete) and
/// size_t (the zero-based cursor position in the StringRef) and returns a
/// CompletionAction.
template <typename T> void setCompleter(T Comp) {
Completer.reset(new CompleterModel<T>(Comp));
}
/// Set the completer for this LineEditor to the given list completer.
/// A list completer is a function object which takes arguments of type
/// StringRef (the string to complete) and size_t (the zero-based cursor
/// position in the StringRef) and returns a std::vector<Completion>.
template <typename T> void setListCompleter(T Comp) {
Completer.reset(new ListCompleterModel<T>(Comp));
}
/// Use the current completer to produce a CompletionAction for the given
/// completion request. If the current completer is a list completer, this
/// will return an AK_Insert CompletionAction if each completion has a common
/// prefix, or an AK_ShowCompletions CompletionAction otherwise.
///
/// \param Buffer The string to complete
/// \param Pos The zero-based cursor position in the StringRef
CompletionAction getCompletionAction(StringRef Buffer, size_t Pos) const;
const std::string &getPrompt() const { return Prompt; }
void setPrompt(const std::string &P) { Prompt = P; }
// Public so callbacks in LineEditor.cpp can use it.
struct InternalData;
private:
std::string Prompt;
std::string HistoryPath;
std::unique_ptr<InternalData> Data;
struct CompleterConcept {
virtual ~CompleterConcept();
virtual CompletionAction complete(StringRef Buffer, size_t Pos) const = 0;
};
struct ListCompleterConcept : CompleterConcept {
~ListCompleterConcept() override;
CompletionAction complete(StringRef Buffer, size_t Pos) const override;
static std::string getCommonPrefix(const std::vector<Completion> &Comps);
virtual std::vector<Completion> getCompletions(StringRef Buffer,
size_t Pos) const = 0;
};
template <typename T>
struct CompleterModel : CompleterConcept {
CompleterModel(T Value) : Value(Value) {}
CompletionAction complete(StringRef Buffer, size_t Pos) const override {
return Value(Buffer, Pos);
}
T Value;
};
template <typename T>
struct ListCompleterModel : ListCompleterConcept {
ListCompleterModel(T Value) : Value(std::move(Value)) {}
std::vector<Completion> getCompletions(StringRef Buffer,
size_t Pos) const override {
return Value(Buffer, Pos);
}
T Value;
};
std::unique_ptr<const CompleterConcept> Completer;
};
}
#endif