Logo Search packages:      
Sourcecode: yash version File versions  Download package

keymap.c

/* Yash: yet another shell */
/* keymap.c: mappings from keys to functions */
/* (C) 2007-2010 magicant */

/* This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.  */


#include "../common.h"
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "../builtin.h"
#include "../exec.h"
#include "../expand.h"
#include "../util.h"
#include "../xfnmatch.h"
#include "complete.h"
#include "editing.h"
#include "key.h"
#include "keymap.h"
#include "trie.h"


/* Definition of editing modes. */
le_mode_T le_modes[LE_MODE_N];

/* The current editing mode.
 * Points to one of the modes in `le_modes'. */
le_mode_T *le_current_mode;

/* Array of pairs of a command name and function.
 * Sorted by name. */
00046 static const struct command_name_pair {
    const char *name;
    le_command_func_T *command;
} commands[] = {
#include "commands.in"
};


/* Initializes `le_modes' if not yet initialized.
 * May be called more than once but does nothing if so. */
void le_keymap_init(void)
{
    static bool initialized = false;
    if (initialized)
      return;
    initialized = true;

    trie_T *t;

#define Set(key, cmd) \
    (t = trie_setw(t, key, (trievalue_T) { .cmdfunc = (cmd) }))

    le_modes[LE_MODE_VI_INSERT].default_command = cmd_self_insert;
    t = trie_create();
    Set(Key_backslash, cmd_self_insert);
    Set(Key_c_v,       cmd_expect_verbatim);
    Set(Key_right,     cmd_forward_char);
    Set(Key_left,      cmd_backward_char);
    Set(Key_home,      cmd_beginning_of_line);
    Set(Key_end,       cmd_end_of_line);
    Set(Key_c_j,       cmd_accept_line);
    Set(Key_c_m,       cmd_accept_line);
    Set(Key_interrupt, cmd_abort_line);
    Set(Key_c_c,       cmd_abort_line);
    Set(Key_eof,       cmd_eof_if_empty);
    Set(Key_c_d,       cmd_eof_if_empty);
    Set(Key_escape,    cmd_setmode_vicommand);
    Set(Key_c_l,       cmd_redraw_all);
    Set(Key_delete,    cmd_delete_char);
    Set(Key_backspace, cmd_backward_delete_char);
    Set(Key_erase,     cmd_backward_delete_char);
    Set(Key_c_h,       cmd_backward_delete_char);
    Set(Key_c_w,       cmd_backward_delete_semiword);
    Set(Key_kill,      cmd_backward_delete_line);
    Set(Key_c_u,       cmd_backward_delete_line);
    Set(Key_tab,       cmd_complete_next_candidate);
    Set(Key_btab,      cmd_complete_prev_candidate);
    Set(Key_down,      cmd_next_history_eol);
    Set(Key_c_n,       cmd_next_history_eol);
    Set(Key_up,        cmd_prev_history_eol);
    Set(Key_c_p,       cmd_prev_history_eol);
    le_modes[LE_MODE_VI_INSERT].keymap = t;

    le_modes[LE_MODE_VI_COMMAND].default_command = cmd_alert;
    t = trie_create();
    Set(Key_escape,    cmd_noop);
    Set(L"1",          cmd_digit_argument);
    Set(L"2",          cmd_digit_argument);
    Set(L"3",          cmd_digit_argument);
    Set(L"4",          cmd_digit_argument);
    Set(L"5",          cmd_digit_argument);
    Set(L"6",          cmd_digit_argument);
    Set(L"7",          cmd_digit_argument);
    Set(L"8",          cmd_digit_argument);
    Set(L"9",          cmd_digit_argument);
    Set(L"0",          cmd_bol_or_digit);
    Set(Key_c_j,       cmd_accept_line);
    Set(Key_c_m,       cmd_accept_line);
    Set(Key_interrupt, cmd_abort_line);
    Set(Key_c_c,       cmd_abort_line);
    Set(Key_eof,       cmd_eof_if_empty);
    Set(Key_c_d,       cmd_eof_if_empty);
    Set(L"#",          cmd_accept_with_hash);
    Set(L"i",          cmd_setmode_viinsert);
    Set(Key_insert,    cmd_setmode_viinsert);
    Set(Key_c_l,       cmd_redraw_all);
    Set(L"l",          cmd_forward_char);
    Set(L" ",          cmd_forward_char);
    Set(Key_right,     cmd_forward_char);
    Set(L"h",          cmd_backward_char);
    Set(Key_left,      cmd_backward_char);
    Set(Key_backspace, cmd_backward_char);
    Set(Key_erase,     cmd_backward_char);
    Set(Key_c_h,       cmd_backward_char);
    Set(L"W",          cmd_forward_bigword);
    Set(L"E",          cmd_end_of_bigword);
    Set(L"B",          cmd_backward_bigword);
    Set(L"w",          cmd_forward_viword);
    Set(L"e",          cmd_end_of_viword);
    Set(L"b",          cmd_backward_viword);
    Set(Key_home,      cmd_beginning_of_line);
    Set(L"$",          cmd_end_of_line);
    Set(Key_end,       cmd_end_of_line);
    Set(L"^",          cmd_first_nonblank);
    Set(L"f",          cmd_find_char);
    Set(L"F",          cmd_find_char_rev);
    Set(L"t",          cmd_till_char);
    Set(L"T",          cmd_till_char_rev);
    Set(L";",          cmd_refind_char);
    Set(L",",          cmd_refind_char_rev);
    Set(L"x",          cmd_kill_char);
    Set(Key_delete,    cmd_kill_char);
    Set(L"X",          cmd_backward_kill_char);
    Set(L"P",          cmd_put_before);
    Set(L"p",          cmd_put);
    Set(L"u",          cmd_undo);
    Set(L"U",          cmd_undo_all);
    Set(Key_c_r,       cmd_cancel_undo);
    Set(L".",          cmd_redo);
    Set(L"|",          cmd_go_to_column);
    Set(L"r",          cmd_vi_replace_char);
    Set(L"I",          cmd_vi_insert_beginning);
    Set(L"a",          cmd_vi_append);
    Set(L"A",          cmd_vi_append_to_eol);
    Set(L"R",          cmd_vi_replace);
    Set(L"~",          cmd_vi_switch_case_char);
    Set(L"y",          cmd_vi_yank);
    Set(L"Y",          cmd_vi_yank_to_eol);
    Set(L"d",          cmd_vi_delete);
    Set(L"D",          cmd_vi_delete_to_eol);
    Set(L"c",          cmd_vi_change);
    Set(L"C",          cmd_vi_change_to_eol);
    Set(L"S",          cmd_vi_change_line);
    Set(L"s",          cmd_vi_substitute);
    Set(L"_",          cmd_vi_append_last_bigword);
    Set(L"@",          cmd_vi_exec_alias);
    Set(L"v",          cmd_vi_edit_and_accept);
    Set(L"=",          cmd_vi_complete_list);
    Set(L"*",          cmd_vi_complete_all);
    Set(Key_backslash, cmd_vi_complete_max);
    Set(L"?",          cmd_vi_search_forward);
    Set(L"/",          cmd_vi_search_backward);
    Set(L"n",          cmd_search_again);
    Set(L"N",          cmd_search_again_rev);
    Set(L"G",          cmd_oldest_history_bol);
    Set(L"g",          cmd_return_history_bol);
    Set(L"j",          cmd_next_history_bol);
    Set(L"+",          cmd_next_history_bol);
    Set(Key_down,      cmd_next_history_bol);
    Set(Key_c_n,       cmd_next_history_bol);
    Set(L"k",          cmd_prev_history_bol);
    Set(L"-",          cmd_prev_history_bol);
    Set(Key_up,        cmd_prev_history_bol);
    Set(Key_c_p,       cmd_prev_history_bol);
    le_modes[LE_MODE_VI_COMMAND].keymap = t;

    le_modes[LE_MODE_VI_SEARCH].default_command = cmd_srch_self_insert;
    t = trie_create();
    Set(Key_c_v,       cmd_expect_verbatim);
    Set(Key_interrupt, cmd_abort_line);
    Set(Key_c_c,       cmd_abort_line);
    Set(Key_c_l,       cmd_redraw_all);
    Set(Key_backslash, cmd_srch_self_insert);
    Set(Key_backspace, cmd_srch_backward_delete_char);
    Set(Key_erase,     cmd_srch_backward_delete_char);
    Set(Key_c_h,       cmd_srch_backward_delete_char);
    Set(Key_kill,      cmd_srch_backward_delete_line);
    Set(Key_c_u,       cmd_srch_backward_delete_line);
    Set(Key_c_j,       cmd_srch_accept_search);
    Set(Key_c_m,       cmd_srch_accept_search);
    Set(Key_escape,    cmd_srch_abort_search);
    le_modes[LE_MODE_VI_SEARCH].keymap = t;

    le_modes[LE_MODE_EMACS].default_command = cmd_self_insert;
    t = trie_create();
    Set(Key_backslash,      cmd_self_insert);
    Set(Key_escape Key_c_i, cmd_insert_tab);
    Set(Key_c_q,            cmd_expect_verbatim);
    Set(Key_c_v,            cmd_expect_verbatim);
    Set(Key_escape "0",     cmd_digit_argument);
    Set(Key_escape "1",     cmd_digit_argument);
    Set(Key_escape "2",     cmd_digit_argument);
    Set(Key_escape "3",     cmd_digit_argument);
    Set(Key_escape "4",     cmd_digit_argument);
    Set(Key_escape "5",     cmd_digit_argument);
    Set(Key_escape "6",     cmd_digit_argument);
    Set(Key_escape "7",     cmd_digit_argument);
    Set(Key_escape "8",     cmd_digit_argument);
    Set(Key_escape "9",     cmd_digit_argument);
    Set(Key_escape "-",     cmd_digit_argument);
    Set(Key_c_j,            cmd_accept_line);
    Set(Key_c_m,            cmd_accept_line);
    Set(Key_interrupt,      cmd_abort_line);
    Set(Key_c_c,            cmd_abort_line);
    Set(Key_eof,            cmd_eof_or_delete);
    Set(Key_c_d,            cmd_eof_or_delete);
    Set(Key_escape "#",     cmd_accept_with_hash);
    Set(Key_c_l,            cmd_redraw_all);
    Set(Key_right,          cmd_forward_char);
    Set(Key_c_f,            cmd_forward_char);
    Set(Key_left,           cmd_backward_char);
    Set(Key_c_b,            cmd_backward_char);
    Set(Key_escape "f",     cmd_forward_emacsword);
    Set(Key_escape "F",     cmd_forward_emacsword);
    Set(Key_escape "b",     cmd_backward_emacsword);
    Set(Key_escape "B",     cmd_backward_emacsword);
    Set(Key_home,           cmd_beginning_of_line);
    Set(Key_c_a,            cmd_beginning_of_line);
    Set(Key_end,            cmd_end_of_line);
    Set(Key_c_e,            cmd_end_of_line);
    Set(Key_c_rb,           cmd_find_char);
    Set(Key_escape Key_c_rb, cmd_find_char_rev);
    Set(Key_delete,         cmd_delete_char);
    Set(Key_backspace,      cmd_backward_delete_char);
    Set(Key_erase,          cmd_backward_delete_char);
    Set(Key_c_h,            cmd_backward_delete_char);
    Set(Key_escape "d",     cmd_kill_emacsword);
    Set(Key_escape "D",     cmd_kill_emacsword);
    Set(Key_escape Key_backspace, cmd_backward_kill_emacsword);
    Set(Key_escape Key_erase, cmd_backward_kill_emacsword);
    Set(Key_escape Key_c_h, cmd_backward_kill_emacsword);
    Set(Key_c_k,            cmd_forward_kill_line);
    Set(Key_kill,           cmd_backward_kill_line);
    Set(Key_c_u,            cmd_backward_kill_line);
    Set(Key_c_x Key_backspace, cmd_backward_kill_line);
    Set(Key_c_x Key_erase,  cmd_backward_kill_line);
    Set(Key_c_y,            cmd_put_left);
    Set(Key_escape "y",     cmd_put_pop);
    Set(Key_escape "Y",     cmd_put_pop);
    Set(Key_c_w,            cmd_backward_kill_bigword);
    Set(Key_c_ul,           cmd_undo);
    Set(Key_c_x Key_c_u,    cmd_undo);
    Set(Key_c_x Key_kill,   cmd_undo);
    Set(Key_escape Key_c_r, cmd_undo_all);
    Set(Key_escape "r",     cmd_undo_all);
    Set(Key_escape "R",     cmd_undo_all);
    Set(Key_tab,            cmd_complete_next_candidate);
    Set(Key_btab,           cmd_complete_prev_candidate);
    Set(Key_escape "=",     cmd_complete_list);
    Set(Key_escape "?",     cmd_complete_list);
    Set(Key_escape "*",     cmd_complete_all);
    Set(Key_c_t,            cmd_emacs_transpose_chars);
    Set(Key_escape "t",     cmd_emacs_transpose_words);
    Set(Key_escape "T",     cmd_emacs_transpose_words);
    Set(Key_escape "l",     cmd_emacs_downcase_word);
    Set(Key_escape "L",     cmd_emacs_downcase_word);
    Set(Key_escape "u",     cmd_emacs_upcase_word);
    Set(Key_escape "U",     cmd_emacs_upcase_word);
    Set(Key_escape "c",     cmd_emacs_capitalize_word);
    Set(Key_escape "C",     cmd_emacs_capitalize_word);
    Set(Key_escape Key_backslash, cmd_emacs_delete_horizontal_space);
    Set(Key_escape " ",     cmd_emacs_just_one_space);
    Set(Key_c_s,            cmd_emacs_search_forward);
    Set(Key_c_r,            cmd_emacs_search_backward);
    Set(Key_escape "<",     cmd_oldest_history_eol);
    Set(Key_escape ">",     cmd_return_history_eol);
    Set(Key_down,           cmd_next_history_eol);
    Set(Key_c_n,            cmd_next_history_eol);
    Set(Key_up,             cmd_prev_history_eol);
    Set(Key_c_p,            cmd_prev_history_eol);
    le_modes[LE_MODE_EMACS].keymap = t;

    le_modes[LE_MODE_EMACS_SEARCH].default_command = cmd_srch_self_insert;
    t = trie_create();
    Set(Key_c_v,       cmd_expect_verbatim);
    Set(Key_c_m,       cmd_accept_line);
    Set(Key_interrupt, cmd_abort_line);
    Set(Key_c_c,       cmd_abort_line);
    Set(Key_c_l,       cmd_redraw_all);
    Set(Key_backslash, cmd_srch_self_insert);
    Set(Key_backspace, cmd_srch_backward_delete_char);
    Set(Key_erase,     cmd_srch_backward_delete_char);
    Set(Key_c_h,       cmd_srch_backward_delete_char);
    Set(Key_kill,      cmd_srch_backward_delete_line);
    Set(Key_c_u,       cmd_srch_backward_delete_line);
    Set(Key_c_s,       cmd_srch_continue_forward);
    Set(Key_c_r,       cmd_srch_continue_backward);
    Set(Key_c_j,       cmd_srch_accept_search);
    Set(Key_escape,    cmd_srch_accept_search);
    Set(Key_c_g,       cmd_srch_abort_search);
    le_modes[LE_MODE_EMACS_SEARCH].keymap = t;

    le_modes[LE_MODE_CHAR_EXPECT].default_command = cmd_expect_char;
    t = trie_create();
    Set(Key_c_v,       cmd_expect_verbatim);
    Set(Key_interrupt, cmd_abort_line);
    Set(Key_c_c,       cmd_abort_line);
    Set(Key_backslash, cmd_expect_char);
    Set(Key_escape,    cmd_abort_expect_char);
    le_modes[LE_MODE_CHAR_EXPECT].keymap = t;

#undef Set
}

