📄 bind.c
字号:
buffer = (char *)xmalloc ((int)finfo.st_size + 1); i = read (file, buffer, finfo.st_size); close (file); if (i != finfo.st_size) return (errno); /* Loop over the lines in the file. Lines that start with `#' are comments; all other lines are commands for readline initialization. */ line = buffer; end = buffer + finfo.st_size; while (line < end) { /* Find the end of this line. */ for (i = 0; line + i != end && line[i] != '\n'; i++); /* Mark end of line. */ line[i] = '\0'; /* Skip leading whitespace. */ while (*line && whitespace (*line)) { line++; i--; } /* If the line is not a comment, then parse it. */ if (*line && *line != '#') rl_parse_and_bind (line); /* Move to the next line. */ line += i + 1; } free (buffer); return (0);}/* **************************************************************** *//* *//* Parser Directives *//* *//* **************************************************************** *//* Conditionals. *//* Calling programs set this to have their argv[0]. */char *rl_readline_name = "other";/* Stack of previous values of parsing_conditionalized_out. */static unsigned char *if_stack = (unsigned char *)NULL;static int if_stack_depth = 0;static int if_stack_size = 0;/* Push _rl_parsing_conditionalized_out, and set parser state based on ARGS. */static intparser_if (args) char *args;{ register int i; /* Push parser state. */ if (if_stack_depth + 1 >= if_stack_size) { if (!if_stack) if_stack = (unsigned char *)xmalloc (if_stack_size = 20); else if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20); } if_stack[if_stack_depth++] = _rl_parsing_conditionalized_out; /* If parsing is turned off, then nothing can turn it back on except for finding the matching endif. In that case, return right now. */ if (_rl_parsing_conditionalized_out) return 0; /* Isolate first argument. */ for (i = 0; args[i] && !whitespace (args[i]); i++); if (args[i]) args[i++] = '\0'; /* Handle "if term=foo" and "if mode=emacs" constructs. If this isn't term=foo, or mode=emacs, then check to see if the first word in ARGS is the same as the value stored in rl_readline_name. */ if (rl_terminal_name && strnicmp (args, "term=", 5) == 0) { char *tem, *tname; /* Terminals like "aaa-60" are equivalent to "aaa". */ tname = savestring (rl_terminal_name); tem = strchr (tname, '-'); if (tem) *tem = '\0'; /* Test the `long' and `short' forms of the terminal name so that if someone has a `sun-cmd' and does not want to have bindings that will be executed if the terminal is a `sun', they can put `$if term=sun-cmd' into their .inputrc. */ if ((stricmp (args + 5, tname) == 0) || (stricmp (args + 5, rl_terminal_name) == 0)) _rl_parsing_conditionalized_out = 0; else _rl_parsing_conditionalized_out = 1; free (tname); }#if defined (VI_MODE) else if (strnicmp (args, "mode=", 5) == 0) { int mode; if (stricmp (args + 5, "emacs") == 0) mode = emacs_mode; else if (stricmp (args + 5, "vi") == 0) mode = vi_mode; else mode = no_mode; if (mode == rl_editing_mode) _rl_parsing_conditionalized_out = 0; else _rl_parsing_conditionalized_out = 1; }#endif /* VI_MODE */ /* Check to see if the first word in ARGS is the same as the value stored in rl_readline_name. */ else if (stricmp (args, rl_readline_name) == 0) _rl_parsing_conditionalized_out = 0; else _rl_parsing_conditionalized_out = 1; return 0;}/* Invert the current parser state if there is anything on the stack. */static intparser_else (args) char *args;{ register int i; if (!if_stack_depth) { /* Error message? */ return 0; } /* Check the previous (n - 1) levels of the stack to make sure that we haven't previously turned off parsing. */ for (i = 0; i < if_stack_depth - 1; i++) if (if_stack[i] == 1) return 0; /* Invert the state of parsing if at top level. */ _rl_parsing_conditionalized_out = !_rl_parsing_conditionalized_out; return 0;}/* Terminate a conditional, popping the value of _rl_parsing_conditionalized_out from the stack. */static intparser_endif (args) char *args;{ if (if_stack_depth) _rl_parsing_conditionalized_out = if_stack[--if_stack_depth]; else { /* *** What, no error message? *** */ } return 0;}/* Associate textual names with actual functions. */static struct { char *name; Function *function;} parser_directives [] = { { "if", parser_if }, { "endif", parser_endif }, { "else", parser_else }, { (char *)0x0, (Function *)0x0 }};/* Handle a parser directive. STATEMENT is the line of the directive without any leading `$'. */static inthandle_parser_directive (statement) char *statement;{ register int i; char *directive, *args; /* Isolate the actual directive. */ /* Skip whitespace. */ for (i = 0; whitespace (statement[i]); i++); directive = &statement[i]; for (; statement[i] && !whitespace (statement[i]); i++); if (statement[i]) statement[i++] = '\0'; for (; statement[i] && whitespace (statement[i]); i++); args = &statement[i]; /* Lookup the command, and act on it. */ for (i = 0; parser_directives[i].name; i++) if (stricmp (directive, parser_directives[i].name) == 0) { (*parser_directives[i].function) (args); return (0); } /* *** Should an error message be output? */ return (1);}static int substring_member_of_array ();/* Read the binding command from STRING and perform it. A key binding command looks like: Keyname: function-name\0, a variable binding command looks like: set variable value. A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */rl_parse_and_bind (string) char *string;{ char *funname, *kname; register int c, i; int key, equivalency; while (string && whitespace (*string)) string++; if (!string || !*string || *string == '#') return 0; /* If this is a parser directive, act on it. */ if (*string == '$') { handle_parser_directive (&string[1]); return 0; } /* If we aren't supposed to be parsing right now, then we're done. */ if (_rl_parsing_conditionalized_out) return 0; i = 0; /* If this keyname is a complex key expression surrounded by quotes, advance to after the matching close quote. This code allows the backslash to quote characters in the key expression. */ if (*string == '"') { int passc = 0; for (i = 1; c = string[i]; i++) { if (passc) { passc = 0; continue; } if (c == '\\') { passc++; continue; } if (c == '"') break; } } /* Advance to the colon (:) or whitespace which separates the two objects. */ for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ ); equivalency = (c == ':' && string[i + 1] == '='); /* Mark the end of the command (or keyname). */ if (string[i]) string[i++] = '\0'; /* If doing assignment, skip the '=' sign as well. */ if (equivalency) string[i++] = '\0'; /* If this is a command to set a variable, then do that. */ if (stricmp (string, "set") == 0) { char *var = string + i; char *value; /* Make VAR point to start of variable name. */ while (*var && whitespace (*var)) var++; /* Make value point to start of value string. */ value = var; while (*value && !whitespace (*value)) value++; if (*value) *value++ = '\0'; while (*value && whitespace (*value)) value++; rl_variable_bind (var, value); return 0; } /* Skip any whitespace between keyname and funname. */ for (; string[i] && whitespace (string[i]); i++); funname = &string[i]; /* Now isolate funname. For straight function names just look for whitespace, since that will signify the end of the string. But this could be a macro definition. In that case, the string is quoted, so skip to the matching delimiter. We allow the backslash to quote the delimiter characters in the macro body. */ /* This code exists to allow whitespace in macro expansions, which would otherwise be gobbled up by the next `for' loop.*/ /* XXX - it may be desirable to allow backslash quoting only if " is the quoted string delimiter, like the shell. */ if (*funname == '\'' || *funname == '"') { int delimiter = string[i++]; int passc = 0; for (; c = string[i]; i++) { if (passc) { passc = 0; continue; } if (c == '\\') { passc = 1; continue; } if (c == delimiter) break; } if (c) i++; } /* Advance to the end of the string. */ for (; string[i] && !whitespace (string[i]); i++); /* No extra whitespace at the end of the string. */ string[i] = '\0'; /* Handle equivalency bindings here. Make the left-hand side be exactly whatever the right-hand evaluates to, including keymaps. */ if (equivalency) { return 0; } /* If this is a new-style key-binding, then do the binding with rl_set_key (). Otherwise, let the older code deal with it. */ if (*string == '"') { char *seq = xmalloc (1 + strlen (string)); register int j, k = 0; int passc = 0; for (j = 1; string[j]; j++) { /* Allow backslash to quote characters, but leave them in place. This allows a string to end with a backslash quoting another backslash, or with a backslash quoting a double quote. The backslashes are left in place for rl_translate_keyseq (). */ if (passc || (string[j] == '\\')) { seq[k++] = string[j]; passc = !passc; continue; } if (string[j] == '"') break; seq[k++] = string[j]; } seq[k] = '\0'; /* Binding macro? */ if (*funname == '\'' || *funname == '"') { j = strlen (funname); /* Remove the delimiting quotes from each end of FUNNAME. */ if (j && funname[j - 1] == *funname) funname[j - 1] = '\0'; rl_macro_bind (seq, &funname[1], _rl_keymap); } else rl_set_key (seq, rl_named_function (funname), _rl_keymap); free (seq); return 0; } /* Get the actual character we want to deal with. */ kname = strrchr (string, '-'); if (!kname) kname = string; else kname++; key = glean_key_from_name (kname); /* Add in control and meta bits. */ if (substring_member_of_array (string, possible_control_prefixes)) key = CTRL (to_upper (key)); if (substring_member_of_array (string, possible_meta_prefixes)) key = META (key); /* Temporary. Handle old-style keyname with macro-binding. */ if (*funname == '\'' || *funname == '"') { char seq[2]; int fl = strlen (funname); seq[0] = key; seq[1] = '\0'; if (fl && funname[fl - 1] == *funname) funname[fl - 1] = '\0'; rl_macro_bind (seq, &funname[1], _rl_keymap); }#if defined (PREFIX_META_HACK) /* Ugly, but working hack to keep prefix-meta around. */ else if (stricmp (funname, "prefix-meta") == 0) { char seq[2]; seq[0] = key; seq[1] = '\0'; rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, _rl_keymap); }#endif /* PREFIX_META_HACK */ else rl_bind_key (key, rl_named_function (funname)); return 0;}/* Simple structure for boolean readline variables (i.e., those that can have one of two values; either "On" or 1 for truth, or "Off" or 0 for false. */static struct { char *name; int *value;} boolean_varlist [] = { { "horizontal-scroll-mode", &_rl_horizontal_scroll_mode }, { "mark-modified-lines", &_rl_mark_modified_lines }, { "meta-flag", &_rl_meta_flag },#if defined (PAREN_MATCHING) { "blink-matching-paren", &rl_blink_matching_paren },#endif { "convert-meta", &_rl_convert_meta_chars_to_ascii }, { "show-all-if-ambiguous", &_rl_complete_show_all }, { "output-meta", &_rl_output_meta_chars },#if defined (VISIBLE_STATS) { "visible-stats", &rl_visible_stats },#endif /* VISIBLE_STATS */ { "expand-tilde", &rl_complete_with_tilde_expansion }, { (char *)NULL, (int *)NULL }};rl_variable_bind (name, value) char *name, *value;{ register int i; /* Check for simple variables first. */ for (i = 0; boolean_varlist[i].name; i++) { if (stricmp (name, boolean_varlist[i].name) == 0) { /* A variable is TRUE if the "value" is "on", "1" or "". */ if ((!*value) || (stricmp (value, "On") == 0) || (value[0] == '1' && value[1] == '\0')) *boolean_varlist[i].value = 1; else *boolean_varlist[i].value = 0; return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -