// pipedial -- terminal element picker
// 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 PIPEDIAL__PROMPTREQUEST_HPP__
#define PIPEDIAL__PROMPTREQUEST_HPP__
#include <functional>
#include <string>
#include <vector>
namespace cursed {
class Input;
class Prompt;
class Screen;
}
// Describes result of a prompt request.
class PromptResult
{
friend class PromptRequest;
private:
// No input was provided (request was declined/cancelled).
PromptResult();
// An input was provided.
PromptResult(std::wstring result);
public:
// Retrieves input.
std::wstring getResult() const
{ return result; }
// Checks if result contains input.
operator bool() const
{ return hasInput; }
private:
std::wstring result; // Input.
bool hasInput; // Whether input makes sense.
};
// 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)>;
public:
// Remembers arguments and makes cursor visible.
PromptRequest(cursed::Input &input, cursed::Screen &screen,
cursed::Prompt &promptArea,
inputChangedFunc onInputChanged = {});
// Cleans up and hides cursor.
~PromptRequest();
PromptRequest(const PromptRequest &rhs) = delete;
PromptRequest(PromptRequest &&rhs) = delete;
PromptRequest & operator=(const PromptRequest &rhs) = delete;
PromptRequest & operator=(PromptRequest &&rhs) = delete;
public:
// 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();
// 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.
std::string initialValue; // Initial value of the prompt.
std::string lastValue; // Last seen input value.
std::vector<int> inputBuf; // Input queue.
};
#endif // PIPEDIAL__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/pipedial
Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/pipedial
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