/* Sets the editing mode to the one specified by `id'. */
void le_set_mode(le_mode_id_T id)
{
    assert(id < LE_MODE_N);
    le_current_mode = le_id_to_mode(id);
}

/* Generates completion candidates for editing command names matching the
 * pattern. */
/* The prototype of this function is declared in "complete.h". */
void generate_bindkey_candidates(const le_compopt_T *compopt)
{
    if (!(compopt->type & CGT_BINDKEY))
      return;

    le_compdebug("adding lineedit command name candidates");
    if (!le_compile_cpatterns(compopt))
      return;

    for (size_t i = 0; i < sizeof commands / sizeof *commands; i++)
      if (le_match_comppatterns(compopt, commands[i].name))
          le_new_candidate(CT_BINDKEY,
                malloc_mbstowcs(commands[i].name), NULL, compopt);
}


/********** Builtin **********/

static int print_all_commands(void);
static int set_key_binding(
      le_mode_id_T mode, const wchar_t *keyseq, const wchar_t *commandname)
    __attribute__((nonnull));
static le_command_func_T *get_command_from_name(const char *name)
    __attribute__((nonnull,pure));
static int command_name_compare(const void *p1, const void *p2)
    __attribute__((nonnull,pure));
static int print_binding(le_mode_id_T mode, const wchar_t *keyseq)
    __attribute__((nonnull));
