Implement bind modes

This commit is contained in:
Julian Aron Prenner 2013-12-31 01:52:41 +01:00
parent 1efb120248
commit d1faac58dd
4 changed files with 185 additions and 22 deletions

View File

@ -414,18 +414,20 @@ static void builtin_bind_list()
wcstring seq = lst.at(i); wcstring seq = lst.at(i);
wcstring ecmd; wcstring ecmd;
input_mapping_get(seq, ecmd); wcstring mode;
input_mapping_get(seq, ecmd, mode);
ecmd = escape_string(ecmd, 1); ecmd = escape_string(ecmd, 1);
wcstring tname; wcstring tname;
if (input_terminfo_get_name(seq, tname)) if (input_terminfo_get_name(seq, tname))
{ {
append_format(stdout_buffer, L"bind -k %ls %ls\n", tname.c_str(), ecmd.c_str()); append_format(stdout_buffer, L"bind -k %ls %ls (in mode `%ls')\n", tname.c_str(), ecmd.c_str(), mode.c_str());
} }
else else
{ {
const wcstring eseq = escape_string(seq, 1); const wcstring eseq = escape_string(seq, 1);
append_format(stdout_buffer, L"bind %ls %ls\n", eseq.c_str(), ecmd.c_str()); append_format(stdout_buffer, L"bind %ls %ls (in mode `%ls')\n", eseq.c_str(), ecmd.c_str(), mode.c_str());
} }
} }
} }
@ -466,7 +468,7 @@ static void builtin_bind_function_names()
/** /**
Add specified key binding. Add specified key binding.
*/ */
static int builtin_bind_add(const wchar_t *seq, const wchar_t *cmd, int terminfo) static int builtin_bind_add(const wchar_t *seq, const wchar_t *cmd, const wchar_t *mode, const wchar_t *new_mode, int terminfo)
{ {
if (terminfo) if (terminfo)
@ -474,7 +476,7 @@ static int builtin_bind_add(const wchar_t *seq, const wchar_t *cmd, int terminfo
wcstring seq2; wcstring seq2;
if (input_terminfo_get_sequence(seq, &seq2)) if (input_terminfo_get_sequence(seq, &seq2))
{ {
input_mapping_add(seq2.c_str(), cmd); input_mapping_add(seq2.c_str(), cmd, mode, new_mode);
} }
else else
{ {
@ -507,7 +509,7 @@ static int builtin_bind_add(const wchar_t *seq, const wchar_t *cmd, int terminfo
} }
else else
{ {
input_mapping_add(seq, cmd); input_mapping_add(seq, cmd, mode, new_mode);
} }
return 0; return 0;
@ -566,6 +568,9 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
int res = STATUS_BUILTIN_OK; int res = STATUS_BUILTIN_OK;
int all = 0; int all = 0;
const wchar_t *bind_mode = DEFAULT_BIND_MODE;
const wchar_t *new_bind_mode = DEFAULT_BIND_MODE;
int use_terminfo = 0; int use_terminfo = 0;
woptind=0; woptind=0;
@ -597,6 +602,14 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
L"key-names", no_argument, 0, 'K' L"key-names", no_argument, 0, 'K'
} }
, ,
{
L"mode", required_argument, 0, 'M'
}
,
{
L"new-mode", required_argument, 0, 'm'
}
,
{ {
0, 0, 0, 0 0, 0, 0, 0
} }
@ -608,7 +621,7 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
int opt_index = 0; int opt_index = 0;
int opt = wgetopt_long(argc, int opt = wgetopt_long(argc,
argv, argv,
L"aehkKf", L"aehkKfM:m:",
long_options, long_options,
&opt_index); &opt_index);
@ -636,7 +649,6 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
mode = BIND_ERASE; mode = BIND_ERASE;
break; break;
case 'h': case 'h':
builtin_print_help(parser, argv[0], stdout_buffer); builtin_print_help(parser, argv[0], stdout_buffer);
return STATUS_BUILTIN_OK; return STATUS_BUILTIN_OK;
@ -653,10 +665,19 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
mode = BIND_FUNCTION_NAMES; mode = BIND_FUNCTION_NAMES;
break; break;
case 'M':
bind_mode = woptarg;
break;
case 'm':
new_bind_mode = woptarg;
break;
case '?': case '?':
builtin_unknown_option(parser, argv[0], argv[woptind-1]); builtin_unknown_option(parser, argv[0], argv[woptind-1]);
return STATUS_BUILTIN_ERROR; return STATUS_BUILTIN_ERROR;
} }
} }
@ -682,7 +703,7 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
case 2: case 2:
{ {
builtin_bind_add(argv[woptind], argv[woptind+1], use_terminfo); builtin_bind_add(argv[woptind], argv[woptind+1], bind_mode, new_bind_mode, use_terminfo);
break; break;
} }
@ -721,6 +742,34 @@ static int builtin_bind(parser_t &parser, wchar_t **argv)
return res; return res;
} }
/**
The bind mode builtin
*/
static int builtin_bind_mode(parser_t &parser, wchar_t **argv)
{
int res = STATUS_BUILTIN_OK;
int argc = builtin_count_args(argv);
switch (argc)
{
case 1:
{
append_format(stdout_buffer, L"%ls\n", input_get_bind_mode());
break;
}
default:
{
res = STATUS_BUILTIN_ERROR;
append_format(stderr_buffer, _(L"%ls: Expected no parameters, got %d"), argv[0], argc);
break;
}
}
return res;
}
/** /**
The block builtin, used for temporarily blocking events The block builtin, used for temporarily blocking events
*/ */
@ -3979,6 +4028,7 @@ static const builtin_data_t builtin_datas[]=
{ L"begin", &builtin_begin, N_(L"Create a block of code") }, { L"begin", &builtin_begin, N_(L"Create a block of code") },
{ L"bg", &builtin_bg, N_(L"Send job to background") }, { L"bg", &builtin_bg, N_(L"Send job to background") },
{ L"bind", &builtin_bind, N_(L"Handle fish key bindings") }, { L"bind", &builtin_bind, N_(L"Handle fish key bindings") },
{ L"bind_mode", &builtin_bind_mode, N_(L"Set or get the current bind mode") },
{ L"block", &builtin_block, N_(L"Temporarily block delivery of events") }, { L"block", &builtin_block, N_(L"Temporarily block delivery of events") },
{ L"break", &builtin_break_continue, N_(L"Stop the innermost loop") }, { L"break", &builtin_break_continue, N_(L"Stop the innermost loop") },
{ L"breakpoint", &builtin_breakpoint, N_(L"Temporarily halt execution of a script and launch an interactive debug prompt") }, { L"breakpoint", &builtin_breakpoint, N_(L"Temporarily halt execution of a script and launch an interactive debug prompt") },

