summaryrefslogtreecommitdiff
path: root/src/input_handler.cc
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2014-08-14 00:31:39 +0100
committerMaxime Coste <frrrwww@gmail.com>2014-08-14 00:31:39 +0100
commitfbbe741c073e3c8c432c8d60f9c17a6ae3959d78 (patch)
tree66234e3456b4299f5b8d5b5ea2eeb9fd380807f6 /src/input_handler.cc
parent518b995720e8eb04b22848313fe278a268e3312b (diff)
Add support for <c-w> <c-b> and <c-e> for word moves in the line editor
This might go away later if we find a better way of handling line edition, but seems like a good compromise for now. Fixes #168
Diffstat (limited to 'src/input_handler.cc')
-rw-r--r--src/input_handler.cc87
1 files changed, 85 insertions, 2 deletions
diff --git a/src/input_handler.cc b/src/input_handler.cc
index 1ece72b6..0402f2ea 100644
--- a/src/input_handler.cc
+++ b/src/input_handler.cc
@@ -143,17 +143,87 @@ private:
Timer m_fs_check_timer;
};
+template<WordType word_type>
+void to_next_word_begin(CharCount& pos, StringView line)
+{
+ const CharCount len = line.char_length();
+ if (pos == len)
+ return;
+ if (word_type == Word and is_punctuation(line[pos]))
+ {
+ while (pos != len and is_punctuation(line[pos]))
+ ++pos;
+ }
+ else if (is_word<word_type>(line[pos]))
+ {
+ while (pos != len and is_word<word_type>(line[pos]))
+ ++pos;
+ }
+ while (pos != len and is_blank(line[pos]))
+ ++pos;
+}
+
+template<WordType word_type>
+void to_next_word_end(CharCount& pos, StringView line)
+{
+ const CharCount len = line.char_length();
+ if (pos + 1 >= len)
+ return;
+ ++pos;
+
+ while (pos != len and is_blank(line[pos]))
+ ++pos;
+
+ if (word_type == Word and is_punctuation(line[pos]))
+ {
+ while (pos != len and is_punctuation(line[pos]))
+ ++pos;
+ }
+ else if (is_word<word_type>(line[pos]))
+ {
+ while (pos != len and is_word<word_type>(line[pos]))
+ ++pos;
+ }
+ --pos;
+}
+
+template<WordType word_type>
+void to_prev_word_begin(CharCount& pos, StringView line)
+{
+ if (pos == 0_char)
+ return;
+ --pos;
+
+ while (pos != 0_char and is_blank(line[pos]))
+ --pos;
+
+ if (word_type == Word and is_punctuation(line[pos]))
+ {
+ while (pos != 0_char and is_punctuation(line[pos]))
+ --pos;
+ if (!is_punctuation(line[pos]))
+ ++pos;
+ }
+ else if (is_word<word_type>(line[pos]))
+ {
+ while (pos != 0_char and is_word<word_type>(line[pos]))
+ --pos;
+ if (!is_word<word_type>(line[pos]))
+ ++pos;
+ }
+}
+
class LineEditor
{
public:
void handle_key(Key key)
{
- if (key == Key::Left or key == ctrl('b'))
+ if (key == Key::Left)
{
if (m_cursor_pos > 0)
--m_cursor_pos;
}
- else if (key == Key::Right or key == ctrl('f'))
+ else if (key == Key::Right)
{
if (m_cursor_pos < m_line.char_length())
++m_cursor_pos;
@@ -178,6 +248,18 @@ public:
m_line = m_line.substr(0, m_cursor_pos)
+ m_line.substr(m_cursor_pos+1);
}
+ else if (key == ctrl('w'))
+ to_next_word_begin<Word>(m_cursor_pos, m_line);
+ else if (key == ctrlalt('w'))
+ to_next_word_begin<WORD>(m_cursor_pos, m_line);
+ else if (key == ctrl('b'))
+ to_prev_word_begin<Word>(m_cursor_pos, m_line);
+ else if (key == ctrlalt('b'))
+ to_prev_word_begin<WORD>(m_cursor_pos, m_line);
+ else if (key == ctrl('e'))
+ to_next_word_end<Word>(m_cursor_pos, m_line);
+ else if (key == ctrlalt('e'))
+ to_next_word_end<WORD>(m_cursor_pos, m_line);
else
{
m_line = m_line.substr(0, m_cursor_pos) + codepoint_to_str(key.key)
@@ -227,6 +309,7 @@ public:
private:
CharCount m_cursor_pos = 0;
CharCount m_display_pos = 0;
+
String m_line;
};