static int print_binding_main(
      void *mode, const wchar_t *keyseq, le_command_func_T *cmd)
    __attribute__((nonnull));
static const char *get_command_name(le_command_func_T *command)
    __attribute__((nonnull,const));

/* The "bindkey" builtin, which accepts the following options:
 *  -v: select the "vi-insert" mode
 *  -a: select the "vi-command" mode
 *  -e: select the "emacs" mode
 *  -l: list names of available commands */
int bindkey_builtin(int argc, void **argv)
{
    static const struct xoption long_options[] = {
      { L"vi-insert",  OPTARG_NONE, L'v', },
      { L"vi-command", OPTARG_NONE, L'a', },
      { L"emacs",      OPTARG_NONE, L'e', },
      { L"list",       OPTARG_NONE, L'l', },
#if YASH_ENABLE_HELP
      { L"help",       OPTARG_NONE, L'-', },
#endif
      { NULL, 0, 0, },
    };

    wchar_t opt;
    bool list = false;
    le_mode_id_T mode = LE_MODE_N;

    xoptind = 0, xopterr = true;
    while ((opt = xgetopt_long(argv, L"aelv", long_options, NULL))) {
      switch (opt) {
          case L'a':  mode = LE_MODE_VI_COMMAND;  break;
          case L'e':  mode = LE_MODE_EMACS;       break;
          case L'v':  mode = LE_MODE_VI_INSERT;   break;
          case L'l':  list = true;                break;
#if YASH_ENABLE_HELP
          case L'-':
            return print_builtin_help(ARGV(0));
#endif
          default:  print_usage:
            fprintf(stderr,
                  gt("Usage:  bindkey -aev [keyseq [command]]\n"
                     "        bindkey -l\n"));
            return Exit_ERROR;
      }
    }

    le_keymap_init();

    if (list) {
      if (mode != LE_MODE_N) {
          xerror(0, Ngt("invalid combination of options"));
          goto print_usage;
      }
      return print_all_commands();
    }

    if (mode == LE_MODE_N) {
      xerror(0, Ngt("option not specified"));
      goto print_usage;
    }

    if (xoptind == argc) {
      /* print all key bindings */
      le_mode_T *m = le_id_to_mode(mode);
      return trie_foreachw(m->keymap, print_binding_main, m);
    } else if (xoptind + 1 == argc) {
      return print_binding(mode, ARGV(xoptind));
    } else if (xoptind + 2 == argc) {
      return set_key_binding(mode, ARGV(xoptind), ARGV(xoptind + 1));
    } else {
      goto print_usage;
    }
}

