Skip to content

Commit aee6a88

Browse files
committed
Fix bug with backspace/del and improve key program to detect not supported keys
1 parent f6e8707 commit aee6a88

File tree

11 files changed

+120
-79
lines changed

11 files changed

+120
-79
lines changed

cpp-terminal/event.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ bool Term::Event::empty()
77
return false;
88
}
99

10+
Term::Event::operator std::string()
11+
{
12+
if(m_Type == Type::CopyPaste) return m_str;
13+
else
14+
return std::string();
15+
}
16+
1017
Term::Event::operator Term::Screen()
1118
{
1219
if(m_Type == Type::Screen) return m_Screen;
@@ -28,9 +35,11 @@ void Term::Event::parse()
2835
{
2936
m_Type = Type::Key;
3037
m_Key = static_cast<Term::Key::Value>(m_str[0]);
38+
/* Backspace return 127 CTRL+backspace return 8 */
39+
if(m_Key == Term::Key::Value::DEL) m_Key = Term::Key::Value::BACKSPACE;
3140
m_str.clear();
3241
}
33-
else if(m_str.size() <= 5)
42+
else if(m_str.size() <= 10)
3443
{
3544
//https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
3645
// CSI = ESC[ SS3 = ESCO
@@ -165,8 +174,11 @@ void Term::Event::parse()
165174
m_Key = Term::Key::Value::F19;
166175
else if(m_str == "\033[34~")
167176
m_Key = Term::Key::Value::F20;
168-
if(!m_Key.empty()) m_Type = Type::Key;
169-
m_str.clear();
177+
if(!m_Key.empty())
178+
{
179+
m_Type = Type::Key;
180+
m_str.clear();
181+
}
170182
}
171183
else { m_Type = Type::CopyPaste; }
172184
}

cpp-terminal/event.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ class Event
2626
bool empty();
2727
Type type();
2828

29-
operator Term::Key();
30-
operator Term::Screen();
31-
Key getKey() { return m_Key; }
29+
operator Term::Key();
30+
operator Term::Screen();
31+
operator std::string();
3232

3333
private:
3434
void parse();

cpp-terminal/input.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,10 @@
88
#include "cpp-terminal/event.hpp"
99

1010
#include <chrono>
11-
#include <iostream>
1211
#include <thread>
1312
#include <type_traits>
1413

15-
Term::Event Term::read_key()
14+
Term::Event Term::read_event()
1615
{
1716
Term::Event event;
1817
while((event = Platform::read_raw()).empty()) { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }

cpp-terminal/input.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ Term::Event read_raw();
1616
char read_raw_stdin();
1717
} // namespace Platform
1818

19-
// Waits for a key press, translates escape codes
20-
// if Term:Terminal is not enabling the keyboard it'll loop for infinity
21-
Term::Event read_key();
19+
// Waits for an event (key press, screen resizing ...)
20+
Term::Event read_event();
2221

2322
// returns the stdin as a string
2423
// waits until the EOT signal is send

cpp-terminal/key.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ bool Term::Key::is_extended_ASCII()
2121
bool Term::Key::is_CTRL()
2222
{
2323
// Need to suppress the TAB etc...
24-
if(m_value > 0 && m_value <= 31 && m_value != Key::BACKSPACE && m_value != Key::TAB && m_value != ESC && /* the two mapped to ENTER */ m_value != Key::LF && m_value != ENTER) return true;
24+
if(m_value > 0 && m_value <= 31 && m_value != Key::BACKSPACE && m_value != Key::TAB && m_value != ESC && /* the two mapped to ENTER */ m_value != ENTER) return true;
2525
else
2626
return false;
2727
}

cpp-terminal/key.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Key
2222
CTRL_G = 7,
2323
BACKSPACE = 8,
2424
TAB = 9,
25-
LF = 10,
25+
CTRL_J = 10,
2626
CTRL_K = 11,
2727
CTRL_L = 12,
2828
ENTER = 13, // Mapped to ENTER

