// libcursedrl -- libcursed extension for integration with readline
// Copyright (C) 2019 xaizek <xaizek@posteo.net>
//
// This file is part of pipedial.
//
// pipedial is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// pipedial is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with pipedial. If not, see <https://www.gnu.org/licenses/>.
#ifndef LIBCURSEDRL__PROMPTREQUEST_HPP__
#define LIBCURSEDRL__PROMPTREQUEST_HPP__
#include <functional>
#include <string>
#include <vector>
#include "cursed/ColorTree.hpp"
#include "cursed/Input.hpp"
namespace cursed {
class Prompt;
class Screen;
}
namespace cursedrl {
// Describes result of a prompt request.
class PromptResult
{
friend class PromptRequest;
private:
// An input was provided. `false` in `accepted` parameter means request
// was declined/cancelled.
PromptResult(std::wstring input, bool accepted);
public:
// Retrieves input regardless of whether it was accepted.
std::wstring getResult() const
{ return input; }
// Checks if input was accepted.
operator bool() const
{ return accepted; }
private:
std::wstring input; // Input.
bool accepted; // Whether input was accepted.
};
// Provides text editing facility via prompt.
class PromptRequest
{
// Type of callback function invoked when input is changed.
using inputChangedFunc = std::function<void(const std::wstring &newInput)>;
// Type of callback function invoked to generate completions.
typedef std::function<
std::vector<std::wstring>(const std::wstring &prefix,
const std::wstring &what)
> completerFunc;
public:
// Remembers arguments.
PromptRequest(cursed::Screen &screen, cursed::Prompt &promptArea);
PromptRequest(const PromptRequest &rhs) = delete;
PromptRequest(PromptRequest &&rhs) = delete;
PromptRequest & operator=(const PromptRequest &rhs) = delete;
PromptRequest & operator=(PromptRequest &&rhs) = delete;
public:
// Loads history from the file.
static void loadHistory(const std::string &path);
// Stores history to the file.
static void saveHistory(const std::string &path);
public:
// Sets callback to be invoked when input is changed.
void setOnInputChanged(inputChangedFunc newOnInputChanged);
// Sets callback to be invoked to perform completion.
void setCompleter(completerFunc newCompleter);
// Performs the prompting. Blocks until it's done. Might throw
// `std::runtime_error`.
PromptResult prompt(const std::wstring &invitation,
const std::wstring &initial);
private:
// Readline's callback for initial preparations.
void rlStartup();
// Readline's callback for drawing prompt.
void rlRedisplay();
// Readline's callback for checking for more input.
int rlInputAvailable();
// Readline's callback for getting input.
int rlGetcFunction();
// Readline's callback for getting completions.
char ** rlComplete(const char text[], int start, int end);
// Reads more input if `inputBuf` is empty populating it as a result. After
// the function is invoked `inputBuf` is never empty.
void fetchInput();
// Resizes and redraws screen.
void updateScreen();
private:
cursed::Input input; // Source of input events.
cursed::Screen &screen; // Screen manager.
cursed::Prompt &promptArea; // Widget that displays the prompt.
inputChangedFunc onInputChanged; // Callback invoked when input is changed.
completerFunc completer; // Completion generator.
std::string initialValue; // Initial value of the prompt.
std::string lastValue; // Last seen input value.
std::vector<int> inputBuf; // Input queue.
cursed::Format promptHi; // Visual style of the prompt.
bool cancelled; // Whether input was cancelled.
};
}
#endif // LIBCURSEDRL__PROMPTREQUEST_HPP__
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"
Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/libcursedrl
Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/libcursedrl
You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a
pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master