View File

@ -61,7 +61,6 @@
#include <vector> #include <vector>
#define DEFAULT_TERM L"ansi" #define DEFAULT_TERM L"ansi"
/** /**
Struct representing a keybinding. Returned by input_get_mappings. Struct representing a keybinding. Returned by input_get_mappings.
*/ */
@ -69,9 +68,12 @@ struct input_mapping_t
{ {
wcstring seq; /**< Character sequence which generates this event */ wcstring seq; /**< Character sequence which generates this event */
wcstring command; /**< command that should be evaluated by this mapping */ wcstring command; /**< command that should be evaluated by this mapping */
wcstring mode; /**< mode in which this command should be evaluated */
wcstring new_mode; /** new mode that should be switched to after command evaluation */
input_mapping_t(const wcstring &s, const wcstring &c,
input_mapping_t(const wcstring &s, const wcstring &c) : seq(s), command(c) {} const wcstring &m = DEFAULT_BIND_MODE,
const wcstring &nm = DEFAULT_BIND_MODE) : seq(s), command(c), mode(m), new_mode(nm) {}
}; };
/** /**
@ -226,6 +228,9 @@ static const wchar_t code_arr[] =
/** Mappings for the current input mode */ /** Mappings for the current input mode */
static std::vector<input_mapping_t> mapping_list; static std::vector<input_mapping_t> mapping_list;
#define MAX_BIND_MODE_NAME_SIZE 512
static wchar_t bind_mode[MAX_BIND_MODE_NAME_SIZE] = DEFAULT_BIND_MODE;
/* Terminfo map list */ /* Terminfo map list */
static std::vector<terminfo_mapping_t> terminfo_mappings; static std::vector<terminfo_mapping_t> terminfo_mappings;
@ -248,28 +253,55 @@ static bool is_init = false;
*/ */
static void input_terminfo_init(); static void input_terminfo_init();
/**
Return the current bind mode
*/
const wchar_t *input_get_bind_mode()
{
return bind_mode;
}
/**
Set the current bind mode
*/
bool input_set_bind_mode(const wchar_t *bm)
{
int len = wcslen(bm) * sizeof(wchar_t);
if(len >= MAX_BIND_MODE_NAME_SIZE)
{
return false;
}
memset(bind_mode, 0, MAX_BIND_MODE_NAME_SIZE);
memcpy(bind_mode, bm, len);
return true;
}
/** /**
Returns the function description for the given function code. Returns the function description for the given function code.
*/ */
void input_mapping_add(const wchar_t *sequence, const wchar_t *command) void input_mapping_add(const wchar_t *sequence, const wchar_t *command,
const wchar_t *mode, const wchar_t *new_mode)
{ {
CHECK(sequence,); CHECK(sequence,);
CHECK(command,); CHECK(command,);
CHECK(mode,);
CHECK(new_mode,);
// debug( 0, L"Add mapping from %ls to %ls", escape(sequence, 1), escape(command, 1 ) ); // debug( 0, L"Add mapping from %ls to %ls in mode %ls", escape(sequence, 1), escape(command, 1 ), mode);
for (size_t i=0; i<mapping_list.size(); i++) for (size_t i=0; i<mapping_list.size(); i++)
{ {
input_mapping_t &m = mapping_list.at(i); input_mapping_t &m = mapping_list.at(i);
if (m.seq == sequence) if (m.seq == sequence && m.mode == mode)
{ {
m.command = command; m.command = command;
m.new_mode = new_mode;
return; return;
} }
} }
mapping_list.push_back(input_mapping_t(sequence, command)); mapping_list.push_back(input_mapping_t(sequence, command, mode, new_mode));
} }
/** /**
@ -536,9 +568,18 @@ wint_t input_readch()
for (i=0; i<mapping_list.size(); i++) for (i=0; i<mapping_list.size(); i++)
{ {
const input_mapping_t &m = mapping_list.at(i); const input_mapping_t &m = mapping_list.at(i);
if(wcscmp(m.mode.c_str(), input_get_bind_mode()))
{
continue;
}
wint_t res = input_try_mapping(m); wint_t res = input_try_mapping(m);
if (res) if (res)
{
input_set_bind_mode(m.new_mode.c_str());
return res; return res;
}
if (m.seq.length() == 0) if (m.seq.length() == 0)
{ {
@ -591,7 +632,7 @@ void input_mapping_get_names(wcstring_list_t &lst)
} }
bool input_mapping_erase(const wchar_t *sequence) bool input_mapping_erase(const wchar_t *sequence, const wchar_t *mode)
{ {
ASSERT_IS_MAIN_THREAD(); ASSERT_IS_MAIN_THREAD();
bool result = false; bool result = false;
@ -600,7 +641,7 @@ bool input_mapping_erase(const wchar_t *sequence)
for (i=0; i<sz; i++) for (i=0; i<sz; i++)
{ {
const input_mapping_t &m = mapping_list.at(i); const input_mapping_t &m = mapping_list.at(i);
if (sequence == m.seq) if (sequence == m.seq && mode == m.mode)
{ {
if (i != (sz-1)) if (i != (sz-1))
{ {
@ -615,7 +656,7 @@ bool input_mapping_erase(const wchar_t *sequence)
return result; return result;
} }
bool input_mapping_get(const wcstring &sequence, wcstring &cmd) bool input_mapping_get(const wcstring &sequence, wcstring &cmd, wcstring &mode)
{ {
size_t i, sz = mapping_list.size(); size_t i, sz = mapping_list.size();
@ -625,6 +666,7 @@ bool input_mapping_get(const wcstring &sequence, wcstring &cmd)
if (sequence == m.seq) if (sequence == m.seq)
{ {
cmd = m.command; cmd = m.command;
mode = m.mode;
return true; return true;
} }
} }

21
input.h
View File

@ -11,6 +11,9 @@ inputrc information for key bindings.
#include <wchar.h> #include <wchar.h>
#include "input_common.h" #include "input_common.h"
#define DEFAULT_BIND_MODE L"default"
/** /**
Key codes for inputrc-style keyboard functions that are passed on Key codes for inputrc-style keyboard functions that are passed on
to the caller of input_read() to the caller of input_read()
@ -102,7 +105,9 @@ void input_unreadch(wint_t ch);
\param sequence the sequence to bind \param sequence the sequence to bind
\param command an input function that will be run whenever the key sequence occurs \param command an input function that will be run whenever the key sequence occurs
*/ */
void input_mapping_add(const wchar_t *sequence, const wchar_t *command); void input_mapping_add(const wchar_t *sequence, const wchar_t *command,
const wchar_t *mode = DEFAULT_BIND_MODE,
const wchar_t *new_mode = DEFAULT_BIND_MODE);
/** /**
Insert all mapping names into the specified wcstring_list_t Insert all mapping names into the specified wcstring_list_t
@ -112,12 +117,22 @@ void input_mapping_get_names(wcstring_list_t &lst);
/** /**
Erase binding for specified key sequence Erase binding for specified key sequence
*/ */
bool input_mapping_erase(const wchar_t *sequence); bool input_mapping_erase(const wchar_t *sequence, const wchar_t *mode = DEFAULT_BIND_MODE);
/** /**
Gets the command bound to the specified key sequence. Returns true if it exists, false if not. Gets the command bound to the specified key sequence. Returns true if it exists, false if not.
*/ */
bool input_mapping_get(const wcstring &sequence, wcstring &cmd); bool input_mapping_get(const wcstring &sequence, wcstring &cmd, wcstring &mode);
/**
Return the current bind mode
*/
const wchar_t *input_get_bind_mode();
/**
Set the current bind mode
*/
bool input_set_bind_mode(const wchar_t *bind_mode);
/** /**
Return the sequence for the terminfo variable of the specified name. Return the sequence for the terminfo variable of the specified name.

View File

@ -0,0 +1,56 @@
function nothing
end
function fish_vi_key_bindings -d "vi-like key bindings for fish"
bind --erase --all
#
# command (default) mode
#
bind \cd exit
bind : exit
bind h backward-char
bind l forward-char
bind \e\[C forward-char
bind \e\[D backward-char
bind -k right forward-char
bind -k left backward-char
bind \n execute
bind -m insert i nothing
bind -m insert a forward-char
bind \x24 end-of-line
bind \x5e beginning-of-line
bind \e\[H beginning-of-line
bind \e\[F end-of-line
bind k up-or-search
bind j down-or-search
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 b backward-word
bind B backward-word
bind w forward-word
bind W backward-word
bind y yank
bind p yank-pop
#
# insert mode
#
bind -M insert "" self-insert
bind -M insert \n execute
bind -M insert -k dc delete-char
bind -M insert -k backspace backward-delete-char
bind -M insert -m default \e nothing
bind -M insert \t complete
end