diff options
author | 2005-12-13 20:18:59 +1000 | |
---|---|---|
committer | 2005-12-13 20:18:59 +1000 | |
commit | 8bf0a14bd5124219d76ac40ff985380bb00297d5 (patch) | |
tree | 59a410307954aa1bf1c2007ea3f6e515ce6e42ae | |
parent | 9c32709fe1c48b30ca49150b955fb756d11ece44 (diff) |
Autodetect common escape codes in fish_prompt output
darcs-hash:20051213101859-ac50b-0ff01bb168d894d401d3d93cc11740789bac0d62.gz
-rw-r--r-- | doc_src/doc.hdr | 8 | ||||
-rw-r--r-- | init/fish_interactive.fish.in | 2 | ||||
-rw-r--r-- | output.c | 2 | ||||
-rw-r--r-- | reader.c | 137 |
4 files changed, 129 insertions, 20 deletions
diff --git a/doc_src/doc.hdr b/doc_src/doc.hdr index 64b165e5..e1ef257c 100644 --- a/doc_src/doc.hdr +++ b/doc_src/doc.hdr @@ -915,17 +915,11 @@ The default \c fish prompt is <p> <pre> function fish_prompt -d "Write out the prompt" - printf '\%s\@\%s\%s\\n\%s\%s\\n> ' (whoami) (hostname|cut -d . -f 1) (set_color \$fish_color_cwd) (prompt_pwd) (set_color normal) + printf '\%s\@\%s\%s\%s\%s> ' (whoami) (hostname|cut -d . -f 1) (set_color \$fish_color_cwd) (prompt_pwd) (set_color normal) end </pre> </p> -If you are using \c set_color or other commands that output escape -codes to change the font settings of the terminal, you must always and -every such sequence with a newline. This is needed since fish needs to -know that exact length of the prompt in order to tetect when the -cursor reaches the end of the line. Any newlines in the output of the -\c fish_prompt command are ignored. \subsection title Programmable title diff --git a/init/fish_interactive.fish.in b/init/fish_interactive.fish.in index fc55b778..11c2f08f 100644 --- a/init/fish_interactive.fish.in +++ b/init/fish_interactive.fish.in @@ -29,7 +29,7 @@ end # long it is. function fish_prompt -d "Write out the prompt" - printf '%s@%s \n%s\n%s\n%s\n> ' (whoami) (hostname|cut -d . -f 1) (set_color $fish_color_cwd) (prompt_pwd) (set_color normal) + printf '%s@%s %s%s%s> \n' (whoami) (hostname|cut -d . -f 1) (set_color $fish_color_cwd) (prompt_pwd) (set_color normal) end # @@ -128,7 +128,7 @@ void set_color( int c, int c2 ) { c = c2 = FISH_COLOR_NORMAL; if( fg ) - writembs( tparm( set_a_foreground, 0 ) ); + writembs( tparm( fg, 0 ) ); writembs( exit_attribute_mode ); return; } @@ -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*/ |