aboutsummaryrefslogtreecommitdiffhomepage
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
parent9c32709fe1c48b30ca49150b955fb756d11ece44 (diff)
Autodetect common escape codes in fish_prompt output
darcs-hash:20051213101859-ac50b-0ff01bb168d894d401d3d93cc11740789bac0d62.gz
-rw-r--r--doc_src/doc.hdr8
-rw-r--r--init/fish_interactive.fish.in2
-rw-r--r--output.c2
-rw-r--r--reader.c137
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
#
diff --git a/output.c b/output.c
index e1e2f848..4578acb5 100644
--- a/output.c
+++ b/output.c
@@ -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;
}
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*/