/* Prints all available commands to the standard output. */
int print_all_commands(void)
{
    for (size_t i = 0; i < sizeof commands / sizeof *commands; i++) {
      if (puts(commands[i].name) == EOF) {
          xerror(errno, Ngt("cannot print to standard output"));
          return Exit_FAILURE;
      }
    }
    return Exit_SUCCESS;
}

/* Binds the specified key sequence to the specified command.
 * If `commandname' is L"-", the binding is removed.
 * If the specified command is not found, it is an error. */
int set_key_binding(
      le_mode_id_T mode, const wchar_t *keyseq, const wchar_t *commandname)
{
    if (keyseq[0] == L'\0') {
      xerror(0, Ngt("cannot bind empty sequence"));
      return Exit_FAILURE;
    }

    if (wcscmp(commandname, L"-") == 0) {
      /* delete key binding */
      register trie_T *t = le_modes[mode].keymap;
      t = trie_removew(t, keyseq);
      le_modes[mode].keymap = t;
    } else {
      /* set key binding */
      char *mbsname = malloc_wcstombs(commandname);
      if (mbsname == NULL) {
          xerror(EILSEQ, Ngt("unexpected error"));
          return Exit_FAILURE;
      }

      le_command_func_T *cmd = get_command_from_name(mbsname);
      free(mbsname);
      if (cmd) {
          register trie_T *t = le_modes[mode].keymap;
          t = trie_setw(t, keyseq, (trievalue_T) { .cmdfunc = cmd });
          le_modes[mode].keymap = t;
      } else {
          xerror(0, Ngt("%ls: no such command"), commandname);
          return Exit_FAILURE;
      }
    }
    return Exit_SUCCESS;
}

