First stab at dropping all support for readlines inputrc files and instead using an internal system for performing keybinding.

darcs-hash:20070925161447-75c98-1feaef88a4b518badb7879f598f06ab650a8f93b.gz
This commit is contained in:
liljencrantz 2007-09-26 02:14:47 +10:00
parent af9c2067e1
commit cf8e746d0c
11 changed files with 757 additions and 1359 deletions

246
builtin.c
View file

@ -402,14 +402,153 @@ static void builtin_missing_argument( const wchar_t *cmd, const wchar_t *opt )
#include "builtin_ulimit.c"
#include "builtin_jobs.c"
static void builtin_bind_list()
{
array_list_t lst;
int i;
al_init( &lst );
input_mapping_get_names( &lst );
for( i=0; i<al_get_count(&lst); i++ )
{
wchar_t *seq = (wchar_t *)al_get( &lst, i );
const wchar_t *tname = input_terminfo_get_name( seq );
wchar_t *ecmd = escape( input_mapping_get( seq ), 1 );
if( tname )
{
sb_printf( sb_out, L"bind -k %ls %ls\n", tname, ecmd );
}
else
{
wchar_t *eseq = escape( seq, 1 );
sb_printf( sb_out, L"bind %ls %ls\n", eseq, ecmd );
free( eseq );
}
free( ecmd );
}
al_destroy( &lst );
}
static void builtin_bind_key_names( int all )
{
array_list_t lst;
int i;
al_init( &lst );
input_terminfo_get_names( &lst, !all );
for( i=0; i<al_get_count(&lst); i++ )
{
wchar_t *seq = (wchar_t *)al_get( &lst, i );
sb_printf( sb_out, L"%ls\n", seq );
}
al_destroy( &lst );
}
static void builtin_bind_function_names()
{
array_list_t lst;
int i;
al_init( &lst );
input_function_get_names( &lst );
for( i=0; i<al_get_count(&lst); i++ )
{
wchar_t *seq = (wchar_t *)al_get( &lst, i );
sb_printf( sb_out, L"%ls\n", seq );
}
al_destroy( &lst );
}
static int builtin_bind_add( wchar_t *seq, wchar_t *cmd, int terminfo )
{
if( terminfo )
{
const wchar_t *seq2 = input_terminfo_get_sequence( seq );
if( seq2 )
{
input_mapping_add( seq2, cmd );
}
else
{
return 1;
}
}
else
{
input_mapping_add( seq, cmd );
}
return 0;
}
static void builtin_bind_erase( wchar_t **seq, int all )
{
if( all )
{
int i;
array_list_t lst;
al_init( &lst );
input_mapping_get_names( &lst );
for( i=0; i<al_get_count( &lst ); i++ )
{
input_mapping_erase( (wchar_t *)al_get( &lst, i ) );
}
al_destroy( &lst );
}
else
{
while( *seq )
{
input_mapping_erase( *seq++ );
}
}
}
/**
The bind builtin, used for setting character sequences
*/
static int builtin_bind( wchar_t **argv )
{
enum
{
BIND_INSERT,
BIND_ERASE,
BIND_KEY_NAMES,
BIND_FUNCTION_NAMES
}
;
int i;
int argc=builtin_count_args( argv );
int mode = BIND_INSERT;
int res = STATUS_BUILTIN_OK;
int all = 0;
int use_terminfo = 0;
woptind=0;
@ -417,13 +556,29 @@ static int builtin_bind( wchar_t **argv )
long_options[] =
{
{
L"set-mode", required_argument, 0, 'M'
L"all", no_argument, 0, 'a'
}
,
{
L"erase", no_argument, 0, 'e'
}
,
{
L"function-names", no_argument, 0, 'f'
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
L"key", no_argument, 0, 'k'
}
,
{
L"key-names", no_argument, 0, 'K'
}
,
{
0, 0, 0, 0
}
@ -433,12 +588,12 @@ static int builtin_bind( wchar_t **argv )
while( 1 )
{
int opt_index = 0;
int opt = wgetopt_long( argc,
argv,
L"M:h",
long_options,
&opt_index );
argv,
L"aehkKf",
long_options,
&opt_index );
if( opt == -1 )
break;
@ -455,14 +610,31 @@ static int builtin_bind( wchar_t **argv )
return STATUS_BUILTIN_ERROR;
case 'M':
input_set_mode( woptarg );
case 'a':
all = 1;
break;
case 'e':
mode = BIND_ERASE;
break;
case 'h':
builtin_print_help( argv[0], sb_out );
return STATUS_BUILTIN_OK;
case 'k':
use_terminfo = 1;
break;
case 'K':
mode = BIND_KEY_NAMES;
break;
case 'f':
mode = BIND_FUNCTION_NAMES;
break;
case '?':
builtin_unknown_option( argv[0], argv[woptind-1] );
return STATUS_BUILTIN_ERROR;
@ -471,12 +643,64 @@ static int builtin_bind( wchar_t **argv )
}
for( i=woptind; i<argc; i++ )
switch( mode )
{
input_parse_inputrc_line( argv[i] );
case BIND_ERASE:
{
builtin_bind_erase( &argv[woptind], all);
break;
}
case BIND_INSERT:
{
switch( argc-woptind )
{
case 0:
{
builtin_bind_list();
break;
}
case 2:
{
builtin_bind_add(argv[woptind], argv[woptind+1], use_terminfo );
break;
}
default:
{
res = STATUS_BUILTIN_ERROR;
sb_printf( sb_err, _(L"%ls: Expected zero or two parameters, got %d"), argv[0], argc-woptind );
break;
}
}
break;
}
case BIND_KEY_NAMES:
{
builtin_bind_key_names( all );
break;
}
case BIND_FUNCTION_NAMES:
{
builtin_bind_function_names();
break;
}
default:
{
res = STATUS_BUILTIN_ERROR;
sb_printf( sb_err, _(L"%ls: Invalid state\n"), argv[0] );
break;
}
}
return STATUS_BUILTIN_OK;
return res;
}
/**

View file

@ -448,7 +448,7 @@ static int builtin_commandline( wchar_t **argv )
}
for( i=woptind; i<argc; i++ )
{
wint_t c = input_get_code( argv[i] );
wint_t c = input_function_get_code( argv[i] );
if( c != -1 )
{
/*

View file

@ -1,23 +1,43 @@
\section bind bind - handle key bindings
\section bind bind - handle fish key bindings
\subsection bind-synopsis Synopsis
<tt>bind [OPTIONS] [BINDINGS...]</tt>
The <tt>bind</tt> builtin causes fish to add the readline style bindings specified by BINDINGS to the list of key bindings, as if they appeared in your <tt>~/.fish_inputrc</tt> file.
For more information on the syntax keyboard bindings, use <tt>man
readline</tt> to access the readline documentation. The available commands
are listed in the <a href="index.html#editor">Command Line Editor</a> section
of the fish manual - but you may also use any fish command! To write such
commands, see the <a href="#commandline">commandline</a> builtin. It's good
practice to put the code into a <tt><a href="#function">function</a> -b</tt>
and bind to the function name.
<tt>bind [OPTIONS] SEQUENCE COMMAND</tt>
\subsection bind-description Description
- <tt>-M MODE</tt> or <tt>--set-mode=MODE</tt> sets the current input mode to MODE.
The <tt>bind</tt> builtin causes fish to add a key binding from the specified sequence.
SEQUENCE is the character sequence to bind to. Usually, one would use
fish escape sequences to express them. For example, Alt-w can be
written as <tt>\\ew</tt>, and Control-x can be written as
<tt>\\cx</tt>.
If the -k switch is used, the name of the key (such as down, up or
backspace) is used instead of a sequence. The names used are the same
as the corresponding curses variables, but without the 'key_'
prefix. (See man 5 terminfo for more information, or use <tt>bind
--names</tt> for a list of all available named keys)
COMMAND can be any fish command, but it can also be one of a set of
special input functions. These include functions for moving the
cursor, operating on the kill-ring, performing tab completion,
etc. Use 'bind -N' for a complete list of these input functions.
When COMMAND is a shellscript command, it is a good practice to put
the actual code into a <a href="#function">function</a> and simply
bind to the function name.
- <tt>-a</tt> or <tt>--all</tt> If --print-key-names is specified, show all key names, not only the ones that actually are defined for the current terminal. If erase mode is specified, this switch will cause all current bindings to be erased.
- <tt>-e</tt> or <tt>--erase</tt> Erase mode. All non-switch arguments are interpreted as character sequences and any commands associated with those sequences are erased.
- <tt>-h</tt> or <tt>--help</tt> Display help and exit
- <tt>-k</tt> or <tt>--key</tt> Specify a key name, such as 'left' or 'backspace' instead of a character sequence
- <tt>-K</tt> or <tt>--key-names</tt> Display a list of available key names
- <tt>-f</tt> or <tt>--function-names</tt> Display a list of available input functions
\subsection bind-example Example
<tt>bind -M vi</tt> changes to the vi input mode
<tt>bind \cd 'exit'</tt> causes fish to exit on Control-d
<tt>bind -k ppage history-search-backward</tt> Causes fish to perform a history search when the page up key is pressed
<tt>bind '"\\M-j": jobs'</tt> Binds the jobs command to the Alt-j keyboard shortcut

View file

@ -1,28 +0,0 @@
#
# This file contains key bindings for fish
#
# Include system-wide inputrc file before including fish-specific key
# bindings if it exists
$include /etc/inputrc
$if fish
"\M-l": __fish_list_current_token
"\M-w": set tok (commandline -pt); if test $tok[1]; whatis $tok[1]; commandline -f repaint; end
"\C-l": clear; commandline -f repaint
"\C-c": delete-line
"\C-u": backward-kill-line
"\M-d": kill-word
"\C-w": backward-kill-word
"\M-k": dump-functions
"\M-d": if test -z (commandline); dirh; commandline -f repaint; else; commandline -f kill-word; end
"\C-d": delete-or-exit
# This will make sure the output of the current command is paged using the less pager when you press Meta-p
"\M-p": if commandline -j|grep -v 'less *$' >/dev/null; commandline -aj "|less;"; end
$endif
# Include user-specific inputrc file after including fish-specific
# bindings so that they will override fish defaults
$include ~/.inputrc

1552
input.c

File diff suppressed because it is too large Load diff

40
input.h
View file

@ -99,26 +99,42 @@ void input_unreadch( wint_t ch );
\param d a description of the sequence
\param cmd an input function that will be run whenever the key sequence occurs
*/
void add_mapping( const wchar_t *mode, const wchar_t *s, const wchar_t * d, const wchar_t *cmd );
void input_mapping_add( const wchar_t *sequence, const wchar_t *cmd );
void input_mapping_get_names( array_list_t *list );
int input_mapping_erase( const wchar_t *sequence );
const wchar_t *input_mapping_get( const wchar_t *sequence );
/**
Sets the mode keybindings.
*/
void input_set_mode( wchar_t *name );
Return the sequence for the terminfo variable of the specified name.
If no terminfo variable of the specified name could be found, return 0 and set errno to ENOENT.
If the terminfo variable does not have a value, return 0 and set errno to EILSEQ.
*/
const wchar_t *input_terminfo_get_sequence( const wchar_t *name );
/**
Sets the application keybindings
*/
void input_set_application( wchar_t *name );
Return the name of the terminfo variable with the specified sequence
*/
const wchar_t *input_terminfo_get_name( const wchar_t *seq );
/**
Parse a single line of inputrc information.
*/
void input_parse_inputrc_line( wchar_t *cmd );
Return a list of all known terminfo names
*/
void input_terminfo_get_names( array_list_t *lst, int skip_null );
/**
Returns the function for the given function name.
Returns the input function code for the given input function name.
*/
wchar_t input_get_code( const wchar_t *name );
wchar_t input_function_get_code( const wchar_t *name );
/**
Returns a list of all existing input function names
*/
void input_function_get_names( array_list_t *lst );
#endif

