mosh-client: Make terminal escape character configurable
Uses environment variable MOSH_ESCAPE_KEY. Defaults to current Ctrl-^ which is somewhat problematic for many non-US keyboards. Signed-off-by: Timo J. Rinne <tri@iki.fi> Closes #425. Closes #215.
This commit is contained in:
committed by
Keith Winstein
parent
4792992afa
commit
f960a8bcf5
+79
-11
@@ -121,6 +121,72 @@ void STMClient::init( void )
|
||||
overlays.set_title_prefix( wstring( L"[mosh] " ) );
|
||||
}
|
||||
|
||||
/* Set terminal escape key. */
|
||||
const char *escape_key_env;
|
||||
if ( (escape_key_env = getenv( "MOSH_ESCAPE_KEY" )) != NULL ) {
|
||||
if ( strlen( escape_key_env ) == 1 ) {
|
||||
escape_key = (int)escape_key_env[0];
|
||||
if ( (escape_key > 0) || (escape_key < 128) ) {
|
||||
if ( escape_key < 32 ) {
|
||||
/* If escape is ctrl-something, pass it with repeating the key without ctrl. */
|
||||
escape_pass_key = escape_key + (int)'@';
|
||||
} else {
|
||||
/* If escape is something else, pass it with repeating the key itself. */
|
||||
escape_pass_key = escape_key;
|
||||
}
|
||||
if ( escape_pass_key >= 'A' && escape_pass_key <= 'Z' ) {
|
||||
/* If escape pass is an upper case character, define optional version
|
||||
as lower case of the same. */
|
||||
escape_pass_key2 = escape_pass_key + (int)'a' - (int)'A';
|
||||
} else {
|
||||
escape_pass_key2 = escape_pass_key;
|
||||
}
|
||||
} else {
|
||||
escape_key = 0x1E;
|
||||
escape_pass_key = '^';
|
||||
escape_pass_key2 = '^';
|
||||
}
|
||||
} else if ( strlen( escape_key_env ) == 0 ) {
|
||||
escape_key = -1;
|
||||
} else {
|
||||
escape_key = 0x1E;
|
||||
escape_pass_key = '^';
|
||||
escape_pass_key2 = '^';
|
||||
}
|
||||
} else {
|
||||
escape_key = 0x1E;
|
||||
escape_pass_key = '^';
|
||||
escape_pass_key2 = '^';
|
||||
}
|
||||
|
||||
/* There are so many better ways to shoot oneself into leg than
|
||||
setting escape key to Ctrl-C, Ctrl-D, NewLine, Ctrl-L or CarriageReturn
|
||||
that we just won't allow that. */
|
||||
if ( escape_key == 0x03 || escape_key == 0x04 || escape_key == 0x0A || escape_key == 0x0C || escape_key == 0x0D ) {
|
||||
escape_key = 0x1E;
|
||||
escape_pass_key = '^';
|
||||
escape_pass_key2 = '^';
|
||||
}
|
||||
|
||||
/* Adjust escape help differently if escape is a control character. */
|
||||
if ( escape_key > 0 ) {
|
||||
char escape_pass_name_buf[16];
|
||||
char escape_key_name_buf[16];
|
||||
sprintf(escape_pass_name_buf, "\"%c\"", escape_pass_key);
|
||||
if (escape_key < 32) {
|
||||
sprintf(escape_key_name_buf, "Ctrl-%c", escape_pass_key);
|
||||
escape_requires_lf = false;
|
||||
} else {
|
||||
sprintf(escape_key_name_buf, "\"%c\"", escape_key);
|
||||
escape_requires_lf = true;
|
||||
}
|
||||
string tmp;
|
||||
tmp = string( escape_pass_name_buf );
|
||||
wstring escape_pass_name = std::wstring(tmp.begin(), tmp.end());
|
||||
tmp = string( escape_key_name_buf );
|
||||
wstring escape_key_name = std::wstring(tmp.begin(), tmp.end());
|
||||
escape_key_help = L"Commands: Ctrl-Z suspends, \".\" quits, " + escape_pass_name + L" gives literal " + escape_key_name;
|
||||
}
|
||||
wchar_t tmp[ 128 ];
|
||||
swprintf( tmp, 128, L"Nothing received from server on UDP port %d.", port );
|
||||
connecting_notification = wstring( tmp );
|
||||
@@ -255,8 +321,6 @@ bool STMClient::process_user_input( int fd )
|
||||
|
||||
overlays.get_prediction_engine().new_user_byte( the_byte, *local_framebuffer );
|
||||
|
||||
const static wstring help_message( L"Commands: Ctrl-Z suspends, \".\" quits, \"^\" gives literal Ctrl-^" );
|
||||
|
||||
if ( quit_sequence_started ) {
|
||||
if ( the_byte == '.' ) { /* Quit sequence is Ctrl-^ . */
|
||||
if ( network->has_remote_addr() && (!network->shutdown_in_progress()) ) {
|
||||
@@ -266,7 +330,7 @@ bool STMClient::process_user_input( int fd )
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if ( the_byte == 0x1a ) { /* Suspend sequence is Ctrl-^ Ctrl-Z */
|
||||
} else if ( the_byte == 0x1a ) { /* Suspend sequence is escape_key Ctrl-Z */
|
||||
/* Restore terminal and terminal-driver state */
|
||||
swrite( STDOUT_FILENO, display.close().c_str() );
|
||||
|
||||
@@ -283,30 +347,34 @@ bool STMClient::process_user_input( int fd )
|
||||
kill( 0, SIGSTOP );
|
||||
|
||||
resume();
|
||||
} else if ( the_byte == '^' ) {
|
||||
/* Emulation sequence to type Ctrl-^ is Ctrl-^ ^ */
|
||||
network->get_current_state().push_back( Parser::UserByte( 0x1E ) );
|
||||
} else if ( (the_byte == escape_pass_key) || (the_byte == escape_pass_key2) ) {
|
||||
/* Emulation sequence to type escape_key is escape_key +
|
||||
escape_pass_key (that is escape key without Ctrl) */
|
||||
network->get_current_state().push_back( Parser::UserByte( escape_key ) );
|
||||
} else {
|
||||
/* Ctrl-^ followed by anything other than . and ^ gets sent literally */
|
||||
network->get_current_state().push_back( Parser::UserByte( 0x1E ) );
|
||||
/* Escape key followed by anything other than . and ^ gets sent literally */
|
||||
network->get_current_state().push_back( Parser::UserByte( escape_key ) );
|
||||
network->get_current_state().push_back( Parser::UserByte( the_byte ) );
|
||||
}
|
||||
|
||||
quit_sequence_started = false;
|
||||
|
||||
if ( overlays.get_notification_engine().get_notification_string() == help_message ) {
|
||||
if ( overlays.get_notification_engine().get_notification_string() == escape_key_help ) {
|
||||
overlays.get_notification_engine().set_notification_string( L"" );
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
quit_sequence_started = (the_byte == 0x1E);
|
||||
quit_sequence_started = (escape_key > 0) && (the_byte == escape_key) && (lf_entered || (! escape_requires_lf));
|
||||
if ( quit_sequence_started ) {
|
||||
overlays.get_notification_engine().set_notification_string( help_message, true, false );
|
||||
lf_entered = false;
|
||||
overlays.get_notification_engine().set_notification_string( escape_key_help, true, false );
|
||||
continue;
|
||||
}
|
||||
|
||||
lf_entered = ( (the_byte == 0x0A) || (the_byte == 0x0D) ); /* LineFeed, Ctrl-J, '\n' or CarriageReturn, Ctrl-M, '\r' */
|
||||
|
||||
if ( the_byte == 0x0C ) { /* Ctrl-L */
|
||||
repaint_requested = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user