mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Add documentation, fix memory leaks and do minor code tweaks in fish_pager
darcs-hash:20061022110414-ac50b-e5ba776e795e0273d819d4eb51d5f60fba967db2.gz
This commit is contained in:
parent
5a7a8003a0
commit
e2dca4273a
1 changed files with 125 additions and 39 deletions
164
fish_pager.c
164
fish_pager.c
|
@ -74,6 +74,24 @@ enum
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This struct should be continually updated by signals as the term
|
This struct should be continually updated by signals as the term
|
||||||
resizes, and as such always contain the correct current size.
|
resizes, and as such always contain the correct current size.
|
||||||
|
@ -81,11 +99,23 @@ enum
|
||||||
|
|
||||||
static struct winsize termsize;
|
static struct winsize termsize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The termios modes the terminal had when the program started. These
|
||||||
|
should be restored on exit
|
||||||
|
*/
|
||||||
static struct termios saved_modes;
|
static struct termios saved_modes;
|
||||||
static struct termios pager_modes;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This flag is set to 1 of we have sent the enter_ca_mode terminfo
|
||||||
|
sequence to save the previous terminal contents.
|
||||||
|
*/
|
||||||
static int is_ca_mode = 0;
|
static int is_ca_mode = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This buffer_t is used to buffer the output of the pager to improve
|
||||||
|
screen redraw performance bu cutting down the number of write()
|
||||||
|
calls to only one.
|
||||||
|
*/
|
||||||
static buffer_t *pager_buffer;
|
static buffer_t *pager_buffer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,7 +131,13 @@ static wchar_t *hightlight_var[] =
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This string_buffer_t contains the text that should be sent back to the calling program
|
||||||
|
*/
|
||||||
static string_buffer_t out_buff;
|
static string_buffer_t out_buff;
|
||||||
|
/**
|
||||||
|
This is the file to which the output text should be sent. It is really a pipe.
|
||||||
|
*/
|
||||||
static FILE *out_file;
|
static FILE *out_file;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -136,6 +172,10 @@ typedef struct
|
||||||
}
|
}
|
||||||
comp_t;
|
comp_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function translates from a highlight code to a specific color
|
||||||
|
by check invironement variables
|
||||||
|
*/
|
||||||
static int get_color( int highlight )
|
static int get_color( int highlight )
|
||||||
{
|
{
|
||||||
wchar_t *val;
|
wchar_t *val;
|
||||||
|
@ -160,6 +200,12 @@ static int get_color( int highlight )
|
||||||
return output_color_code( val );
|
return output_color_code( val );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function calculates the minimum width for each completion
|
||||||
|
entry in the specified array_list. This width depends on the
|
||||||
|
terminal size, so this function should be called when the terminal
|
||||||
|
changes size.
|
||||||
|
*/
|
||||||
static void recalc_width( array_list_t *l, const wchar_t *prefix )
|
static void recalc_width( array_list_t *l, const wchar_t *prefix )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -173,6 +219,10 @@ static void recalc_width( array_list_t *l, const wchar_t *prefix )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Test if the specified character sequence has been entered on the
|
||||||
|
keyboard
|
||||||
|
*/
|
||||||
static int try_sequence( char *seq )
|
static int try_sequence( char *seq )
|
||||||
{
|
{
|
||||||
int j, k;
|
int j, k;
|
||||||
|
@ -196,6 +246,9 @@ static int try_sequence( char *seq )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Read a character from keyboard
|
||||||
|
*/
|
||||||
static wint_t readch()
|
static wint_t readch()
|
||||||
{
|
{
|
||||||
struct mapping
|
struct mapping
|
||||||
|
@ -255,13 +308,18 @@ static wint_t readch()
|
||||||
return input_common_readch(0);
|
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)
|
||||||
{
|
{
|
||||||
b_append( pager_buffer, &c, 1 );
|
b_append( pager_buffer, &c, 1 );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Flush \c pager_buffer to stdout
|
||||||
|
*/
|
||||||
static void pager_flush()
|
static void pager_flush()
|
||||||
{
|
{
|
||||||
write( 1, pager_buffer->buff, pager_buffer->used );
|
write( 1, pager_buffer->buff, pager_buffer->used );
|
||||||
|
@ -424,7 +482,7 @@ static void completion_print( int cols,
|
||||||
\param is_quoted whether the completions should be quoted
|
\param is_quoted whether the completions should be quoted
|
||||||
\param l the list of completions
|
\param l the list of completions
|
||||||
|
|
||||||
\return zero if the specified number of columns do not fit, no-zero otherwise
|
\return one of PAGER_RETRY, PAGER_DONE and PAGER_RESIZE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int completion_try_print( int cols,
|
static int completion_try_print( int cols,
|
||||||
|
@ -455,13 +513,13 @@ static int completion_try_print( int cols,
|
||||||
|
|
||||||
int pref_tot_width=0;
|
int pref_tot_width=0;
|
||||||
int min_tot_width = 0;
|
int min_tot_width = 0;
|
||||||
int res=0;
|
int res=PAGER_RETRY;
|
||||||
/*
|
/*
|
||||||
Skip completions on tiny terminals
|
Skip completions on tiny terminals
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if( termsize.ws_col < 16 )
|
if( termsize.ws_col < 16 )
|
||||||
return 1;
|
return PAGER_DONE;
|
||||||
|
|
||||||
memset( pref_width, 0, sizeof(pref_width) );
|
memset( pref_width, 0, sizeof(pref_width) );
|
||||||
memset( min_width, 0, sizeof(min_width) );
|
memset( min_width, 0, sizeof(min_width) );
|
||||||
|
@ -550,7 +608,7 @@ static int completion_try_print( int cols,
|
||||||
|
|
||||||
if( print )
|
if( print )
|
||||||
{
|
{
|
||||||
res=1;
|
res=PAGER_DONE;
|
||||||
if( rows < termsize.ws_row )
|
if( rows < termsize.ws_row )
|
||||||
{
|
{
|
||||||
/* List fits on screen. Print it and leave */
|
/* List fits on screen. Print it and leave */
|
||||||
|
@ -585,11 +643,10 @@ static int completion_try_print( int cols,
|
||||||
while(do_loop)
|
while(do_loop)
|
||||||
{
|
{
|
||||||
wchar_t msg[30];
|
wchar_t msg[30];
|
||||||
int percent = 100*(pos+rows)/(2*rows-termsize.ws_row+1);
|
|
||||||
set_color( FISH_COLOR_BLACK,
|
set_color( FISH_COLOR_BLACK,
|
||||||
get_color(HIGHLIGHT_PAGER_PROGRESS) );
|
get_color(HIGHLIGHT_PAGER_PROGRESS) );
|
||||||
swprintf( msg, 30,
|
swprintf( msg, 30,
|
||||||
L" %d to %d of %d \r",
|
_(L" %d to %d of %d \r"),
|
||||||
pos, pos+termsize.ws_row-1, rows );
|
pos, pos+termsize.ws_row-1, rows );
|
||||||
writestr(msg);
|
writestr(msg);
|
||||||
set_color( FISH_COLOR_NORMAL, FISH_COLOR_NORMAL );
|
set_color( FISH_COLOR_NORMAL, FISH_COLOR_NORMAL );
|
||||||
|
@ -689,7 +746,7 @@ static int completion_try_print( int cols,
|
||||||
case R_NULL:
|
case R_NULL:
|
||||||
{
|
{
|
||||||
do_loop=0;
|
do_loop=0;
|
||||||
res=2;
|
res=PAGER_RESIZE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -887,6 +944,10 @@ static int interrupt_handler()
|
||||||
static void init()
|
static void init()
|
||||||
{
|
{
|
||||||
struct sigaction act;
|
struct sigaction act;
|
||||||
|
|
||||||
|
static struct termios pager_modes;
|
||||||
|
|
||||||
|
|
||||||
program_name = L"fish_pager";
|
program_name = L"fish_pager";
|
||||||
wsetlocale( LC_ALL, L"" );
|
wsetlocale( LC_ALL, L"" );
|
||||||
|
|
||||||
|
@ -903,21 +964,21 @@ static void init()
|
||||||
{
|
{
|
||||||
if( dup2( 2, 1 ) == -1 )
|
if( dup2( 2, 1 ) == -1 )
|
||||||
{
|
{
|
||||||
debug( 0, L"Could not set up output file descriptors for pager" );
|
debug( 0, _(L"Could not set up output file descriptors for pager") );
|
||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( dup2( in, 0 ) == -1 )
|
if( dup2( in, 0 ) == -1 )
|
||||||
{
|
{
|
||||||
debug( 0, L"Could not set up input file descriptors for pager %d", in );
|
debug( 0, _(L"Could not set up input file descriptors for pager %d"), in );
|
||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug( 0, L"Could not open tty for pager" );
|
debug( 0, _(L"Could not open tty for pager") );
|
||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
out_file = fdopen( out, "w" );
|
out_file = fdopen( out, "w" );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -925,7 +986,6 @@ static void init()
|
||||||
*/
|
*/
|
||||||
sb_init( &out_buff );
|
sb_init( &out_buff );
|
||||||
|
|
||||||
halloc_util_init();
|
|
||||||
env_universal_init( 0, 0, 0, 0);
|
env_universal_init( 0, 0, 0, 0);
|
||||||
input_common_init( &interrupt_handler );
|
input_common_init( &interrupt_handler );
|
||||||
output_set_writer( &pager_buffered_writer );
|
output_set_writer( &pager_buffered_writer );
|
||||||
|
@ -966,7 +1026,7 @@ static void init()
|
||||||
|
|
||||||
if( setupterm( 0, STDOUT_FILENO, 0) == ERR )
|
if( setupterm( 0, STDOUT_FILENO, 0) == ERR )
|
||||||
{
|
{
|
||||||
debug( 0, L"Could not set up terminal" );
|
debug( 0, _(L"Could not set up terminal") );
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -977,6 +1037,7 @@ void destroy()
|
||||||
env_universal_destroy();
|
env_universal_destroy();
|
||||||
input_common_destroy();
|
input_common_destroy();
|
||||||
halloc_util_destroy();
|
halloc_util_destroy();
|
||||||
|
wutil_destroy();
|
||||||
if( del_curterm( cur_term ) == ERR )
|
if( del_curterm( cur_term ) == ERR )
|
||||||
{
|
{
|
||||||
debug( 0, _(L"Error while closing terminfo") );
|
debug( 0, _(L"Error while closing terminfo") );
|
||||||
|
@ -986,43 +1047,54 @@ void destroy()
|
||||||
fclose( out_file );
|
fclose( out_file );
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BUFSIZE 1024
|
|
||||||
void read_array( FILE* file, array_list_t *comp )
|
void read_array( FILE* file, array_list_t *comp )
|
||||||
{
|
{
|
||||||
char buffer[BUFSIZE];
|
buffer_t buffer;
|
||||||
int c;
|
int c;
|
||||||
int i;
|
char cc;
|
||||||
wchar_t *wcs, *unescaped;
|
wchar_t *wcs, *unescaped;
|
||||||
|
|
||||||
|
b_init( &buffer );
|
||||||
|
|
||||||
while( !feof( file ) )
|
while( !feof( file ) )
|
||||||
{
|
{
|
||||||
i = 0;
|
buffer.used=0;
|
||||||
while( i < BUFSIZE-1 )
|
|
||||||
|
while( 1 )
|
||||||
{
|
{
|
||||||
c = getc( file );
|
c = getc( file );
|
||||||
if( c == EOF )
|
if( c == EOF )
|
||||||
{
|
{
|
||||||
return;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( c == '\n' )
|
if( c == '\n' )
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc=c;
|
||||||
|
|
||||||
buffer[ i++ ] = c;
|
b_append( &buffer, &cc, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[ i ] = '\0';
|
if( buffer.used )
|
||||||
|
|
||||||
wcs = str2wcs( buffer );
|
|
||||||
if( wcs )
|
|
||||||
{
|
{
|
||||||
unescaped = unescape( wcs, 0 );
|
cc=0;
|
||||||
al_push( comp, unescaped );
|
b_append( &buffer, &cc, 1 );
|
||||||
free( wcs );
|
|
||||||
|
wcs = str2wcs( buffer.buff );
|
||||||
|
if( wcs )
|
||||||
|
{
|
||||||
|
unescaped = unescape( wcs, 0 );
|
||||||
|
al_push( comp, unescaped );
|
||||||
|
free( wcs );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b_destroy( &buffer );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main( int argc, char **argv )
|
int main( int argc, char **argv )
|
||||||
|
@ -1032,12 +1104,19 @@ int main( int argc, char **argv )
|
||||||
array_list_t *comp;
|
array_list_t *comp;
|
||||||
wchar_t *prefix;
|
wchar_t *prefix;
|
||||||
|
|
||||||
|
/*
|
||||||
|
This initialization is made early, so that the other init code
|
||||||
|
can use global_context for memory managment
|
||||||
|
*/
|
||||||
|
halloc_util_init();
|
||||||
|
|
||||||
if( argc < 3 )
|
if( argc < 3 )
|
||||||
{
|
{
|
||||||
debug( 0, L"Insufficient arguments" );
|
debug( 0, _(L"Insufficient arguments") );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
comp = al_halloc( global_context );
|
comp = al_halloc( global_context );
|
||||||
prefix = str2wcs( argv[2] );
|
prefix = str2wcs( argv[2] );
|
||||||
is_quoted = strcmp( "1", argv[1] )==0;
|
is_quoted = strcmp( "1", argv[1] )==0;
|
||||||
|
@ -1061,28 +1140,35 @@ int main( int argc, char **argv )
|
||||||
read_array( stdin, comp );
|
read_array( stdin, comp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
mangle_descriptions( comp );
|
mangle_descriptions( comp );
|
||||||
|
|
||||||
if( wcscmp( prefix, L"-" ) == 0 )
|
if( wcscmp( prefix, L"-" ) == 0 )
|
||||||
join_completions( comp );
|
join_completions( comp );
|
||||||
|
|
||||||
mangle_completions( comp, prefix );
|
mangle_completions( comp, prefix );
|
||||||
|
|
||||||
for( i = 6; i>0; i-- )
|
for( i = 6; i>0; i-- )
|
||||||
{
|
{
|
||||||
switch( completion_try_print( i, prefix, is_quoted, comp ) )
|
switch( completion_try_print( i, prefix, is_quoted, comp ) )
|
||||||
{
|
{
|
||||||
case 0:
|
|
||||||
|
case PAGER_RETRY:
|
||||||
break;
|
break;
|
||||||
case 1:
|
|
||||||
|
case PAGER_DONE:
|
||||||
i=0;
|
i=0;
|
||||||
break;
|
break;
|
||||||
case 2:
|
|
||||||
|
case PAGER_RESIZE:
|
||||||
|
/*
|
||||||
|
This means we got a resize event, so we start over from the beginning
|
||||||
|
*/
|
||||||
i=7;
|
i=7;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(prefix );
|
free(prefix );
|
||||||
|
|
Loading…
Reference in a new issue