View file

@ -1,3 +1,12 @@
complete -c bind -s a -l all --description 'Show unavaliable key bindings/erase all bindings'
complete -c bind -s e -l erase --description 'Erase mode'
complete -c bind -s f -l function-names --description 'Print names of available functions'
complete -c bind -s h -l help --description "Display help and exit"
complete -c bind -s M -l set-mode --description 'Change input mode'
complete -c bind -s k -l key --description 'Specify key name, not sequence'
complete -c bind -s K -l key-names --description 'Print names of available keys'
complete -c bind -n __fish_bind_test1 -a '(bind --key-names)' -d 'Key name' -x
complete -c bind -n __fish_bind_test2 -a '(bind --function-names)' -d 'Function name' -x

View file

@ -0,0 +1,27 @@
function __fish_bind_test1
set -l args
set -l use_keys no
for i in (commandline -poc)
switch $i
case -k --k --ke --key
set use_keys yes
case "-*"
case "*"
set args $args $i
end
end
switch $use_keys
case yes
switch (count $args)
case 1
return 0
end
end
return 1
end

View file

@ -0,0 +1,20 @@
function __fish_bind_test2
set -l args
for i in (commandline -poc)
switch $i
case "-*"
case "*"
set args $args $i
end
end
switch (count $args)
case 2
return 0
end
return 1
end

