178 lines
5.5 KiB
C++
178 lines
5.5 KiB
C++
|
#ifndef MALACHSCRIPT_INPUTWINDOW_HPP
|
||
|
#define MALACHSCRIPT_INPUTWINDOW_HPP
|
||
|
#include <ncurses.h>
|
||
|
#include <string>
|
||
|
#include <vector>
|
||
|
|
||
|
namespace MalachScriptRepl {
|
||
|
class InputWindow {
|
||
|
private:
|
||
|
WINDOW* _window;
|
||
|
|
||
|
std::vector<std::u8string> _lines = {u8""};
|
||
|
int _row = 0;
|
||
|
int _col = 0;
|
||
|
int _rightPos = 0;
|
||
|
[[maybe_unused]] int _scroll = 0;
|
||
|
|
||
|
std::function<void(const std::vector<std::u8string>&)> _onChange;
|
||
|
|
||
|
public:
|
||
|
InputWindow(int height, int width, int y, int x) {
|
||
|
_window = newwin(height, width, y, x);
|
||
|
keypad(_window, true);
|
||
|
}
|
||
|
|
||
|
inline void RegisterOnChange(std::function<void(const std::vector<std::u8string>&)> listener) {
|
||
|
_onChange = listener;
|
||
|
}
|
||
|
|
||
|
inline void Refresh() { wrefresh(_window); }
|
||
|
inline void Clear() { wclear(_window); }
|
||
|
|
||
|
[[nodiscard]] inline int GetInput() const { return wgetch(_window); }
|
||
|
inline std::pair<int, int> GetCursorPosition() {
|
||
|
int row, col;
|
||
|
getyx(_window, row, col);
|
||
|
return std::pair<int, int>(row, col);
|
||
|
}
|
||
|
|
||
|
inline void MoveCursorPosition(int row, int col) { wmove(_window, row, col); }
|
||
|
|
||
|
inline void MoveCursorLeft() {
|
||
|
if (_col > 0) {
|
||
|
wmove(_window, _row, --_col);
|
||
|
_rightPos = _col;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void MoveCursorRight() {
|
||
|
auto& line = _lines[_row];
|
||
|
if (_col < (int)line.size()) {
|
||
|
wmove(_window, _row, ++_col);
|
||
|
_rightPos = _col;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void MoveCursorUp() {
|
||
|
if (_row > 0) {
|
||
|
_col = _rightPos;
|
||
|
if (_col > (int)_lines[_row - 1].size()) {
|
||
|
_col = (int)_lines[_row - 1].size();
|
||
|
}
|
||
|
wmove(_window, --_row, _col);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void MoveCursorDown() {
|
||
|
if (_row < (int)_lines.size() - 1) {
|
||
|
_col = _rightPos;
|
||
|
if (_col > (int)_lines[_row + 1].size()) {
|
||
|
_col = (int)_lines[_row + 1].size();
|
||
|
}
|
||
|
wmove(_window, ++_row, _col);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void Backspace() {
|
||
|
if (_col > 0) {
|
||
|
mvwdelch(_window, _row, --_col);
|
||
|
auto& line = _lines[_row];
|
||
|
line = line.erase(_col, 1);
|
||
|
_onChange(_lines);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void Return() {
|
||
|
_lines.insert(_lines.begin() + _row + 1, u8"");
|
||
|
_row++;
|
||
|
_col = 0;
|
||
|
for (size_t i = _row - 1; i < _lines.size(); i++) {
|
||
|
wmove(_window, i, 0);
|
||
|
wclrtoeol(_window);
|
||
|
waddstr(_window, (char*)_lines[i].c_str());
|
||
|
}
|
||
|
wmove(_window, _row, _col);
|
||
|
}
|
||
|
inline void Tab() {
|
||
|
wmove(_window, _row, 0);
|
||
|
wclrtoeol(_window);
|
||
|
auto& line = _lines[_row];
|
||
|
if ((int)line.length() <= _col) {
|
||
|
line += u8" ";
|
||
|
} else {
|
||
|
for (size_t i = 0; i < 4; i++) {
|
||
|
line.insert(line.begin() + _col, u8' ');
|
||
|
}
|
||
|
}
|
||
|
waddstr(_window, (char*)line.c_str());
|
||
|
_col += 4;
|
||
|
_rightPos = _col;
|
||
|
wmove(_window, _row, _col);
|
||
|
_onChange(_lines);
|
||
|
}
|
||
|
|
||
|
inline void GoToEndOfLine() {
|
||
|
_col = _lines[_row].size();
|
||
|
_rightPos = _col;
|
||
|
wmove(_window, _row, _col);
|
||
|
}
|
||
|
inline void GoToStartOfLine() {
|
||
|
_col = _lines[_row].size();
|
||
|
_rightPos = _col;
|
||
|
wmove(_window, _row, _col);
|
||
|
}
|
||
|
|
||
|
inline void Input(int c) {
|
||
|
wmove(_window, _row, 0);
|
||
|
auto& line = _lines[_row];
|
||
|
if ((int)line.length() <= _col) {
|
||
|
line += (char8_t)c;
|
||
|
} else {
|
||
|
line.insert(line.begin() + _col, c);
|
||
|
}
|
||
|
waddstr(_window, (char*)line.c_str());
|
||
|
_col++;
|
||
|
_rightPos = _col;
|
||
|
wmove(_window, _row, _col);
|
||
|
_onChange(_lines);
|
||
|
}
|
||
|
|
||
|
inline void SetScriptWithDiagnostics(const std::u8string& script,
|
||
|
const MalachScript::Diagnostics::Diagnostic* diag) {
|
||
|
auto yx = GetCursorPosition();
|
||
|
|
||
|
Clear();
|
||
|
|
||
|
if (diag != nullptr) {
|
||
|
auto start = diag->GetSpan().GetStart();
|
||
|
auto end = diag->GetSpan().GetEnd() + 1;
|
||
|
if (end > script.size()) {
|
||
|
end = script.size();
|
||
|
if (start == end && start > 0) {
|
||
|
start--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
waddnstr(_window, (char*)script.c_str(), start);
|
||
|
wattron(_window, COLOR_PAIR(1));
|
||
|
waddnstr(_window, (char*)script.substr(start).data(), end - start);
|
||
|
wattroff(_window, COLOR_PAIR(1));
|
||
|
waddnstr(_window, (char*)script.substr(end).data(), script.size() - end);
|
||
|
|
||
|
if (start >= script.size() - 1) {
|
||
|
wattron(_window, COLOR_PAIR(1));
|
||
|
waddch(_window, ' ');
|
||
|
wattroff(_window, COLOR_PAIR(1));
|
||
|
}
|
||
|
} else {
|
||
|
waddstr(_window, (char*)script.c_str());
|
||
|
}
|
||
|
MoveCursorPosition(yx.first, yx.second);
|
||
|
Refresh();
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
#endif // MALACHSCRIPT_INPUTWINDOW_HPP
|