aboutsummaryrefslogtreecommitdiffhomepage
path: root/reader.c
diff options
context:
space:
mode:
authorGravatar axel <axel@liljencrantz.se>2005-12-13 20:18:59 +1000
committerGravatar axel <axel@liljencrantz.se>2005-12-13 20:18:59 +1000
commit8bf0a14bd5124219d76ac40ff985380bb00297d5 (patch)
tree59a410307954aa1bf1c2007ea3f6e515ce6e42ae /reader.c
parent9c32709fe1c48b30ca49150b955fb756d11ece44 (diff)
Autodetect common escape codes in fish_prompt output
darcs-hash:20051213101859-ac50b-0ff01bb168d894d401d3d93cc11740789bac0d62.gz
Diffstat (limited to 'reader.c')
-rw-r--r--reader.c137
1 files changed, 126 insertions, 11 deletions
diff --git a/reader.c b/reader.c
index c4183916..e790db3b 100644
--- a/reader.c
+++ b/reader.c
@@ -621,6 +621,129 @@ void reader_write_title()
}
/**
+ Tests if the specified narrow character sequence is present at the
+ specified position of the specified wide character string. All of
+ \c seq must match, but str may be longer than seq.
+*/
+static int try_sequence( char *seq, wchar_t *str )
+{
+ int i;
+
+ for( i=0;; i++ )
+ {
+ if( !seq[i] )
+ return i;
+
+ if( seq[i] != str[i] )
+ return 0;
+ }
+
+ return 0;
+}
+
+/**
+ Calculate the width of the specified prompt. Does some clever magic
+ to detect common escape sequences that may be embeded in a prompt,
+ such as color codes.
+*/
+static int calc_prompt_width( array_list_t *arr )
+{
+ int res = 0;
+ int i, j, k;
+
+ for( i=0; i<al_get_count( arr ); i++ )
+ {
+ wchar_t *next = (wchar_t *)al_get( arr, i );
+
+ for( j=0; next[j]; j++ )
+ {
+ if( next[j] == L'\e' )
+ {
+ /*
+ This is the start of an escape code. Try to guess it's width.
+ */
+ int l;
+ int len=0;
+ int found = 0;
+
+ /*
+ Test these color escapes with parameter value 0..7
+ */
+ char * esc[] =
+ {
+ set_a_foreground,
+ set_a_background,
+ set_foreground,
+ set_background,
+ }
+ ;
+
+ /*
+ Test these regular escapes without any parameter values
+ */
+ char *esc2[] =
+ {
+ enter_bold_mode,
+ exit_attribute_mode,
+ enter_underline_mode,
+ exit_underline_mode,
+ enter_standout_mode,
+ exit_standout_mode,
+ flash_screen
+ }
+ ;
+
+ for( l=0; l < (sizeof(esc)/sizeof(char *)) && !found; l++ )
+ {
+ if( !esc[l] )
+ continue;
+
+ for( k=0; k<8; k++ )
+ {
+ len = try_sequence( tparm(esc[l],k), &next[j] );
+ if( len )
+ {
+ j += (len-1);
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ for( l=0; l < (sizeof(esc2)/sizeof(char *)) && !found; l++ )
+ {
+ if( !esc2[l] )
+ continue;
+ /*
+ Test both padded and unpadded version, just to
+ be safe. Most versions of tparm don't actually
+ seem to do anything these days.
+ */
+ len = maxi( try_sequence( tparm(esc2[l]), &next[j] ),
+ try_sequence( esc2[l], &next[j] ));
+
+ if( len )
+ {
+ j += (len-1);
+ found = 1;
+ }
+ }
+ }
+ else
+ {
+ /*
+ Ordinary decent character. Just add width.
+ */
+ res += wcwidth( next[j] );
+ }
+
+ }
+ }
+ return res;
+}
+
+
+/**
Write the prompt to screen. If data->exec_prompt is set, the prompt
command is first evaluated, and the title will be reexecuted as
well.
@@ -649,14 +772,8 @@ static void write_prompt()
al_init( &prompt_list );
}
}
- data->prompt_width=0;
- for( i=0; i<al_get_count( &prompt_list ); i++ )
- {
- wchar_t *next = (wchar_t *)al_get( &prompt_list, i );
- if( *next == L'\e' )
- continue;
- data->prompt_width += my_wcswidth( next );
- }
+
+ data->prompt_width=calc_prompt_width( &prompt_list );
data->exec_prompt = 0;
reader_write_title();
@@ -2509,9 +2626,7 @@ wchar_t *reader_readline()
if( last_char != R_YANK && last_char != R_YANK_POP )
yank=0;
-
-
- switch (c)
+ switch( c )
{
/* go to beginning of line*/