View file

@ -99,24 +99,6 @@ function __fish_config_interactive -d "Initializations that should be performed
printf (_ "Good bye\n")
end
#
# Set INPUTRC to something nice
#
# We override INPUTRC if already set, since it may be set by a shell
# other than fish, which may use a different file. The new value should
# be exported, since the fish inputrc file plays nice with other files
# by including them when found.
#
for i in $configdir/fish/fish_inputrc $__fish_sysconfdir/fish_inputrc ~/.inputrc /etc/inputrc
if test -f $i
set -xg INPUTRC $i
break
end
end
#
# Set various defaults using these throwaway functions
#
@ -203,4 +185,15 @@ function __fish_config_interactive -d "Initializations that should be performed
complete -x -p "/etc/init.d/*" -a restart --description 'Stop and then start service'
complete -x -p "/etc/init.d/*" -a reload --description 'Reload service configuration'
if not set -q fish_key_bindings
set -U fish_key_bindings fish_default_key_bindings
end
eval $fish_key_bindings
function __fish_reload_key_bindings -d "Reload keybindings when binding variable change"
eval $fish_key_bindings
end
end

View file

@ -0,0 +1,91 @@
function fish_default_key_bindings -d "Default (Emacs-like) key bindings for fish"
# Clear earlier bindings, if any
bind --erase --all
# This is the default binding, i.e. the one used if no other binding matches
bind "" self-insert
bind \n execute
bind \ck kill-line
bind \cy yank
bind \t complete
bind \e\n "commandline -i \n"
bind \e\[A up-or-search
bind \e\[B down-or-search
bind -k down down-or-search
bind -k up up-or-search
bind \e\[C forward-char
bind \e\[D backward-char
bind -k right forward-char
bind -k left backward-char
bind -k dc delete-char
bind -k backspace backward-delete-char
bind \x7f backward-delete-char
bind \e\[H beginning-of-line
bind \e\[F end-of-line
bind -k home beginning-of-line
bind -k end end-of-line
bind \e\eOC nextd-or-forward-word
bind \e\eOD prevd-or-backward-word
bind \e\e\[C nextd-or-forward-word
bind \e\e\[D prevd-or-backward-word
bind \eO3C nextd-or-forward-word
bind \eO3D prevd-or-backward-word
bind \e\[3C nextd-or-forward-word
bind \e\[3D prevd-or-backward-word
bind \e\[1\;3C nextd-or-forward-word
bind \e\[1\;3D prevd-or-backward-word
bind \e\eOA history-token-search-backward
bind \e\eOB history-token-search-forward
bind \e\e\[A history-token-search-backward
bind \e\e\[B history-token-search-forward
bind \eO3A history-token-search-backward
bind \eO3B history-token-search-forward
bind \e\[3A history-token-search-backward
bind \e\[3B history-token-search-forward
bind \e\[1\;3A history-token-search-backward
bind \e\[1\;3B history-token-search-forward
bind \ca beginning-of-line
bind \ce end-of-line
bind \ey yank-pop
bind \ch backward-delete-char
bind \cw backward-kill-word
bind \cp history-search-backward
bind \cn history-search-forward
bind \cf forward-char
bind \cb backward-char
bind \e\x7f backward-kill-word
bind \eb backward-word
bind \ef forward-word
bind \ed forward-kill-word
bind -k ppage beginning-of-history
bind -k npage end-of-history
bind \e\< beginning-of-buffer
bind \e\> end-of-buffer
bind \el __fish_list_current_token
bind \ew 'set tok (commandline -pt); if test $tok[1]; whatis $tok[1]; commandline -f repaint; end'
bind \cl 'clear; commandline -f repaint'
bind \cc delete-line
bind \cu backward-kill-line
bind \ed kill-word
bind \cw backward-kill-word
bind \ed 'if test -z (commandline); dirh; commandline -f repaint; else; commandline -f kill-word; end'
bind \cd delete-or-exit
# This will make sure the output of the current command is paged using the less pager when you press Meta-p
bind \ep 'if commandline -j|grep -v "less *\$" >/dev/null; commandline -aj "|less;"; end'
end