From f8b4c1b3893fedcb50241af3f5d5e9d6a786ede9 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Thu, 12 Jul 2012 12:51:47 -0700 Subject: [PATCH] First pass at making autosuggestions not trigger wrapping Addresses https://github.com/fish-shell/fish-shell/issues/167 --- reader.cpp | 13 ++----------- screen.cpp | 43 ++++++++++++++++++++++++++++++------------- screen.h | 9 +++++++++ 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/reader.cpp b/reader.cpp index 520bcbf5e..553c2e4b4 100644 --- a/reader.cpp +++ b/reader.cpp @@ -424,15 +424,6 @@ static void reader_repaint() //Update the indentation parser_t::principal_parser().test( data->command_line.c_str(), &data->indents[0], 0, 0 ); -#if 0 - s_write( &data->screen, - data->prompt_buff.c_str(), - data->command_line.c_str(), - &data->colors[0], - &data->indents[0], - data->buff_pos ); -#else - wcstring full_line = (data->autosuggestion.empty() ? data->command_line : data->autosuggestion); size_t len = std::max((size_t)1, full_line.size()); @@ -445,10 +436,10 @@ static void reader_repaint() s_write( &data->screen, data->prompt_buff.c_str(), full_line.c_str(), + data->command_line.size(), &colors[0], &indents[0], data->buff_pos ); -#endif data->repaint_needed = false; } @@ -2072,7 +2063,7 @@ int reader_shell_test( const wchar_t *b ) int tmp[1]; int tmp2[1]; - s_write( &data->screen, L"", L"", tmp, tmp2, 0 ); + s_write( &data->screen, L"", L"", 0, tmp, tmp2, 0 ); parser_t::principal_parser().test( b, 0, &sb, L"fish" ); fwprintf( stderr, L"%ls", sb.c_str() ); diff --git a/screen.cpp b/screen.cpp index 79b7b7d14..3e7b86c75 100644 --- a/screen.cpp +++ b/screen.cpp @@ -735,7 +735,8 @@ static int is_dumb() void s_write( screen_t *s, const wchar_t *prompt, - const wchar_t *b, + const wchar_t *commandline, + int explicit_len, const int *c, const int *indent, int cursor ) @@ -746,12 +747,11 @@ void s_write( screen_t *s, int prompt_width; int screen_width; - int max_line_width = 0; - int current_line_width = 0; + int max_line_width = 0, current_line_width = 0, newline_count = 0, explicit_portion_width = 0; CHECK( s, ); CHECK( prompt, ); - CHECK( b, ); + CHECK( commandline, ); CHECK( c, ); CHECK( indent, ); @@ -762,7 +762,7 @@ void s_write( screen_t *s, if( is_dumb() ) { char *prompt_narrow = wcs2str( prompt ); - char *buffer_narrow = wcs2str( b ); + char *buffer_narrow = wcs2str( commandline ); write_loop( 1, "\r", 1 ); write_loop( 1, prompt_narrow, strlen( prompt_narrow ) ); @@ -803,18 +803,25 @@ void s_write( screen_t *s, /* Check if we are overflowing */ - - for( i=0; b[i]; i++ ) + int last_char_that_fits = 0; + for( i=0; commandline[i]; i++ ) { - if( b[i] == L'\n' ) + if( commandline[i] == L'\n' ) { if( current_line_width > max_line_width ) max_line_width = current_line_width; current_line_width = indent[i]*INDENT_STEP; + newline_count++; } else { - current_line_width += wcwidth(b[i]); + int width = wcwidth(commandline[i]); + current_line_width += width; + if (i < explicit_len) + explicit_portion_width += width; + + if (prompt_width + current_line_width < screen_width) + last_char_that_fits = i; } } if( current_line_width > max_line_width ) @@ -822,6 +829,16 @@ void s_write( screen_t *s, s->desired.resize(0); s->desired.cursor[0] = s->desired.cursor[1] = 0; + + /* If we cannot fit with the autosuggestion, but we can fit without it, truncate the autosuggestion. We limit this check to just one line to avoid confusion; not sure how well this would work with multiple lines */ + wcstring truncated_autosuggestion_line; + if (newline_count == 0 && prompt_width + max_line_width >= screen_width && prompt_width + explicit_portion_width < screen_width) + { + max_line_width = screen_width - prompt_width - 1; + truncated_autosuggestion_line = wcstring(commandline, 0, last_char_that_fits); + truncated_autosuggestion_line.push_back(ellipsis_char); + commandline = truncated_autosuggestion_line.c_str(); + } /* If overflowing, give the prompt its own line to improve the @@ -842,7 +859,7 @@ void s_write( screen_t *s, - for( i=0; b[i]; i++ ) + for( i=0; commandline[i]; i++ ) { int col = c[i]; @@ -857,9 +874,9 @@ void s_write( screen_t *s, cursor_arr[1] = s->desired.cursor[1]; } - s_desired_append_char( s, b[i], col, indent[i], prompt_width ); + s_desired_append_char( s, commandline[i], col, indent[i], prompt_width ); - if( i== cursor && s->desired.cursor[1] != cursor_arr[1] && b[i] != L'\n' ) + if( i== cursor && s->desired.cursor[1] != cursor_arr[1] && commandline[i] != L'\n' ) { /* Ugh. We are placed exactly at the wrapping point of a @@ -867,7 +884,7 @@ void s_write( screen_t *s, cursor won't be on the ellipsis which looks unintuitive. */ - cursor_arr[0] = s->desired.cursor[0] - wcwidth(b[i]); + cursor_arr[0] = s->desired.cursor[0] - wcwidth(commandline[i]); cursor_arr[1] = s->desired.cursor[1]; } diff --git a/screen.h b/screen.h index 0f930a178..a8ce72b5c 100644 --- a/screen.h +++ b/screen.h @@ -132,10 +132,19 @@ class screen_t will use it's knowlege of the current contents of the screen in order to render the desired output using as few terminal commands as possible. + + \param s the screen on which to write + \param prompt the prompt to prepend to the command line + \param commandline the command line + \param explicit_len the number of characters of the "explicit" (non-autosuggestion) portion of the command line + \param colors the colors to use for the comand line + \param indent the indent to use for the command line + \param cursor_pos where the cursor is */ void s_write( screen_t *s, const wchar_t *prompt, const wchar_t *commandline, + int explicit_len, const int *colors, const int *indent, int cursor_pos );