cpp-terminal/prompt.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Term::Result Term::prompt(const std::string& message, const std::string& first_o
2525
{
2626
while(true)
2727
{
28-
key = Term::read_key();
28+
key = Term::read_event();
2929
if(key == Term::Key::NO_KEY) continue;
3030
if(key == 'y' || key == 'Y')
3131
{
@@ -60,7 +60,7 @@ Term::Result Term::prompt(const std::string& message, const std::string& first_o
6060
unsigned short int length = 0;
6161
while(true)
6262
{
63-
key = Term::read_key();
63+
key = Term::read_event();
6464
if(key == Term::Key::NO_KEY) continue;
6565
if(key >= 'a' && key <= 'z')
6666
{
@@ -224,7 +224,7 @@ std::string Term::prompt_multiline(const std::string& prompt_string, std::vector
224224
bool not_complete = true;
225225
while(not_complete)
226226
{
227-
key = Term::read_key();
227+
key = Term::read_event();
228228
if(key == Term::Key::NO_KEY) continue;
229229
if((key >= 'a' && key <= 'z') || (key >= 'A' && key <= 'Z') || (key.is_extended_ASCII() && !iscntrl(key)))
230230
{

examples/keys.cpp

Lines changed: 87 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "cpp-terminal/key.hpp"
88
#include "cpp-terminal/terminal.hpp"
99
#include "cpp-terminal/tty.hpp"
10+
#include "cpp-terminal/version.hpp"
1011

1112
#include <iostream>
1213
#include <utility>
@@ -29,67 +30,96 @@ int main()
2930
int quit{0};
3031
while(quit != 3)
3132
{
32-
Term::Key key{Term::read_key()};
33-
if(key == Term::Key::Value::q) quit++;
34-
else
35-
quit = 0;
36-
std::string s;
37-
if(key == Term::Key::Value::NO_KEY) continue;
38-
if(key >= Term::Key::a && key <= Term::Key::z)
33+
Term::Event event{Term::read_event()};
34+
switch(event.type())
3935
{
40-
s = (char)(key + Term::Key::A - Term::Key::a); // Convert to upper case
41-
}
42-
else if(key >= Term::Key::A && key <= Term::Key::Z)
43-
{
44-
s = (std::string) "Shift+" + (char)key; // Already in upper case;
45-
}
46-
else if(key.is_CTRL()) { s = (std::string) "CTRL+" + (char)(-Term::Key::CTRL + key); }
47-
else if(key.is_ALT())
48-
{
49-
s = (std::string) "Alt+" + (char)(key + Term::Key::A - (Term::Key::ALT + Term::Key::a)); // Convert to upper case
50-
}
51-
else if(key.is_extended_ASCII() && !iscntrl(key)) { s = (char)key; }
52-
else
53-
{
54-
switch(key)
36+
case Term::Event::Type::Key:
5537
{
56-
case Term::Key::BACKSPACE: s = "BACKSPACE"; break;
57-
case Term::Key::ENTER: s = "ENTER"; break;
58-
case Term::Key::ALT_ENTER: s = "Alt+ENTER"; break;
59-
case Term::Key::TAB: s = "TAB"; break;
60-
case Term::Key::ARROW_LEFT: s = "ARROW_LEFT"; break;
61-
case Term::Key::ARROW_RIGHT: s = "ARROW_RIGHT"; break;
62-
case Term::Key::ARROW_UP: s = "ARROW_UP"; break;
63-
case Term::Key::ARROW_DOWN: s = "ARROW_DOWN"; break;
64-
case Term::Key::CTRL_UP: s = "CTRL_UP"; break;
65-
case Term::Key::CTRL_DOWN: s = "CTRL_DOWN"; break;
66-
case Term::Key::CTRL_RIGHT: s = "CTRL_RIGHT"; break;
67-
case Term::Key::CTRL_LEFT: s = "CTRL_LEFT"; break;
68-
case Term::Key::NUMERIC_5: s = "NUMERIC_5"; break;
69-
case Term::Key::DEL: s = "DELETE"; break;
70-
case Term::Key::HOME: s = "HOME"; break;
71-
case Term::Key::INSERT: s = "INSERT"; break;
72-
case Term::Key::END: s = "END"; break;
73-
case Term::Key::PAGE_UP: s = "PAGE_UP"; break;
74-
case Term::Key::PAGE_DOWN: s = "PAGE_DOWN"; break;
75-
case Term::Key::ESC: s = "ESC"; break;
76-
case Term::Key::F1: s = "F1"; break;
77-
case Term::Key::F2: s = "F2"; break;
78-
case Term::Key::F3: s = "F3"; break;
79-
case Term::Key::F4: s = "F4"; break;
80-
case Term::Key::F5: s = "F5"; break;
81-
case Term::Key::F6: s = "F6"; break;
82-
case Term::Key::F7: s = "F7"; break;
83-
case Term::Key::F8: s = "F8"; break;
84-
case Term::Key::F9: s = "F9"; break;
85-
case Term::Key::F10: s = "F10"; break;
86-
case Term::Key::F11: s = "F11"; break;
87-
case Term::Key::F12: s = "F12"; break;
88-
89-
default: s = "Unknown:" + std::to_string(key);
38+
Term::Key key{event};
39+
if(key == Term::Key::Value::q) quit++;
40+
else
41+
quit = 0;
42+
std::string s;
43+
if(key == Term::Key::Value::NO_KEY) continue;
44+
if(key >= Term::Key::a && key <= Term::Key::z)
45+
{
46+
s = (char)(key + Term::Key::A - Term::Key::a); // Convert to upper case
47+
}
48+
else if(key >= Term::Key::A && key <= Term::Key::Z)
49+
{
50+
s = (std::string) "Shift+" + (char)key; // Already in upper case;
51+
}
52+
else if(key.is_CTRL()) { s = (std::string) "CTRL+" + (char)(-Term::Key::CTRL + key); }
53+
else if(key.is_ALT())
54+
{
55+
s = (std::string) "Alt+" + (char)(key + Term::Key::A - (Term::Key::ALT + Term::Key::a)); // Convert to upper case
56+
}
57+
else if(key.is_extended_ASCII() && !iscntrl(key)) { s = (char)key; }
58+
else
59+
{
60+
switch(key)
61+
{
62+
case Term::Key::BACKSPACE: s = "BACKSPACE"; break;
63+
case Term::Key::ENTER: s = "ENTER"; break;
64+
case Term::Key::ALT_ENTER: s = "Alt+ENTER"; break;
65+
case Term::Key::TAB: s = "TAB"; break;
66+
case Term::Key::ARROW_LEFT: s = "ARROW_LEFT"; break;
67+
case Term::Key::ARROW_RIGHT: s = "ARROW_RIGHT"; break;
68+
case Term::Key::ARROW_UP: s = "ARROW_UP"; break;
69+
case Term::Key::ARROW_DOWN: s = "ARROW_DOWN"; break;
70+
case Term::Key::CTRL_UP: s = "CTRL_UP"; break;
71+
case Term::Key::CTRL_DOWN: s = "CTRL_DOWN"; break;
72+
case Term::Key::CTRL_RIGHT: s = "CTRL_RIGHT"; break;
73+
case Term::Key::CTRL_LEFT: s = "CTRL_LEFT"; break;
74+
case Term::Key::NUMERIC_5: s = "NUMERIC_5"; break;
75+
case Term::Key::DEL: s = "DELETE"; break;
76+
case Term::Key::HOME: s = "HOME"; break;
77+
case Term::Key::INSERT: s = "INSERT"; break;
78+
case Term::Key::END: s = "END"; break;
79+
case Term::Key::PAGE_UP: s = "PAGE_UP"; break;
80+
case Term::Key::PAGE_DOWN: s = "PAGE_DOWN"; break;
81+
case Term::Key::ESC: s = "ESC"; break;
82+
case Term::Key::F1: s = "F1"; break;
83+
case Term::Key::F2: s = "F2"; break;
84+
case Term::Key::F3: s = "F3"; break;
85+
case Term::Key::F4: s = "F4"; break;
86+
case Term::Key::F5: s = "F5"; break;
87+
case Term::Key::F6: s = "F6"; break;
88+
case Term::Key::F7: s = "F7"; break;
89+
case Term::Key::F8: s = "F8"; break;
90+
case Term::Key::F9: s = "F9"; break;
91+
case Term::Key::F10: s = "F10"; break;
92+
case Term::Key::F11: s = "F11"; break;
93+
case Term::Key::F12: s = "F12"; break;
94+
case Term::Key::F13: s = "F13"; break;
95+
case Term::Key::F14: s = "F14"; break;
96+
case Term::Key::F15: s = "F15"; break;
97+
case Term::Key::F16: s = "F16"; break;
98+
case Term::Key::F17: s = "F17"; break;
99+
case Term::Key::F18: s = "F18"; break;
100+
case Term::Key::F19: s = "F19"; break;
101+
case Term::Key::F20: s = "F20"; break;
102+
case Term::Key::F21: s = "F21"; break;
103+
case Term::Key::F22: s = "F22"; break;
104+
case Term::Key::F23: s = "F23"; break;
105+
case Term::Key::F24: s = "F24"; break;
106+
default: s = "Unknown:" + std::to_string(key);
107+
}
108+
}
109+
std::cout << "Key: " << s << " (" << key << ") " << std::endl;
110+
break;
111+
}
112+
case Term::Event::Type::CopyPaste:
113+
{
114+
std::string key_str{event};
115+
if(!key_str.empty() && key_str[0] == '\033')
116+
{
117+
std::cout << "You discovered a key combination not yet managed by cpp-terminal (";
118+
for(std::size_t i = 0; i != key_str.size(); ++i) std::cout << static_cast<std::int32_t>(key_str[i]) << " ";
119+
std::cout << ").\nPlease report key combination pressed to " << Term::Homepage << std::endl;
120+
}
90121
}
91122
}
92-
std::cout << "Key: " << s << std::endl;
93123
}
94124
}
95125
catch(const Term::Exception& re)

examples/kilo.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,9 @@ char* editorPrompt(const char* prompt, void (*callback)(char*, int))
748748
editorSetStatusMessage(prompt, buf);
749749
editorRefreshScreen();
750750

751-
Term::Key c = Term::read_key();
751+
Term::Key c = Term::read_event();
752+
753+
if(c) continue;
752754
if(c == Term::Key::DEL || c == Term::Key::CTRL + 'h' || c == Term::Key::BACKSPACE)
753755
{
754756
if(buflen != 0) buf[--buflen] = '\0';
@@ -823,11 +825,10 @@ bool editorProcessKeypress()
823825
{
824826
static int quit_times = KILO_QUIT_TIMES;
825827

826-
Term::Key c = Term::read_key();
827-
828+
Term::Key c;
829+
while((c = Term::read_event()).empty()) continue; //NEEDED for windows (FIXME ?)
828830
switch(c)
829831
{
830-
case Term::Key::NO_KEY: break;
831832
case Term::Key::ENTER: editorInsertNewline(); break;
832833

833834
case Term::Key::CTRL_Q:

examples/menu.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ int main()
8383
while(on)
8484
{
8585
render(std::get<0>(term_size), std::get<1>(term_size), h, w, pos);
86-
Term::Event event = Term::read_key();
86+
Term::Event event = Term::read_event();
8787
switch(event.type())
8888
{
8989
case Term::Event::Type::Key:

0 commit comments

Comments
 (0)