From 4f197e226788c74f91a0e7b6a85b0793069a2f37 Mon Sep 17 00:00:00 2001 From: axel Date: Sun, 2 Oct 2005 23:40:46 +1000 Subject: [PATCH] Support symbolic keybindings darcs-hash:20051002134046-ac50b-1e3dc058105d30ad0541c99a250e2d33c31dc7e3.gz --- doc_src/doc.hdr | 9 +- input.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 235 insertions(+), 14 deletions(-) diff --git a/doc_src/doc.hdr b/doc_src/doc.hdr index eb2dd4739..4dd73d257 100644 --- a/doc_src/doc.hdr +++ b/doc_src/doc.hdr @@ -638,7 +638,7 @@ Here are some of the commands available in the editor: - Home or Ctrl-a moves to the beginning of the line - End or Ctrl-e moves to the end of line - Left and right moves one character left or right -- Alt-left and Alt-right moves one word left or right +- Alt-left and Alt-right moves one word left or right, or moves forward/backward in the directory history if the commandline is empty - Delete and backspace removes one character forwards or backwards - Ctrl-c delete entire line - Ctrl-d delete one character to the right of the cursor, unless the buffer is empty, in which case the shell will exit @@ -656,10 +656,9 @@ this, copy the file /etc/fish_inputrc to your home directory and rename it to '.fish_inputrc'. Now you can edit the file .fish_inputrc, to change your key bindings. The fileformat of this file is described in the manual page for readline. Use the command man readline -to read up on this syntax. Please note thet the key binding support in -\c fish is still limited. You can not use the set command or the -keyname-syntax, and the list functions is incomplete. Currently, the -following functions are available: +to read up on this syntax. Please note thet the list of key binding +functions in fish is different to that offered by readline. Currently, +the following functions are available: - \c backward-char, moves one character to the left diff --git a/input.c b/input.c index aaa7a4948..2da86c838 100644 --- a/input.c +++ b/input.c @@ -66,6 +66,15 @@ typedef struct } mapping; +/** + Symbolic names for some acces-modifiers used when parsing symbolic sequences +*/ +#define CTRL L"Control-" +/** + Symbolic names for some acces-modifiers used when parsing symbolic sequences +*/ +#define META L"Meta-" + /** Names of all the readline functions supported */ @@ -354,6 +363,175 @@ repaint();*/ } +/** + Parse special character from the specified inputrc-style key binding. + + Control-a is expanded to 1, etc. +*/ + +static wchar_t *input_symbolic_sequence( const wchar_t *in ) +{ + wchar_t *res=0; + + if( !*in || *in == L'\n' ) + return 0; + + debug( 4, L"Try to parse symbolic sequence %ls", in ); + + if( wcsncmp( in, CTRL, wcslen(CTRL) ) == 0 ) + { + int has_meta=0; + + in += wcslen(CTRL); + + /* + Control-Meta- Should be rearranged to Meta-Control, this + special-case must be handled manually. + */ + if( wcsncmp( in, META, wcslen(META) ) == 0 ) + { + in += wcslen(META); + has_meta=1; + } + + wchar_t c = towlower( *in ); + in++; + if( c < L'a' || c > L'z' ) + { + debug( 1, L"Invalid Control sequence" ); + return 0; + } + if( has_meta ) + { + res = wcsdup( L"\ea" ); + res[1]=1+c-L'a'; + } + else + { + res = wcsdup( L"a" ); + res[0]=1+c-L'a'; + } + debug( 4, L"Got control sequence %d", res[0] ); + + } + else if( wcsncmp( in, META, wcslen(META) ) == 0 ) + { + in += wcslen(META); + res = wcsdup( L"\e" ); + debug( 4, L"Got meta" ); + } + else + { + int i; + struct + { + wchar_t *in; + char *out; + } + map[]= + { + { + L"rubout", + key_backspace + } + , + { + L"del", + key_dc + } + , + { + L"esc", + "\e" + } + , + { + L"lfd", + "\r" + } + , + { + L"newline", + "\n" + } + , + { + L"ret", + "\n" + } + , + { + L"return", + "\n" + } + , + { + L"spc", + " " + } + , + { + L"space", + " " + } + , + { + L"tab", + "\t" + } + , + { + 0, + 0 + } + } + ; + + for( i=0; map[i].in; i++ ) + { + if( wcsncmp( in, map[i].in, wcslen(map[i].in) )==0 ) + { + in+= wcslen( map[i].in ); + res = str2wcs( map[i].out ); + + break; + } + } + + if( !res ) + { + if( iswalnum( *in ) || iswpunct( *in ) ) + { + res = wcsdup( L"a" ); + *res = *in++; + debug( 4, L"Got character %lc", *res ); + } + } + } + if( !res ) + { + debug( 1, L"Could not parse sequence %ls", in ); + return 0; + } + if( !*in || *in == L'\n') + { + debug( 4, L"Finished parsing sequence" ); + return res; + } + + wchar_t *res2 = input_symbolic_sequence( in ); + if( !res2 ) + { + free( res ); + return 0; + } + wchar_t *res3 = wcsdupcat( res, res2 ); + free( res); + free(res2); + + return res3; +} + /** Unescape special character from the specified inputrc-style key sequence. @@ -720,16 +898,12 @@ void input_parse_inputrc_line( wchar_t *cmd ) val = cmd; sequence = input_expand_sequence( key ); - add_mapping( L"global", sequence, key, val ); - -// fwprintf( stderr, L"Map %ls to %ls\n", key, val ); - - free( sequence ); - - //fwprintf( stderr, L"Remainder \'%ls\', endchar %d\n", cmd, *cmd ); + if( sequence ) + { + add_mapping( L"global", sequence, key, val ); + free( sequence ); + } - //fwprintf( stderr, L"%ls -> %ls\n", key, val ); - return; } else if( wcsncmp( L"$include ", cmd, wcslen(L"$include ") ) == 0 ) @@ -812,6 +986,54 @@ void input_parse_inputrc_line( wchar_t *cmd ) return; } + else + { + /* + This is a redular key binding, like + + Control-o: kill-word + + Or at least we hope it is, since if it isn't, we have no idea what it is. + */ + + wchar_t *key; + wchar_t *val; + wchar_t *sequence; + wchar_t prev=0; + + key=cmd; + + cmd = wcschr( cmd, ':' ); + + if( !cmd ) + { + debug( 1, + L"Unable to parse binding" ); + inputrc_error = 1; + return; + } + *cmd = 0; + + cmd++; + + while( *cmd == L' ' ) + cmd++; + + val = cmd; + + debug( 1, L"Map %ls to %ls\n", key, val ); + + sequence = input_symbolic_sequence( key ); + if( sequence ) + { + add_mapping( L"global", sequence, key, val ); + free( sequence ); + } + + return; + + } + debug( 1, L"I don\'t know what %ls means", cmd ); }