Slight refactoring of bracketed paste feature
Handle begin/end paste directly in paste csi, manage paste buffer out of get_char, filter Key::Invalid earlier. get_next_key returning Key::Invalid means there was some input but it could not be represented as a Key. An empty optional means there was no input at all.
This commit is contained in:
parent
f05ab99d4d
commit
6548846950
|
@ -46,6 +46,7 @@ Client::Client(std::unique_ptr<UserInterface>&& ui,
|
||||||
|
|
||||||
m_ui->set_ui_options(m_window->options()["ui_options"].get<UserInterface::Options>());
|
m_ui->set_ui_options(m_window->options()["ui_options"].get<UserInterface::Options>());
|
||||||
m_ui->set_on_key([this](Key key) {
|
m_ui->set_on_key([this](Key key) {
|
||||||
|
kak_assert(key != Key::Invalid);
|
||||||
if (key == ctrl('c'))
|
if (key == ctrl('c'))
|
||||||
{
|
{
|
||||||
auto prev_handler = set_signal_handler(SIGINT, SIG_IGN);
|
auto prev_handler = set_signal_handler(SIGINT, SIG_IGN);
|
||||||
|
|
|
@ -1750,8 +1750,7 @@ static bool is_valid(Key key)
|
||||||
{
|
{
|
||||||
constexpr Key::Modifiers valid_mods = (Key::Modifiers::Control | Key::Modifiers::Alt | Key::Modifiers::Shift);
|
constexpr Key::Modifiers valid_mods = (Key::Modifiers::Control | Key::Modifiers::Alt | Key::Modifiers::Shift);
|
||||||
|
|
||||||
return key != Key::Invalid and
|
return ((key.modifiers & ~valid_mods) or key.key <= 0x10FFFF);
|
||||||
((key.modifiers & ~valid_mods) or key.key <= 0x10FFFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputHandler::handle_key(Key key)
|
void InputHandler::handle_key(Key key)
|
||||||
|
|
|
@ -447,9 +447,9 @@ TerminalUI::TerminalUI()
|
||||||
|
|
||||||
while (auto key = get_next_key())
|
while (auto key = get_next_key())
|
||||||
{
|
{
|
||||||
if (key == ctrl('z'))
|
if (*key == ctrl('z'))
|
||||||
kill(0, SIGTSTP); // We suspend at this line
|
kill(0, SIGTSTP); // We suspend at this line
|
||||||
else
|
else if (*key != Key::Invalid)
|
||||||
m_on_key(*key);
|
m_on_key(*key);
|
||||||
}
|
}
|
||||||
}},
|
}},
|
||||||
|
@ -689,11 +689,7 @@ Optional<Key> TerminalUI::get_next_key()
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if (unsigned char c = 0; read(STDIN_FILENO, &c, 1) == 1)
|
if (unsigned char c = 0; read(STDIN_FILENO, &c, 1) == 1)
|
||||||
{
|
|
||||||
if (m_paste_buffer)
|
|
||||||
m_paste_buffer->push_back(c);
|
|
||||||
return c;
|
return c;
|
||||||
}
|
|
||||||
|
|
||||||
stdin_closed = 1;
|
stdin_closed = 1;
|
||||||
return {};
|
return {};
|
||||||
|
@ -759,16 +755,7 @@ Optional<Key> TerminalUI::get_next_key()
|
||||||
return mod;
|
return mod;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class PasteEvent { Begin, End };
|
auto parse_csi = [this]() -> Optional<Key> {
|
||||||
struct KeyOrPasteEvent {
|
|
||||||
KeyOrPasteEvent() = default;
|
|
||||||
KeyOrPasteEvent(Key key) : key(key) {}
|
|
||||||
KeyOrPasteEvent(Optional<Key> key) : key(key) {}
|
|
||||||
KeyOrPasteEvent(PasteEvent paste) : paste(paste) {}
|
|
||||||
const Optional<Key> key;
|
|
||||||
const Optional<PasteEvent> paste;
|
|
||||||
};
|
|
||||||
auto parse_csi = [this]() -> KeyOrPasteEvent {
|
|
||||||
auto next_char = [] { return get_char().value_or((unsigned char)0xff); };
|
auto next_char = [] { return get_char().value_or((unsigned char)0xff); };
|
||||||
int params[16][4] = {};
|
int params[16][4] = {};
|
||||||
auto c = next_char();
|
auto c = next_char();
|
||||||
|
@ -878,9 +865,15 @@ Optional<Key> TerminalUI::get_next_key()
|
||||||
case 33: case 34:
|
case 33: case 34:
|
||||||
return Key{Key::Modifiers::Shift, Key::F9 + params[0][0] - 33}; // rxvt style
|
return Key{Key::Modifiers::Shift, Key::F9 + params[0][0] - 33}; // rxvt style
|
||||||
case 200:
|
case 200:
|
||||||
return PasteEvent::Begin;
|
m_paste_buffer = String{};
|
||||||
|
return Key{Key::Invalid};
|
||||||
case 201:
|
case 201:
|
||||||
return PasteEvent::End;
|
if (m_paste_buffer)
|
||||||
|
{
|
||||||
|
m_on_paste(*m_paste_buffer);
|
||||||
|
m_paste_buffer.reset();
|
||||||
|
}
|
||||||
|
return Key{Key::Invalid};
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
case 'u':
|
case 'u':
|
||||||
|
@ -962,41 +955,26 @@ Optional<Key> TerminalUI::get_next_key()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (m_paste_buffer)
|
if (*c == 27)
|
||||||
{
|
{
|
||||||
if (*c == 27 and get_char() == '[' and parse_csi().paste == PasteEvent::End)
|
|
||||||
{
|
|
||||||
m_paste_buffer->resize(m_paste_buffer->length() - "\033[201~"_str.length(), '\0');
|
|
||||||
m_on_paste(*m_paste_buffer);
|
|
||||||
m_paste_buffer.reset();
|
|
||||||
}
|
|
||||||
return get_next_key();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*c != 27)
|
|
||||||
return parse_key(*c);
|
|
||||||
|
|
||||||
if (auto next = get_char())
|
if (auto next = get_char())
|
||||||
{
|
{
|
||||||
|
if (*next == '[') // potential CSI
|
||||||
|
return parse_csi().value_or(alt('['));
|
||||||
if (*next == 'O') // potential SS3
|
if (*next == 'O') // potential SS3
|
||||||
return parse_ss3().value_or(alt('O'));
|
return parse_ss3().value_or(alt('O'));
|
||||||
if (*next != '[')
|
|
||||||
return alt(parse_key(*next));
|
return alt(parse_key(*next));
|
||||||
// potential CSI
|
|
||||||
KeyOrPasteEvent csi = parse_csi();
|
|
||||||
if (csi.paste == PasteEvent::Begin)
|
|
||||||
{
|
|
||||||
m_paste_buffer = String{};
|
|
||||||
return get_next_key();
|
|
||||||
}
|
}
|
||||||
if (csi.paste == PasteEvent::End) // Unmatched bracketed paste sequence.
|
else if (not m_paste_buffer)
|
||||||
return {};
|
return Key{Key::Escape};
|
||||||
if (csi.key)
|
|
||||||
return *csi.key;
|
|
||||||
return alt('[');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Key{Key::Escape};
|
if (m_paste_buffer)
|
||||||
|
{
|
||||||
|
m_paste_buffer->push_back(*c);
|
||||||
|
return Key{Key::Invalid};
|
||||||
|
}
|
||||||
|
return parse_key(*c);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user