Allow non-inserting prediction.

This may be useful for users who find prediction's activity right of
the cursor distracting.

Prediction underscoring is still a little weird sometimes, it replays
a history of known/unknown changes as acks come in from the server.
This commit is contained in:
John Hood
2015-06-07 04:44:21 -04:00
parent 91de8901f5
commit 8aac3cc927
5 changed files with 52 additions and 20 deletions
+8
View File
@@ -65,6 +65,8 @@ my $server = 'mosh-server';
my $predict = undef; my $predict = undef;
my $overwrite = 0;
my $bind_ip = undef; my $bind_ip = undef;
my $use_remote_ip = 'proxy'; my $use_remote_ip = 'proxy';
@@ -97,6 +99,8 @@ qq{Usage: $0 [options] [--] [user@]host [command...]
-n --predict=never never use local echo -n --predict=never never use local echo
--predict=experimental aggressively echo even when incorrect --predict=experimental aggressively echo even when incorrect
-o --overwrite prediction overwrites instead of inserting
-4 --family=inet use IPv4 only -4 --family=inet use IPv4 only
-6 --family=inet6 use IPv6 only -6 --family=inet6 use IPv6 only
--family=auto autodetect network type for single-family hosts only --family=auto autodetect network type for single-family hosts only
@@ -150,6 +154,7 @@ sub predict_check {
GetOptions( 'client=s' => \$client, GetOptions( 'client=s' => \$client,
'server=s' => \$server, 'server=s' => \$server,
'predict=s' => \$predict, 'predict=s' => \$predict,
'overwrite|o!' => \$overwrite,
'port=s' => \$port_request, 'port=s' => \$port_request,
'a' => sub { $predict = 'always' }, 'a' => sub { $predict = 'always' },
'n' => sub { $predict = 'never' }, 'n' => sub { $predict = 'never' },
@@ -200,6 +205,9 @@ if (!$have_ipv6) {
# Force IPv4. # Force IPv4.
$family = "inet"; $family = "inet";
} }
if ( $overwrite ) {
$ENV{ "MOSH_PREDICTION_OVERWRITE" } = "yes";
}
if ( defined $port_request ) { if ( defined $port_request ) {
if ( $port_request =~ m{^(\d+)(:(\d+))?$} ) { if ( $port_request =~ m{^(\d+)(:(\d+))?$} ) {
+5 -1
View File
@@ -175,6 +175,10 @@ int main( int argc, char *argv[] )
char *predict_mode = getenv( "MOSH_PREDICTION_DISPLAY" ); char *predict_mode = getenv( "MOSH_PREDICTION_DISPLAY" );
/* can be NULL */ /* can be NULL */
/* Read prediction insertion preference */
char *predict_overwrite = getenv( "MOSH_PREDICTION_OVERWRITE" );
/* can be NULL */
char *key = strdup( env_key ); char *key = strdup( env_key );
if ( key == NULL ) { if ( key == NULL ) {
perror( "strdup" ); perror( "strdup" );
@@ -191,7 +195,7 @@ int main( int argc, char *argv[] )
bool success = false; bool success = false;
try { try {
STMClient client( ip, desired_port, key, predict_mode, verbose ); STMClient client( ip, desired_port, key, predict_mode, verbose, predict_overwrite );
client.init(); client.init();
try { try {
+4 -1
View File
@@ -84,7 +84,7 @@ private:
void resume( void ); /* restore state after SIGCONT */ void resume( void ); /* restore state after SIGCONT */
public: public:
STMClient( const char *s_ip, const char *s_port, const char *s_key, const char *predict_mode, unsigned int s_verbose ) STMClient( const char *s_ip, const char *s_port, const char *s_key, const char *predict_mode, unsigned int s_verbose, const char *predict_overwrite )
: ip( s_ip ? s_ip : "" ), port( s_port ? s_port : "" ), : ip( s_ip ? s_ip : "" ), port( s_port ? s_port : "" ),
key( s_key ? s_key : "" ), key( s_key ? s_key : "" ),
escape_key( 0x1E ), escape_pass_key( '^' ), escape_pass_key2( '^' ), escape_key( 0x1E ), escape_pass_key( '^' ), escape_pass_key2( '^' ),
@@ -117,6 +117,9 @@ public:
exit( 1 ); exit( 1 );
} }
} }
if ( predict_overwrite && !strcmp( predict_overwrite, "yes" ) ) {
overlays.get_prediction_engine().set_predict_overwrite( true );
}
} }
void init( void ); void init( void );
+30 -16
View File
@@ -698,32 +698,45 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb )
cursor().col--; cursor().col--;
cursor().expire( local_frame_sent + 1, now ); cursor().expire( local_frame_sent + 1, now );
for ( int i = cursor().col; i < fb.ds.get_width(); i++ ) { if ( predict_overwrite ) {
ConditionalOverlayCell &cell = the_row.overlay_cells[ i ]; ConditionalOverlayCell &cell = the_row.overlay_cells[ cursor().col ];
cell.reset_with_orig(); cell.reset_with_orig();
cell.active = true; cell.active = true;
cell.tentative_until_epoch = prediction_epoch; cell.tentative_until_epoch = prediction_epoch;
cell.expire( local_frame_sent + 1, now ); cell.expire( local_frame_sent + 1, now );
cell.original_contents.push_back( *fb.get_cell( cursor().row, i ) ); const Cell orig_cell = *fb.get_cell();
cell.original_contents.push_back( orig_cell );
cell.replacement = orig_cell;
cell.replacement.clear();
cell.replacement.append(' ');
} else {
for ( int i = cursor().col; i < fb.ds.get_width(); i++ ) {
ConditionalOverlayCell &cell = the_row.overlay_cells[ i ];
if ( i + 2 < fb.ds.get_width() ) { cell.reset_with_orig();
ConditionalOverlayCell &next_cell = the_row.overlay_cells[ i + 1 ]; cell.active = true;
const Cell *next_cell_actual = fb.get_cell( cursor().row, i + 1 ); cell.tentative_until_epoch = prediction_epoch;
cell.expire( local_frame_sent + 1, now );
cell.original_contents.push_back( *fb.get_cell( cursor().row, i ) );
if ( next_cell.active ) { if ( i + 2 < fb.ds.get_width() ) {
if ( next_cell.unknown ) { ConditionalOverlayCell &next_cell = the_row.overlay_cells[ i + 1 ];
cell.unknown = true; const Cell *next_cell_actual = fb.get_cell( cursor().row, i + 1 );
if ( next_cell.active ) {
if ( next_cell.unknown ) {
cell.unknown = true;
} else {
cell.unknown = false;
cell.replacement = next_cell.replacement;
}
} else { } else {
cell.unknown = false; cell.unknown = false;
cell.replacement = next_cell.replacement; cell.replacement = *next_cell_actual;
} }
} else { } else {
cell.unknown = false; cell.unknown = true;
cell.replacement = *next_cell_actual;
} }
} else {
cell.unknown = true;
} }
} }
} }
@@ -746,7 +759,8 @@ void PredictionEngine::new_user_byte( char the_byte, const Framebuffer &fb )
} }
/* do the insert */ /* do the insert */
for ( int i = fb.ds.get_width() - 1; i > cursor().col; i-- ) { int rightmost_column = predict_overwrite ? cursor().col + 1 : fb.ds.get_width() - 1;
for ( int i = rightmost_column; i > cursor().col; i-- ) {
ConditionalOverlayCell &cell = the_row.overlay_cells[ i ]; ConditionalOverlayCell &cell = the_row.overlay_cells[ i ];
cell.reset_with_orig(); cell.reset_with_orig();
cell.active = true; cell.active = true;
+4 -1
View File
@@ -262,6 +262,7 @@ namespace Overlay {
private: private:
DisplayPreference display_preference; DisplayPreference display_preference;
bool predict_overwrite;
bool active( void ) const; bool active( void ) const;
@@ -272,6 +273,7 @@ namespace Overlay {
public: public:
void set_display_preference( DisplayPreference s_pref ) { display_preference = s_pref; } void set_display_preference( DisplayPreference s_pref ) { display_preference = s_pref; }
void set_predict_overwrite( bool overwrite ) { predict_overwrite = overwrite; }
void apply( Framebuffer &fb ) const; void apply( Framebuffer &fb ) const;
void new_user_byte( char the_byte, const Framebuffer &fb ); void new_user_byte( char the_byte, const Framebuffer &fb );
@@ -302,7 +304,8 @@ namespace Overlay {
last_quick_confirmation( 0 ), last_quick_confirmation( 0 ),
send_interval( 250 ), send_interval( 250 ),
last_height( 0 ), last_width( 0 ), last_height( 0 ), last_width( 0 ),
display_preference( Adaptive ) display_preference( Adaptive ),
predict_overwrite( false )
{ {
} }
}; };