/* Returns the command function of the specified name.
 * Returns a null pointer if no such command is found. */
le_command_func_T *get_command_from_name(const char *name)
{
    struct command_name_pair *cnp = bsearch(name, commands,
          sizeof commands / sizeof *commands,
          sizeof *commands,
          command_name_compare);

    return cnp ? cnp->command : 0;
}

int command_name_compare(const void *p1, const void *p2)
{
    return strcmp((const char *) p1,
          ((const struct command_name_pair *) p2)->name);
}

/* Prints the binding for the given key sequence. */
int print_binding(le_mode_id_T mode, const wchar_t *keyseq)
{
    trieget_T tg = trie_getw(le_modes[mode].keymap, keyseq);

    if ((tg.type & TG_EXACTMATCH) && tg.matchlength == wcslen(keyseq)) {
      return print_binding_main(
            le_id_to_mode(mode), keyseq, tg.value.cmdfunc);
    } else {
      xerror(0, Ngt("%ls: unbound sequence"), keyseq);
      return Exit_FAILURE;
    }
}

/* Prints a command to restore the specified key binding.
 * `mode' must be a pointer to one of the modes in `le_modes'. */
int print_binding_main(
      void *mode, const wchar_t *keyseq, le_command_func_T *cmd)
{
    const char *format;
    char modechar;
    wchar_t *keyseqquote;
    const char *commandname;
    int r;

    switch (le_mode_to_id(mode)) {
      case LE_MODE_VI_INSERT:     modechar = 'v';  break;
      case LE_MODE_VI_COMMAND:    modechar = 'a';  break;
      case LE_MODE_VI_SEARCH:     modechar = 'V';  break;
      case LE_MODE_EMACS:         modechar = 'e';  break;
      case LE_MODE_EMACS_SEARCH:  modechar = 'E';  break;
      case LE_MODE_CHAR_EXPECT:   modechar = 'c';  break;
      default:                    assert(false);
    }
    if (keyseq[0] == L'-')
      format = "bindkey -%c -- %ls %s\n";
    else
      format = "bindkey -%c %ls %s\n";
    keyseqquote = quote_sq(keyseq);
    commandname = get_command_name(cmd);
    r = printf(format, modechar, keyseqquote, commandname);
    if (r < 0)
      xerror(errno, Ngt("cannot print to standard output"));
    free(keyseqquote);
    return r >= 0 ? Exit_SUCCESS : Exit_FAILURE;
}

