diff options
author | 2012-11-18 16:30:30 -0800 | |
---|---|---|
committer | 2012-11-18 16:30:30 -0800 | |
commit | 9992b8eb0e3366ff8a3948aa0b66a19c3c12c737 (patch) | |
tree | 6dda0fef85812016fbba9ea067c9d586092b506d /fish_pager.cpp | |
parent | bab69f26724028d16054a3daf5c78aad7c67bb2d (diff) |
Apply new indentation, brace, and whitespace style
Diffstat (limited to 'fish_pager.cpp')
-rw-r--r-- | fish_pager.cpp | 1874 |
1 files changed, 939 insertions, 935 deletions
diff --git a/fish_pager.cpp b/fish_pager.cpp index 88ef8d3b..d8dd4210 100644 --- a/fish_pager.cpp +++ b/fish_pager.cpp @@ -64,40 +64,40 @@ enum { - LINE_UP = R_NULL+1, - LINE_DOWN, - PAGE_UP, - PAGE_DOWN + LINE_UP = R_NULL+1, + LINE_DOWN, + PAGE_UP, + PAGE_DOWN } - ; +; enum { - HIGHLIGHT_PAGER_PREFIX, - HIGHLIGHT_PAGER_COMPLETION, - HIGHLIGHT_PAGER_DESCRIPTION, - HIGHLIGHT_PAGER_PROGRESS, - HIGHLIGHT_PAGER_SECONDARY + HIGHLIGHT_PAGER_PREFIX, + HIGHLIGHT_PAGER_COMPLETION, + HIGHLIGHT_PAGER_DESCRIPTION, + HIGHLIGHT_PAGER_PROGRESS, + HIGHLIGHT_PAGER_SECONDARY } - ; +; enum { - /* - Returnd by the pager if no more displaying is needed - */ - PAGER_DONE, - /* - Returned by the pager if the completions would not fit in the specified number of columns - */ - PAGER_RETRY, - /* - Returned by the pager if the terminal changes size - */ - PAGER_RESIZE + /* + Returnd by the pager if no more displaying is needed + */ + PAGER_DONE, + /* + Returned by the pager if the completions would not fit in the specified number of columns + */ + PAGER_RETRY, + /* + Returned by the pager if the terminal changes size + */ + PAGER_RESIZE } - ; +; /** The minimum width (in characters) the terminal may have for fish_pager to not refuse showing the completions @@ -150,13 +150,13 @@ static std::vector<char> pager_buffer; */ static const wchar_t *hightlight_var[] = { - L"fish_pager_color_prefix", - L"fish_pager_color_completion", - L"fish_pager_color_description", - L"fish_pager_color_progress", - L"fish_pager_color_secondary" + L"fish_pager_color_prefix", + L"fish_pager_color_completion", + L"fish_pager_color_description", + L"fish_pager_color_progress", + L"fish_pager_color_secondary" } - ; +; /** This string contains the text that should be sent back to the calling program @@ -172,58 +172,58 @@ static FILE *out_file; */ struct comp_t { - /** - The list of all completin strings this entry applies to - */ - wcstring_list_t comp; - /** - The description - */ - wcstring desc; - /** - On-screen width of the completion string - */ - int comp_width; - /** - On-screen width of the description information - */ - int desc_width; - /** - Preffered total width - */ - int pref_width; - /** - Minimum acceptable width - */ - int min_width; + /** + The list of all completin strings this entry applies to + */ + wcstring_list_t comp; + /** + The description + */ + wcstring desc; + /** + On-screen width of the completion string + */ + int comp_width; + /** + On-screen width of the description information + */ + int desc_width; + /** + Preffered total width + */ + int pref_width; + /** + Minimum acceptable width + */ + int min_width; }; /** This function translates from a highlight code to a specific color by check invironement variables */ -static rgb_color_t get_color( int highlight ) +static rgb_color_t get_color(int highlight) { - const wchar_t *val; + const wchar_t *val; - if( highlight < 0 ) - return rgb_color_t::normal(); - if( highlight >= (5) ) - return rgb_color_t::normal(); + if (highlight < 0) + return rgb_color_t::normal(); + if (highlight >= (5)) + return rgb_color_t::normal(); - val = wgetenv( hightlight_var[highlight]); + val = wgetenv(hightlight_var[highlight]); - if( !val ) - { - val = env_universal_get( hightlight_var[highlight]); - } + if (!val) + { + val = env_universal_get(hightlight_var[highlight]); + } - if( !val ) - { - return rgb_color_t::normal(); - } + if (!val) + { + return rgb_color_t::normal(); + } - return parse_color( val, false ); + return parse_color(val, false); } /** @@ -232,15 +232,15 @@ static rgb_color_t get_color( int highlight ) terminal size, so this function should be called when the terminal changes size. */ -static void recalc_width( std::vector<comp_t *> &lst, const wchar_t *prefix ) +static void recalc_width(std::vector<comp_t *> &lst, const wchar_t *prefix) { - for( size_t i=0; i<lst.size(); i++ ) - { - comp_t *c = lst.at(i); + for (size_t i=0; i<lst.size(); i++) + { + comp_t *c = lst.at(i); - c->min_width = mini( c->desc_width, maxi(0,termsize.ws_col/3 - 2)) + - mini( c->desc_width, maxi(0,termsize.ws_col/5 - 4)) +4; - } + c->min_width = mini(c->desc_width, maxi(0,termsize.ws_col/3 - 2)) + + mini(c->desc_width, maxi(0,termsize.ws_col/5 - 4)) +4; + } } @@ -248,27 +248,27 @@ static void recalc_width( std::vector<comp_t *> &lst, const wchar_t *prefix ) Test if the specified character sequence has been entered on the keyboard */ -static int try_sequence( const char *seq ) +static int try_sequence(const char *seq) { - int j, k; - wint_t c=0; + int j, k; + wint_t c=0; - for( j=0; - seq[j] != '\0' && seq[j] == (c=input_common_readch( j>0 )); - j++ ) - ; + for (j=0; + seq[j] != '\0' && seq[j] == (c=input_common_readch(j>0)); + j++) + ; - if( seq[j] == '\0' ) - { - return 1; - } - else - { - input_common_unreadch(c); - for(k=j-1; k>=0; k--) - input_common_unreadch(seq[k]); - } - return 0; + if (seq[j] == '\0') + { + return 1; + } + else + { + input_common_unreadch(c); + for (k=j-1; k>=0; k--) + input_common_unreadch(seq[k]); + } + return 0; } /** @@ -276,75 +276,75 @@ static int try_sequence( const char *seq ) */ static wint_t readch() { - struct mapping - { - const char *seq; - wint_t bnd; - } - ; - - struct mapping m[]= + struct mapping { - { - "\x1b[A", LINE_UP - } - , - { - key_up, LINE_UP - } - , - { - "\x1b[B", LINE_DOWN - } - , - { - key_down, LINE_DOWN - } - , - { - key_ppage, PAGE_UP - } - , - { - key_npage, PAGE_DOWN - } - , - { - " ", PAGE_DOWN - } - , - { - "\t", PAGE_DOWN - } - , - { - 0, 0 - } - + const char *seq; + wint_t bnd; } - ; - int i; + ; - for( i=0; m[i].bnd; i++ ) - { - if( !m[i].seq ) + struct mapping m[]= { - continue; + { + "\x1b[A", LINE_UP + } + , + { + key_up, LINE_UP + } + , + { + "\x1b[B", LINE_DOWN + } + , + { + key_down, LINE_DOWN + } + , + { + key_ppage, PAGE_UP + } + , + { + key_npage, PAGE_DOWN + } + , + { + " ", PAGE_DOWN + } + , + { + "\t", PAGE_DOWN + } + , + { + 0, 0 + } + } + ; + int i; - if( try_sequence(m[i].seq ) ) - return m[i].bnd; - } - return input_common_readch(0); + for (i=0; m[i].bnd; i++) + { + if (!m[i].seq) + { + continue; + } + + if (try_sequence(m[i].seq)) + return m[i].bnd; + } + return input_common_readch(0); } /** Write specified character to the output buffer \c pager_buffer */ -static int pager_buffered_writer( char c) +static int pager_buffered_writer(char c) { - pager_buffer.push_back(c); - return 0; + pager_buffer.push_back(c); + return 0; } /** @@ -352,8 +352,9 @@ static int pager_buffered_writer( char c) */ static void pager_flush() { - if (! pager_buffer.empty()) { - write_loop( 1, & pager_buffer.at(0), pager_buffer.size() * sizeof(char) ); + if (! pager_buffer.empty()) + { + write_loop(1, & pager_buffer.at(0), pager_buffer.size() * sizeof(char)); pager_buffer.clear(); } } @@ -366,99 +367,99 @@ static void pager_flush() \param max the maximum space that may be used for printing \param has_more if this flag is true, this is not the entire string, and the string should be ellisiszed even if the string fits but takes up the whole space. */ -static int print_max( const wchar_t *str, int max, int has_more ) +static int print_max(const wchar_t *str, int max, int has_more) { - int i; - int written = 0; - for( i=0; str[i]; i++ ) - { - - if( written + wcwidth(str[i]) > max ) - break; - if( ( written + wcwidth(str[i]) == max) && (has_more || str[i+1]) ) + int i; + int written = 0; + for (i=0; str[i]; i++) { - writech( ellipsis_char ); - written += wcwidth(ellipsis_char ); - break; - } - writech( str[i] ); - written+= wcwidth( str[i] ); - } - return written; + if (written + wcwidth(str[i]) > max) + break; + if ((written + wcwidth(str[i]) == max) && (has_more || str[i+1])) + { + writech(ellipsis_char); + written += wcwidth(ellipsis_char); + break; + } + + writech(str[i]); + written+= wcwidth(str[i]); + } + return written; } /** Print the specified item using at the specified amount of space */ -static void completion_print_item( const wchar_t *prefix, comp_t *c, int width, bool secondary ) +static void completion_print_item(const wchar_t *prefix, comp_t *c, int width, bool secondary) { - int comp_width=0, desc_width=0; - int written=0; - - if( c->pref_width <= width ) - { - /* - The entry fits, we give it as much space as it wants - */ - comp_width = c->comp_width; - desc_width = c->desc_width; - } - else - { - /* - The completion and description won't fit on the - allocated space. Give a maximum of 2/3 of the - space to the completion, and whatever is left to - the description. - */ - int desc_all = c->desc_width?c->desc_width+4:0; + int comp_width=0, desc_width=0; + int written=0; - comp_width = maxi( mini( c->comp_width, - 2*(width-4)/3 ), - width - desc_all ); - if( c->desc_width ) - desc_width = width-comp_width-4; + if (c->pref_width <= width) + { + /* + The entry fits, we give it as much space as it wants + */ + comp_width = c->comp_width; + desc_width = c->desc_width; + } else - c->desc_width=0; + { + /* + The completion and description won't fit on the + allocated space. Give a maximum of 2/3 of the + space to the completion, and whatever is left to + the description. + */ + int desc_all = c->desc_width?c->desc_width+4:0; + + comp_width = maxi(mini(c->comp_width, + 2*(width-4)/3), + width - desc_all); + if (c->desc_width) + desc_width = width-comp_width-4; + else + c->desc_width=0; - } + } rgb_color_t bg = secondary ? get_color(HIGHLIGHT_PAGER_SECONDARY) : rgb_color_t::normal(); - for( size_t i=0; i<c->comp.size(); i++ ) - { + for (size_t i=0; i<c->comp.size(); i++) + { const wcstring &comp = c->comp.at(i); - if( i != 0 ) - written += print_max( L" ", comp_width - written, 2 ); - set_color( get_color(HIGHLIGHT_PAGER_PREFIX), bg ); - written += print_max( prefix, comp_width - written, comp.empty()?0:1 ); - set_color( get_color(HIGHLIGHT_PAGER_COMPLETION), bg); - written += print_max( comp.c_str(), comp_width - written, i!=(c->comp.size()-1) ); - } - - - if( desc_width ) - { - while( written < (width-desc_width-2)) + if (i != 0) + written += print_max(L" ", comp_width - written, 2); + set_color(get_color(HIGHLIGHT_PAGER_PREFIX), bg); + written += print_max(prefix, comp_width - written, comp.empty()?0:1); + set_color(get_color(HIGHLIGHT_PAGER_COMPLETION), bg); + written += print_max(comp.c_str(), comp_width - written, i!=(c->comp.size()-1)); + } + + + if (desc_width) { - written++; - writech( L' '); + while (written < (width-desc_width-2)) + { + written++; + writech(L' '); + } + set_color(get_color(HIGHLIGHT_PAGER_DESCRIPTION), bg); + written += print_max(L"(", 1, 0); + written += print_max(c->desc.c_str(), desc_width, 0); + written += print_max(L")", 1, 0); } - set_color( get_color( HIGHLIGHT_PAGER_DESCRIPTION ), bg); - written += print_max( L"(", 1, 0 ); - written += print_max( c->desc.c_str(), desc_width, 0 ); - written += print_max( L")", 1, 0 ); - } - else - { - while( written < width ) + else { - written++; - writech( L' '); + while (written < width) + { + written++; + writech(L' '); + } } - } - if ( secondary ) - set_color( rgb_color_t::normal(), rgb_color_t::normal() ); + if (secondary) + set_color(rgb_color_t::normal(), rgb_color_t::normal()); } /** @@ -474,38 +475,38 @@ static void completion_print_item( const wchar_t *prefix, comp_t *c, int width, \param is_quoted Whether to print the completions are in a quoted environment */ -static void completion_print( int cols, - int *width, - int row_start, - int row_stop, - wchar_t *prefix, - int is_quoted, - const std::vector<comp_t *> &lst ) +static void completion_print(int cols, + int *width, + int row_start, + int row_stop, + wchar_t *prefix, + int is_quoted, + const std::vector<comp_t *> &lst) { - size_t rows = (lst.size()-1)/cols+1; - size_t i, j; + size_t rows = (lst.size()-1)/cols+1; + size_t i, j; - for( i = row_start; i<row_stop; i++ ) - { - for( j = 0; j < cols; j++ ) + for (i = row_start; i<row_stop; i++) { - comp_t *el; + for (j = 0; j < cols; j++) + { + comp_t *el; - int is_last = (j==(cols-1)); + int is_last = (j==(cols-1)); - if( lst.size() <= j*rows + i ) - continue; + if (lst.size() <= j*rows + i) + continue; - el = lst.at(j*rows + i ); + el = lst.at(j*rows + i); - completion_print_item( prefix, el, width[j] - (is_last?0:2), i%2 ); + completion_print_item(prefix, el, width[j] - (is_last?0:2), i%2); - if( !is_last) - writestr( L" " ); + if (!is_last) + writestr(L" "); + } + writech(L'\n'); } - writech( L'\n' ); - } } @@ -527,302 +528,302 @@ static void completion_print( int cols, \return one of PAGER_RETRY, PAGER_DONE and PAGER_RESIZE */ -static int completion_try_print( int cols, - wchar_t *prefix, - int is_quoted, - std::vector<comp_t *> &lst ) +static int completion_try_print(int cols, + wchar_t *prefix, + int is_quoted, + std::vector<comp_t *> &lst) { - /* - The calculated preferred width of each column - */ - int pref_width[PAGER_MAX_COLS]; - /* - The calculated minimum width of each column - */ - int min_width[PAGER_MAX_COLS]; - /* - If the list can be printed with this width, width will contain the width of each column - */ - int *width=pref_width; - /* - Set to one if the list should be printed at this width - */ - int print=0; - - long i, j; - - int rows = (int)((lst.size()-1)/cols+1); - - int pref_tot_width=0; - int min_tot_width = 0; - int res=PAGER_RETRY; - /* - Skip completions on tiny terminals - */ - - if( termsize.ws_col < PAGER_MIN_WIDTH ) - return PAGER_DONE; - - memset( pref_width, 0, sizeof(pref_width) ); - memset( min_width, 0, sizeof(min_width) ); - - /* Calculate how wide the list would be */ - for( j = 0; j < cols; j++ ) - { - for( i = 0; i<rows; i++ ) - { - int pref,min; - comp_t *c; - if( lst.size() <= j*rows + i ) - continue; - - c = lst.at(j*rows + i ); - pref = c->pref_width; - min = c->min_width; - - if( j != cols-1 ) - { - pref += 2; - min += 2; - } - min_width[j] = maxi( min_width[j], - min ); - pref_width[j] = maxi( pref_width[j], - pref ); - } - min_tot_width += min_width[j]; - pref_tot_width += pref_width[j]; - } - /* - Force fit if one column - */ - if( cols == 1) - { - if( pref_tot_width > termsize.ws_col ) + /* + The calculated preferred width of each column + */ + int pref_width[PAGER_MAX_COLS]; + /* + The calculated minimum width of each column + */ + int min_width[PAGER_MAX_COLS]; + /* + If the list can be printed with this width, width will contain the width of each column + */ + int *width=pref_width; + /* + Set to one if the list should be printed at this width + */ + int print=0; + + long i, j; + + int rows = (int)((lst.size()-1)/cols+1); + + int pref_tot_width=0; + int min_tot_width = 0; + int res=PAGER_RETRY; + /* + Skip completions on tiny terminals + */ + + if (termsize.ws_col < PAGER_MIN_WIDTH) + return PAGER_DONE; + + memset(pref_width, 0, sizeof(pref_width)); + memset(min_width, 0, sizeof(min_width)); + + /* Calculate how wide the list would be */ + for (j = 0; j < cols; j++) { - pref_width[0] = termsize.ws_col; + for (i = 0; i<rows; i++) + { + int pref,min; + comp_t *c; + if (lst.size() <= j*rows + i) + continue; + + c = lst.at(j*rows + i); + pref = c->pref_width; + min = c->min_width; + + if (j != cols-1) + { + pref += 2; + min += 2; + } + min_width[j] = maxi(min_width[j], + min); + pref_width[j] = maxi(pref_width[j], + pref); + } + min_tot_width += min_width[j]; + pref_tot_width += pref_width[j]; } - width = pref_width; - print=1; - } - else if( pref_tot_width <= termsize.ws_col ) - { - /* Terminal is wide enough. Print the list! */ - width = pref_width; - print=1; - } - else - { - long next_rows = (lst.size()-1)/(cols-1)+1; -/* fwprintf( stderr, - L"cols %d, min_tot %d, term %d, rows=%d, nextrows %d, termrows %d, diff %d\n", - cols, - min_tot_width, termsize.ws_col, - rows, next_rows, termsize.ws_row, - pref_tot_width-termsize.ws_col ); -*/ - if( min_tot_width < termsize.ws_col && - ( ( (rows < termsize.ws_row) && (next_rows >= termsize.ws_row ) ) || - ( pref_tot_width-termsize.ws_col< 4 && cols < 3 ) ) ) + /* + Force fit if one column + */ + if (cols == 1) { - /* - Terminal almost wide enough, or squeezing makes the - whole list fit on-screen. - - This part of the code is really important. People hate - having to scroll through the completion list. In cases - where there are a huge number of completions, it can't - be helped, but it is not uncommon for the completions to - _almost_ fit on one screen. In those cases, it is almost - always desirable to 'squeeze' the completions into a - single page. - - If we are using N columns and can get everything to - fit using squeezing, but everything would also fit - using N-1 columns, don't try. - */ - - int tot_width = min_tot_width; - width = min_width; - - while( tot_width < termsize.ws_col ) - { - for( i=0; (i<cols) && ( tot_width < termsize.ws_col ); i++ ) + if (pref_tot_width > termsize.ws_col) { - if( width[i] < pref_width[i] ) - { - width[i]++; - tot_width++; - } + pref_width[0] = termsize.ws_col; } - } - print=1; + width = pref_width; + print=1; } - } - - if( print ) - { - res=PAGER_DONE; - if( rows < termsize.ws_row ) + else if (pref_tot_width <= termsize.ws_col) { - /* List fits on screen. Print it and leave */ - if( is_ca_mode ) - { - is_ca_mode = 0; - writembs(exit_ca_mode); - } - - completion_print( cols, width, 0, rows, prefix, is_quoted, lst); - pager_flush(); + /* Terminal is wide enough. Print the list! */ + width = pref_width; + print=1; } else { - int npos, pos = 0; - int do_loop = 1; - - /* - Enter ca_mode, which means that the terminal - content will be restored to the current - state on exit. - */ - if( enter_ca_mode && exit_ca_mode ) - { - is_ca_mode=1; - writembs(enter_ca_mode); - } - - - completion_print( cols, - width, - 0, - termsize.ws_row-1, - prefix, - is_quoted, - lst); - /* - List does not fit on screen. Print one screenfull and - leave a scrollable interface - */ - while(do_loop) - { - set_color( rgb_color_t::black(), get_color(HIGHLIGHT_PAGER_PROGRESS) ); - wcstring msg = format_string(_(L" %d to %d of %d"), pos, pos+termsize.ws_row-1, rows ); - msg.append(L" \r" ); - - writestr(msg.c_str()); - set_color( rgb_color_t::normal(), rgb_color_t::normal() ); - pager_flush(); - int c = readch(); - - switch( c ) + long next_rows = (lst.size()-1)/(cols-1)+1; + /* fwprintf( stderr, + L"cols %d, min_tot %d, term %d, rows=%d, nextrows %d, termrows %d, diff %d\n", + cols, + min_tot_width, termsize.ws_col, + rows, next_rows, termsize.ws_row, + pref_tot_width-termsize.ws_col ); + */ + if (min_tot_width < termsize.ws_col && + (((rows < termsize.ws_row) && (next_rows >= termsize.ws_row)) || + (pref_tot_width-termsize.ws_col< 4 && cols < 3))) { - case LINE_UP: - { - if( pos > 0 ) + /* + Terminal almost wide enough, or squeezing makes the + whole list fit on-screen. + + This part of the code is really important. People hate + having to scroll through the completion list. In cases + where there are a huge number of completions, it can't + be helped, but it is not uncommon for the completions to + _almost_ fit on one screen. In those cases, it is almost + always desirable to 'squeeze' the completions into a + single page. + + If we are using N columns and can get everything to + fit using squeezing, but everything would also fit + using N-1 columns, don't try. + */ + + int tot_width = min_tot_width; + width = min_width; + + while (tot_width < termsize.ws_col) { - pos--; - writembs(tparm( cursor_address, 0, 0)); - writembs(scroll_reverse); - completion_print( cols, - width, - pos, - pos+1, - prefix, - is_quoted, - lst ); - writembs( tparm( cursor_address, - termsize.ws_row-1, 0) ); - writembs(clr_eol ); - + for (i=0; (i<cols) && (tot_width < termsize.ws_col); i++) + { + if (width[i] < pref_width[i]) + { + width[i]++; + tot_width++; + } + } } + print=1; + } + } - break; - } - - case LINE_DOWN: - { - if( pos <= (rows - termsize.ws_row ) ) + if (print) + { + res=PAGER_DONE; + if (rows < termsize.ws_row) + { + /* List fits on screen. Print it and leave */ + if (is_ca_mode) { - pos++; - completion_print( cols, - width, - pos+termsize.ws_row-2, - pos+termsize.ws_row-1, - prefix, - is_quoted, - lst ); + is_ca_mode = 0; + writembs(exit_ca_mode); } - break; - } - case PAGE_DOWN: - { - - npos = mini( (int)(rows - termsize.ws_row+1), (int)(pos + termsize.ws_row-1) ); - if( npos != pos ) - { - pos = npos; - completion_print( cols, - width, - pos, - pos+termsize.ws_row-1, - prefix, - is_quoted, - lst ); - } - else + completion_print(cols, width, 0, rows, prefix, is_quoted, lst); + pager_flush(); + } + else + { + int npos, pos = 0; + int do_loop = 1; + + /* + Enter ca_mode, which means that the terminal + content will be restored to the current + state on exit. + */ + if (enter_ca_mode && exit_ca_mode) { - if( flash_screen ) - writembs( flash_screen ); + is_ca_mode=1; + writembs(enter_ca_mode); } - break; - } - - case PAGE_UP: - { - npos = maxi( 0, - pos - termsize.ws_row+1 ); - if( npos != pos ) + completion_print(cols, + width, + 0, + termsize.ws_row-1, + prefix, + is_quoted, + lst); + /* + List does not fit on screen. Print one screenfull and + leave a scrollable interface + */ + while (do_loop) { - pos = npos; - completion_print( cols, - width, - pos, - pos+termsize.ws_row-1, - prefix, - is_quoted, - lst ); - } - else - { - if( flash_screen ) - writembs( flash_screen ); - } - break; - } + set_color(rgb_color_t::black(), get_color(HIGHLIGHT_PAGER_PROGRESS)); + wcstring msg = format_string(_(L" %d to %d of %d"), pos, pos+termsize.ws_row-1, rows); + msg.append(L" \r"); - case R_NULL: - { - do_loop=0; - res=PAGER_RESIZE; - break; + writestr(msg.c_str()); + set_color(rgb_color_t::normal(), rgb_color_t::normal()); + pager_flush(); + int c = readch(); + + switch (c) + { + case LINE_UP: + { + if (pos > 0) + { + pos--; + writembs(tparm(cursor_address, 0, 0)); + writembs(scroll_reverse); + completion_print(cols, + width, + pos, + pos+1, + prefix, + is_quoted, + lst); + writembs(tparm(cursor_address, + termsize.ws_row-1, 0)); + writembs(clr_eol); + + } + + break; + } + + case LINE_DOWN: + { + if (pos <= (rows - termsize.ws_row)) + { + pos++; + completion_print(cols, + width, + pos+termsize.ws_row-2, + pos+termsize.ws_row-1, + prefix, + is_quoted, + lst); + } + break; + } + + case PAGE_DOWN: + { - } + npos = mini((int)(rows - termsize.ws_row+1), (int)(pos + termsize.ws_row-1)); + if (npos != pos) + { + pos = npos; + completion_print(cols, + width, + pos, + pos+termsize.ws_row-1, + prefix, + is_quoted, + lst); + } + else + { + if (flash_screen) + writembs(flash_screen); + } + + break; + } + + case PAGE_UP: + { + npos = maxi(0, + pos - termsize.ws_row+1); + + if (npos != pos) + { + pos = npos; + completion_print(cols, + width, + pos, + pos+termsize.ws_row-1, + prefix, + is_quoted, + lst); + } + else + { + if (flash_screen) + writembs(flash_screen); + } + break; + } + + case R_NULL: + { + do_loop=0; + res=PAGER_RESIZE; + break; - default: - { - out_buff.push_back( c ); - do_loop = 0; - break; - } + } + + default: + { + out_buff.push_back(c); + do_loop = 0; + break; + } + } + } + writembs(clr_eol); } - } - writembs(clr_eol); } - } - return res; + return res; } /** @@ -830,71 +831,71 @@ static int completion_try_print( int cols, inside completion descriptions. Remove all whitespace from beginning/end of completion descriptions. */ -static void mangle_descriptions( wcstring_list_t &lst ) +static void mangle_descriptions(wcstring_list_t &lst) { - int skip; - for( size_t i=0; i<lst.size(); i++ ) - { + int skip; + for (size_t i=0; i<lst.size(); i++) + { wcstring &next = lst.at(i); - size_t in, out; - skip=1; + size_t in, out; + skip=1; size_t next_idx = 0; - while( next_idx < next.size() && next[next_idx] != COMPLETE_SEP ) - next_idx++; + while (next_idx < next.size() && next[next_idx] != COMPLETE_SEP) + next_idx++; - if( next_idx == next.size() ) - continue; + if (next_idx == next.size()) + continue; - in=out=next_idx + 1; + in=out=next_idx + 1; - while( in < next.size() ) - { - if( next[in] == L' ' || next[in]==L'\t' || next[in]<32 ) - { - if( !skip ) - next[out++]=L' '; - skip=1; - } - else - { - next[out++] = next[in]; - skip=0; - } - in++; - } + while (in < next.size()) + { + if (next[in] == L' ' || next[in]==L'\t' || next[in]<32) + { + if (!skip) + next[out++]=L' '; + skip=1; + } + else + { + next[out++] = next[in]; + skip=0; + } + in++; + } next.resize(out); - } + } } /** Merge multiple completions with the same description to the same line */ -static void join_completions( wcstring_list_t lst ) +static void join_completions(wcstring_list_t lst) { std::map<wcstring, long> desc_table; - for( size_t i=0; i<lst.size(); i++ ) - { - const wchar_t *item = lst.at(i).c_str(); - const wchar_t *desc = wcschr( item, COMPLETE_SEP ); - long prev_idx; + for (size_t i=0; i<lst.size(); i++) + { + const wchar_t *item = lst.at(i).c_str(); + const wchar_t *desc = wcschr(item, COMPLETE_SEP); + long prev_idx; - if( !desc ) - continue; - desc++; + if (!desc) + continue; + desc++; prev_idx = desc_table[desc] - 1; - if( prev_idx == -1 ) - { + if (prev_idx == -1) + { desc_table[desc] = (long)(i+1); - } - else - { - const wchar_t *old = lst.at(i).c_str(); - const wchar_t *old_end = wcschr( old, COMPLETE_SEP ); + } + else + { + const wchar_t *old = lst.at(i).c_str(); + const wchar_t *old_end = wcschr(old, COMPLETE_SEP); - if( old_end ) - { + if (old_end) + { wcstring foo; foo.append(old, old_end - old); @@ -903,11 +904,11 @@ static void join_completions( wcstring_list_t lst ) lst.at(prev_idx) = foo; lst.at(i).clear(); - } + } - } + } - } + } /* Remove empty strings */ lst.erase(remove(lst.begin(), lst.end(), wcstring()), lst.end()); @@ -916,50 +917,50 @@ static void join_completions( wcstring_list_t lst ) /** Replace completion strings with a comp_t structure */ -static std::vector<comp_t *> mangle_completions( wcstring_list_t &lst, const wchar_t *prefix ) +static std::vector<comp_t *> mangle_completions(wcstring_list_t &lst, const wchar_t *prefix) { std::vector<comp_t *> result; - for( size_t i=0; i<lst.size(); i++ ) - { + for (size_t i=0; i<lst.size(); i++) + { wcstring &next = lst.at(i); - size_t start, end; + size_t start, end; comp_t zerod = {}; - comp_t *comp = new comp_t(zerod); + comp_t *comp = new comp_t(zerod); - for( start=end=0; 1; end++ ) - { - wchar_t c = next.c_str()[end]; + for (start=end=0; 1; end++) + { + wchar_t c = next.c_str()[end]; - if( (c == COMPLETE_ITEM_SEP) || (c==COMPLETE_SEP) || !c) - { + if ((c == COMPLETE_ITEM_SEP) || (c==COMPLETE_SEP) || !c) + { wcstring start2 = wcstring(next, start, end - start); wcstring str = escape_string(start2, ESCAPE_ALL | ESCAPE_NO_QUOTED); - comp->comp_width += my_wcswidth( str.c_str() ); - comp->comp.push_back(str); - start = end+1; - } + comp->comp_width += my_wcswidth(str.c_str()); + comp->comp.push_back(str); + start = end+1; + } - if( c == COMPLETE_SEP ) - { - comp->desc = next.c_str() + start; - break; - } + if (c == COMPLETE_SEP) + { + comp->desc = next.c_str() + start; + break; + } - if( !c ) - break; + if (!c) + break; - } + } - comp->comp_width += (int)(my_wcswidth(prefix)*comp->comp.size() + 2*(comp->comp.size()-1)); - comp->desc_width = comp->desc.empty()?0:my_wcswidth( comp->desc.c_str() ); + comp->comp_width += (int)(my_wcswidth(prefix)*comp->comp.size() + 2*(comp->comp.size()-1)); + comp->desc_width = comp->desc.empty()?0:my_wcswidth(comp->desc.c_str()); - comp->pref_width = comp->comp_width + comp->desc_width + (comp->desc_width?4:0); + comp->pref_width = comp->comp_width + comp->desc_width + (comp->desc_width?4:0); result.push_back(comp); - } + } - recalc_width( result, prefix ); + recalc_width(result, prefix); return result; } @@ -968,12 +969,12 @@ static std::vector<comp_t *> mangle_completions( wcstring_list_t &lst, const wch /** Respond to a winch signal by checking the terminal size */ -static void handle_winch( int sig ) +static void handle_winch(int sig) { - if (ioctl(1,TIOCGWINSZ,&termsize)!=0) - { - return; - } + if (ioctl(1,TIOCGWINSZ,&termsize)!=0) + { + return; + } } /** @@ -983,7 +984,7 @@ static void handle_winch( int sig ) */ static int interrupt_handler() { - return R_NULL; + return R_NULL; } /** @@ -991,111 +992,114 @@ static int interrupt_handler() it with a copy of stderr, so the reading of completion strings must be done before init is called. */ -static void init( int mangle_descriptors, int out ) +static void init(int mangle_descriptors, int out) { - struct sigaction act; + struct sigaction act; - static struct termios pager_modes; - char *term; + static struct termios pager_modes; + char *term; - if( mangle_descriptors ) - { + if (mangle_descriptors) + { + + /* + Make fd 1 output to screen, and use some other fd for writing + the resulting output back to the caller + */ + int in; + out = dup(1); + close(1); + close(0); + + /* OK to not use CLO_EXEC here because fish_pager is single threaded */ + if ((in = open(ttyname(2), O_RDWR)) != -1) + { + if (dup2(2, 1) == -1) + { + debug(0, _(L"Could not set up output file descriptors for pager")); + exit(1); + } + + if (dup2(in, 0) == -1) + { + debug(0, _(L"Could not set up input file descriptors for pager")); + exit(1); + } + } + else + { + debug(0, _(L"Could not open tty for pager")); + exit(1); + } + } + + if (!(out_file = fdopen(out, "w"))) + { + debug(0, _(L"Could not initialize result pipe")); + exit(1); + } + + + env_universal_init(0, 0, 0, 0); + input_common_init(&interrupt_handler); + output_set_writer(&pager_buffered_writer); + + sigemptyset(& act.sa_mask); + act.sa_flags=0; + act.sa_handler=SIG_DFL; + act.sa_flags = 0; + act.sa_handler= &handle_winch; + if (sigaction(SIGWINCH, &act, 0)) + { + wperror(L"sigaction"); + exit(1); + } + + handle_winch(0); /* Set handler for window change events */ + + tcgetattr(0,&pager_modes); /* get the current terminal modes */ + memcpy(&saved_modes, + &pager_modes, + sizeof(saved_modes)); /* save a copy so we can reset the terminal later */ + + pager_modes.c_lflag &= ~ICANON; /* turn off canonical mode */ + pager_modes.c_lflag &= ~ECHO; /* turn off echo mode */ + pager_modes.c_cc[VMIN]=1; + pager_modes.c_cc[VTIME]=0; /* - Make fd 1 output to screen, and use some other fd for writing - the resulting output back to the caller + */ - int in; - out = dup( 1 ); - close(1); - close(0); + if (tcsetattr(0,TCSANOW,&pager_modes)) /* set the new modes */ + { + wperror(L"tcsetattr"); + exit(1); + } - /* OK to not use CLO_EXEC here because fish_pager is single threaded */ - if( (in = open( ttyname(2), O_RDWR )) != -1 ) + + if (setupterm(0, STDOUT_FILENO, 0) == ERR) { - if( dup2( 2, 1 ) == -1 ) - { - debug( 0, _(L"Could not set up output file descriptors for pager") ); - exit( 1 ); - } - - if( dup2( in, 0 ) == -1 ) - { - debug( 0, _(L"Could not set up input file descriptors for pager") ); - exit( 1 ); - } + debug(0, _(L"Could not set up terminal")); + exit(1); } - else + + term = getenv("TERM"); + if (term) { - debug( 0, _(L"Could not open tty for pager") ); - exit( 1 ); + wchar_t *wterm = str2wcs(term); + output_set_term(wterm); + free(wterm); } - } - - if( !(out_file = fdopen( out, "w" )) ) - { - debug( 0, _(L"Could not initialize result pipe" ) ); - exit( 1 ); - } - - - env_universal_init( 0, 0, 0, 0); - input_common_init( &interrupt_handler ); - output_set_writer( &pager_buffered_writer ); - - sigemptyset( & act.sa_mask ); - act.sa_flags=0; - act.sa_handler=SIG_DFL; - act.sa_flags = 0; - act.sa_handler= &handle_winch; - if( sigaction( SIGWINCH, &act, 0 ) ) - { - wperror( L"sigaction" ); - exit(1); - } - - handle_winch( 0 ); /* Set handler for window change events */ - - tcgetattr(0,&pager_modes); /* get the current terminal modes */ - memcpy( &saved_modes, - &pager_modes, - sizeof(saved_modes)); /* save a copy so we can reset the terminal later */ - - pager_modes.c_lflag &= ~ICANON; /* turn off canonical mode */ - pager_modes.c_lflag &= ~ECHO; /* turn off echo mode */ - pager_modes.c_cc[VMIN]=1; - pager_modes.c_cc[VTIME]=0; - - /* - - */ - if( tcsetattr(0,TCSANOW,&pager_modes)) /* set the new modes */ - { - wperror(L"tcsetattr"); - exit(1); - } - - - if( setupterm( 0, STDOUT_FILENO, 0) == ERR ) - { - debug( 0, _(L"Could not set up terminal") ); - exit(1); - } - - term = getenv("TERM"); - if( term ) - { - wchar_t *wterm = str2wcs(term); - output_set_term( wterm ); - free( wterm ); - } /* Infer term256 support */ char *fish_term256 = getenv("fish_term256"); bool support_term256; - if (fish_term256) { + if (fish_term256) + { support_term256 = from_string<bool>(fish_term256); - } else { + } + else + { support_term256 = term && strstr(term, "256color"); } output_set_supports_term256(support_term256); @@ -1106,336 +1110,336 @@ static void init( int mangle_descriptors, int out ) */ static void destroy() { - env_universal_destroy(); - input_common_destroy(); - wutil_destroy(); - if( del_curterm( cur_term ) == ERR ) - { - debug( 0, _(L"Error while closing terminfo") ); - } - - fclose( out_file ); + env_universal_destroy(); + input_common_destroy(); + wutil_destroy(); + if (del_curterm(cur_term) == ERR) + { + debug(0, _(L"Error while closing terminfo")); + } + + fclose(out_file); } /** Read lines of input from the specified file, unescape them and insert them into the specified list. */ -static void read_array( FILE* file, wcstring_list_t &comp ) +static void read_array(FILE* file, wcstring_list_t &comp) { - std::vector<char> buffer; - int c; - wchar_t *wcs; - - while( !feof( file ) ) - { - buffer.clear(); + std::vector<char> buffer; + int c; + wchar_t *wcs; - while( 1 ) + while (!feof(file)) { - c = getc( file ); - if( c == EOF ) - { - break; - } + buffer.clear(); + + while (1) + { + c = getc(file); + if (c == EOF) + { + break; + } - if( c == '\n' ) - { - break; - } + if (c == '\n') + { + break; + } buffer.push_back(static_cast<char>(c)); - } + } - if( ! buffer.empty() ) - { + if (! buffer.empty()) + { buffer.push_back(0); - wcs = str2wcs( &buffer.at(0) ); - if( wcs ) - { + wcs = str2wcs(&buffer.at(0)); + if (wcs) + { wcstring tmp = wcs; if (unescape_string(tmp, 0)) { comp.push_back(tmp); + } + free(wcs); + } } - free( wcs ); - } } - } } -static int get_fd( const char *str ) +static int get_fd(const char *str) { - char *end; - long fd; - - errno = 0; - fd = strtol( str, &end, 10 ); - if( fd < 0 || *end || errno ) - { - debug( 0, ERR_NOT_FD, program_name, optarg ); - exit( 1 ); - } - return (int)fd; + char *end; + long fd; + + errno = 0; + fd = strtol(str, &end, 10); + if (fd < 0 || *end || errno) + { + debug(0, ERR_NOT_FD, program_name, optarg); + exit(1); + } + return (int)fd; } -int main( int argc, char **argv ) +int main(int argc, char **argv) { - int i; - int is_quoted=0; - wcstring_list_t comp; - wchar_t *prefix = 0; - - int mangle_descriptors = 0; - int result_fd = -1; - set_main_thread(); + int i; + int is_quoted=0; + wcstring_list_t comp; + wchar_t *prefix = 0; + + int mangle_descriptors = 0; + int result_fd = -1; + set_main_thread(); setup_fork_guards(); - /* - This initialization is made early, so that the other init code - can use global_context for memory managment - */ - program_name = L"fish_pager"; - + /* + This initialization is made early, so that the other init code + can use global_context for memory managment + */ + program_name = L"fish_pager"; - wsetlocale( LC_ALL, L"" ); - /* - The call signature for fish_pager is a mess. Because we want - to be able to upgrade fish without breaking running - instances, we need to support all previous - modes. Unfortunatly, the two previous ones are a mess. The - third one is designed to be extensible, so hopefully it will - be the last. - */ + wsetlocale(LC_ALL, L""); - if( argc > 1 && argv[1][0] == '-' ) - { /* - Third mode + The call signature for fish_pager is a mess. Because we want + to be able to upgrade fish without breaking running + instances, we need to support all previous + modes. Unfortunatly, the two previous ones are a mess. The + third one is designed to be extensible, so hopefully it will + be the last. */ - int completion_fd = -1; - FILE *completion_file; - - while( 1 ) + if (argc > 1 && argv[1][0] == '-') { - static struct option - long_options[] = + /* + Third mode + */ + + int completion_fd = -1; + FILE *completion_file; + + while (1) { - { - "result-fd", required_argument, 0, 'r' - } - , - { - "completion-fd", required_argument, 0, 'c' - } - , - { - "prefix", required_argument, 0, 'p' - } - , - { - "is-quoted", no_argument, 0, 'q' - } - , - { - "help", no_argument, 0, 'h' - } - , - { - "version", no_argument, 0, 'v' - } - , - { - 0, 0, 0, 0 - } - } - ; + static struct option + long_options[] = + { + { + "result-fd", required_argument, 0, 'r' + } + , + { + "completion-fd", required_argument, 0, 'c' + } + , + { + "prefix", required_argument, 0, 'p' + } + , + { + "is-quoted", no_argument, 0, 'q' + } + , + { + "help", no_argument, 0, 'h' + } + , + { + "version", no_argument, 0, 'v' + } + , + { + 0, 0, 0, 0 + } + } + ; - int opt_index = 0; + int opt_index = 0; - int opt = getopt_long( argc, - argv, - GETOPT_STRING, - long_options, - &opt_index ); + int opt = getopt_long(argc, + argv, + GETOPT_STRING, + long_options, + &opt_index); - if( opt == -1 ) - break; + if (opt == -1) + break; - switch( opt ) - { - case 0: - { - break; - } + switch (opt) + { + case 0: + { + break; + } - case 'r': - { - result_fd = get_fd( optarg ); - break; - } + case 'r': + { + result_fd = get_fd(optarg); + break; + } - case 'c': - { - completion_fd = get_fd( optarg ); - break; + case 'c': + { + completion_fd = get_fd(optarg); + break; + } + + case 'p': + { + prefix = str2wcs(optarg); + break; + } + + case 'h': + { + print_help(argv[0], 1); + exit(0); + } + + case 'v': + { + debug(0, L"%ls, version %s\n", program_name, PACKAGE_VERSION); + exit(0); + } + + case 'q': + { + is_quoted = 1; + } + + } } - case 'p': + if (completion_fd == -1 || result_fd == -1) { - prefix = str2wcs(optarg); - break; + debug(0, _(L"Unspecified file descriptors")); + exit(1); } - case 'h': + + if ((completion_file = fdopen(completion_fd, "r"))) { - print_help( argv[0], 1 ); - exit(0); + read_array(completion_file, comp); + fclose(completion_file); } - - case 'v': + else { - debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION ); - exit( 0 ); + debug(0, _(L"Could not read completions")); + wperror(L"fdopen"); + exit(1); } - case 'q': + if (!prefix) { - is_quoted = 1; + prefix = wcsdup(L""); } - } - } - - if( completion_fd == -1 || result_fd == -1 ) - { - debug( 0, _(L"Unspecified file descriptors") ); - exit( 1 ); - } - - if( (completion_file = fdopen( completion_fd, "r" ) ) ) - { - read_array( completion_file, comp ); - fclose( completion_file ); } else { - debug( 0, _(L"Could not read completions") ); - wperror( L"fdopen" ); - exit( 1 ); - } - - if( !prefix ) - { - prefix = wcsdup( L"" ); - } - - - } - else - { - /* - Second or first mode. These suck, but we need to support - them for backwards compatibility. At least for some - time. - - Third mode was implemented in January 2007, and previous - modes should be considered deprecated from that point - forward. A reasonable time frame for removal of the code - below has yet to be determined. - */ - - if( argc < 3 ) - { - print_help( argv[0], 1 ); - exit( 0 ); - } - else - { - mangle_descriptors = 1; - - prefix = str2wcs( argv[2] ); - is_quoted = strcmp( "1", argv[1] )==0; - - if( argc > 3 ) - { /* - First mode + Second or first mode. These suck, but we need to support + them for backwards compatibility. At least for some + time. + + Third mode was implemented in January 2007, and previous + modes should be considered deprecated from that point + forward. A reasonable time frame for removal of the code + below has yet to be determined. */ - for( i=3; i<argc; i++ ) + + if (argc < 3) { - wcstring wcs = str2wcstring( argv[i] ); + print_help(argv[0], 1); + exit(0); + } + else + { + mangle_descriptors = 1; + + prefix = str2wcs(argv[2]); + is_quoted = strcmp("1", argv[1])==0; + + if (argc > 3) + { + /* + First mode + */ + for (i=3; i<argc; i++) + { + wcstring wcs = str2wcstring(argv[i]); comp.push_back(wcs); + } + } + else + { + /* + Second mode + */ + read_array(stdin, comp); + } } - } - else - { - /* - Second mode - */ - read_array( stdin, comp ); - } - } - } + } // debug( 3, L"prefix is '%ls'", prefix ); - init( mangle_descriptors, result_fd ); + init(mangle_descriptors, result_fd); - mangle_descriptions( comp ); + mangle_descriptions(comp); - if( wcscmp( prefix, L"-" ) == 0 ) - join_completions( comp ); + if (wcscmp(prefix, L"-") == 0) + join_completions(comp); - std::vector<comp_t *> completions = mangle_completions( comp, prefix ); + std::vector<comp_t *> completions = mangle_completions(comp, prefix); - /** - Try to print the completions. Start by trying to print the - list in PAGER_MAX_COLS columns, if the completions won't - fit, reduce the number of columns by one. Printing a single - column never fails. - */ - for( i = PAGER_MAX_COLS; i>0; i-- ) - { - switch( completion_try_print( i, prefix, is_quoted, completions ) ) + /** + Try to print the completions. Start by trying to print the + list in PAGER_MAX_COLS columns, if the completions won't + fit, reduce the number of columns by one. Printing a single + column never fails. + */ + for (i = PAGER_MAX_COLS; i>0; i--) { + switch (completion_try_print(i, prefix, is_quoted, completions)) + { - case PAGER_RETRY: - break; + case PAGER_RETRY: + break; - case PAGER_DONE: - i=0; - break; + case PAGER_DONE: + i=0; + break; - case PAGER_RESIZE: - /* - This means we got a resize event, so we start - over from the beginning. Since it the screen got - bigger, we might be able to fit all completions - on-screen. - */ - i=PAGER_MAX_COLS+1; - break; + case PAGER_RESIZE: + /* + This means we got a resize event, so we start + over from the beginning. Since it the screen got + bigger, we might be able to fit all completions + on-screen. + */ + i=PAGER_MAX_COLS+1; + break; + } } - } - free(prefix ); + free(prefix); - fwprintf( out_file, L"%ls", out_buff.c_str() ); - if( is_ca_mode ) - { - writembs(exit_ca_mode); - pager_flush(); - } - destroy(); + fwprintf(out_file, L"%ls", out_buff.c_str()); + if (is_ca_mode) + { + writembs(exit_ca_mode); + pager_flush(); + } + destroy(); } |