/* Returns the name of the specified command. */
const char *get_command_name(le_command_func_T *command)
{
    for (size_t i = 0; i < sizeof commands / sizeof *commands; i++)
      if (commands[i].command == command)
          return commands[i].name;
    return NULL;
}

#if YASH_ENABLE_HELP
const char bindkey_help[] = Ngt(
"bindkey - set or print key bindings for line-editing\n"
"\tbindkey -aev [keyseq [command]]\n"
"\tbindkey -l\n"
"The first form, without <keyseq> or <command>, prints all the current key\n"
"bindings. With <keyseq> without <command>, prints the binding for <keyseq>.\n"
"With <keyseq> and <command>, binds <keyseq> to <command>. If <command> is\n"
"a hyphen ('-'), <keyseq> is unbound.\n"
"The second form, with the -l (--list) option, prints all available commands.\n"
"\n"
"One of the following options must be given in the first form:\n"
" -v --vi-insert\n"
"\tSpecifies the \"vi insert\" mode.\n"
" -a --vi-command\n"
"\tSpecifies the \"vi command\" mode.\n"
" -e --emacs\n"
"\tSpecifies the \"emacs\" mode.\n"
);
#endif


/* vim: set ts=8 sts=4 sw=4 noet tw=80: */

Generated by  Doxygen 1.6.0   Back to index