1 /* $OpenBSD: funmap.c,v 1.63 2021/04/22 19:50:55 lum Exp $ */ 2 3 /* This file is in the public domain */ 4 5 #include <sys/queue.h> 6 #include <signal.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 11 #include "def.h" 12 #include "funmap.h" 13 #include "kbd.h" 14 15 /* 16 * funmap structure: a list of functions and their command-names/#parameters. 17 * 18 * If the function is NULL, it must be listed with the same name in the 19 * map_table. 20 */ 21 struct funmap { 22 PF fn_funct; 23 const char *fn_name; 24 int fn_nparams; 25 struct funmap *fn_next; 26 }; 27 static struct funmap *funs; 28 29 /* 30 * 3rd column in the functnames structure indicates how many parameters the 31 * function takes in 'normal' usage. This column is only used to identify 32 * function profiles when lines of a buffer are being evaluated via excline(). 33 * 34 * 0 = a toggle, non-modifiable insert/delete, region modifier, etc 35 * 1 = value can be string or number value (like: file/buf name, search string) 36 * 2 = multiple type value required, see auto-execute, or global-set-key, etc 37 * -1 = error: interactive commmand, unsuitable for interpreter 38 * 39 * Some functions when used interactively may ask for a 'y' or 'n' (or another 40 * character) to continue, in excline, a 'y' is assumed. Functions like this 41 * have '0' in the 3rd column below. 42 */ 43 static struct funmap functnames[] = { 44 {apropos_command, "apropos", 1}, 45 {toggleaudiblebell, "audible-bell", 0}, 46 {auto_execute, "auto-execute", 2}, 47 {fillmode, "auto-fill-mode", 0}, 48 {indentmode, "auto-indent-mode", 0}, 49 {backtoindent, "back-to-indentation", 0}, 50 {backuptohomedir, "backup-to-home-directory", 0}, 51 {backchar, "backward-char", 1}, 52 {delbword, "backward-kill-word", 1}, 53 {gotobop, "backward-paragraph", 1}, 54 {backword, "backward-word", 1}, 55 {gotobob, "beginning-of-buffer", 0}, 56 {gotobol, "beginning-of-line", 0}, 57 {showmatch, "blink-and-insert", 1}, /* startup only */ 58 {bsmap, "bsmap-mode", 0}, 59 {NULL, "c-x 4 prefix", 0}, /* internal */ 60 {NULL, "c-x prefix", 0}, /* internal */ 61 {executemacro, "call-last-kbd-macro", 0}, 62 {capword, "capitalize-word", 1}, 63 {changedir, "cd", 1}, 64 {clearmark, "clear-mark", 0}, 65 {colnotoggle, "column-number-mode", 0}, 66 {copyregion, "copy-region-as-kill", 0}, 67 #ifdef REGEX 68 {cntmatchlines, "count-matches", 1}, 69 {cntnonmatchlines, "count-non-matches", 1}, 70 #endif /* REGEX */ 71 {cscreatelist, "cscope-create-list-of-files-to-index", 1}, 72 {csfuncalled, "cscope-find-called-functions", 1}, 73 {csegrep, "cscope-find-egrep-pattern", 1}, 74 {csfindinc, "cscope-find-files-including-file", 1}, 75 {cscallerfuncs, "cscope-find-functions-calling-this-function", 1}, 76 {csdefinition, "cscope-find-global-definition", 1}, 77 {csfindfile, "cscope-find-this-file", 1}, 78 {cssymbol, "cscope-find-this-symbol", 1}, 79 {csfindtext, "cscope-find-this-text-string", 1}, 80 {csnextfile, "cscope-next-file", 0}, 81 {csnextmatch, "cscope-next-symbol", 0}, 82 {csprevfile, "cscope-prev-file", 0}, 83 {csprevmatch, "cscope-prev-symbol", 0}, 84 {redefine_key, "define-key", 3}, 85 {backdel, "delete-backward-char", 1}, 86 {deblank, "delete-blank-lines", 0}, 87 {forwdel, "delete-char", 1}, 88 {delwhite, "delete-horizontal-space", 0}, 89 {delleadwhite, "delete-leading-space", 0}, 90 #ifdef REGEX 91 {delmatchlines, "delete-matching-lines", 1}, 92 {delnonmatchlines, "delete-non-matching-lines", 1}, 93 #endif /* REGEX */ 94 {onlywind, "delete-other-windows", 0}, 95 {deltrailwhite, "delete-trailing-space", 0}, 96 {delwind, "delete-window", 0}, 97 {wallchart, "describe-bindings", 0}, 98 {desckey, "describe-key-briefly", 1}, 99 {diffbuffer, "diff-buffer-with-file", 0}, 100 {digit_argument, "digit-argument", 1}, 101 {dired_jump, "dired-jump", 1}, 102 {lowerregion, "downcase-region", 0}, 103 {lowerword, "downcase-word", 1}, 104 {showversion, "emacs-version", 0}, 105 {finishmacro, "end-kbd-macro", 0}, 106 {gotoeob, "end-of-buffer", 0}, 107 {gotoeol, "end-of-line", 0}, 108 {enlargewind, "enlarge-window", 0}, 109 {NULL, "esc prefix", 0}, /* internal */ 110 {evalbuffer, "eval-current-buffer", 0}, 111 {evalexpr, "eval-expression", 0}, 112 {swapmark, "exchange-point-and-mark", 0}, 113 {extend, "execute-extended-command", 1}, 114 {fillpara, "fill-paragraph", 0}, 115 {filevisitalt, "find-alternate-file", 1}, 116 {filevisit, "find-file", 1}, 117 {poptofile, "find-file-other-window", 1}, 118 {filevisitro, "find-file-read-only", 1}, 119 {findtag, "find-tag", 1}, 120 {forwchar, "forward-char", 1}, 121 {gotoeop, "forward-paragraph", 1}, 122 {forwword, "forward-word", 1}, 123 {bindtokey, "global-set-key", 2}, 124 {unbindtokey, "global-unset-key", 1}, 125 {globalwdtoggle, "global-wd-mode", 0}, 126 {gotoline, "goto-line", 1}, 127 {help_help, "help-help", 0}, 128 {indent, "indent-current-line", 0}, 129 {insert, "insert", 1}, 130 {bufferinsert, "insert-buffer", 1}, 131 {fileinsert, "insert-file", 1}, 132 {fillword, "insert-with-wrap", 1}, /* startup only */ 133 {backisearch, "isearch-backward", 1}, 134 {forwisearch, "isearch-forward", 1}, 135 {joinline, "join-line", 0}, 136 {justone, "just-one-space", 0}, 137 {ctrlg, "keyboard-quit", 0}, 138 {killbuffer_cmd, "kill-buffer", 1}, 139 {killline, "kill-line", 1}, 140 {killpara, "kill-paragraph", 1}, 141 {killregion, "kill-region", 0}, 142 {delfword, "kill-word", 1}, 143 {toggleleavetmp, "leave-tmpdir-backups", 0}, 144 {linenotoggle, "line-number-mode", 0}, 145 {listbuffers, "list-buffers", 0}, 146 {evalfile, "load", 1}, 147 {localbind, "local-set-key", 1}, 148 {localunbind, "local-unset-key", 1}, 149 {makebkfile, "make-backup-files", 0}, 150 {makedir, "make-directory", 1}, 151 {markpara, "mark-paragraph", 1}, 152 {markbuffer, "mark-whole-buffer", 0}, 153 {do_meta, "meta-key-mode", 0}, /* better name, anyone? */ 154 {negative_argument, "negative-argument", 1}, 155 {enewline, "newline", 1}, 156 {lfindent, "newline-and-indent", 1}, 157 {forwline, "next-line", 1}, 158 #ifdef NOTAB 159 {notabmode, "no-tab-mode", 0}, 160 #endif /* NOTAB */ 161 {notmodified, "not-modified", 0}, 162 {openline, "open-line", 1}, 163 {nextwind, "other-window", 0}, 164 {overwrite_mode, "overwrite-mode", 0}, 165 {poptag, "pop-tag-mark", 0}, 166 {prefixregion, "prefix-region", 0}, 167 {backline, "previous-line", 1}, 168 {prevwind, "previous-window", 0}, 169 {spawncli, "push-shell", 0}, 170 {showcwdir, "pwd", 0}, 171 {queryrepl, "query-replace", -1}, 172 #ifdef REGEX 173 {re_queryrepl, "query-replace-regexp", -1}, 174 #endif /* REGEX */ 175 {quote, "quoted-insert", 1}, 176 #ifdef REGEX 177 {re_searchagain, "re-search-again", 0}, 178 {re_backsearch, "re-search-backward", 0}, 179 {re_forwsearch, "re-search-forward", 0}, 180 #endif /* REGEX */ 181 {reposition, "recenter", 0}, 182 {redraw, "redraw-display", 0}, 183 #ifdef REGEX 184 {re_repl, "replace-regexp", 2}, 185 {replstr, "replace-string", 2}, 186 #endif /* REGEX */ 187 {revertbuffer, "revert-buffer", 0}, 188 {filesave, "save-buffer", 1}, 189 {quit, "save-buffers-kill-emacs", 0}, 190 {savebuffers, "save-some-buffers", 0}, 191 {backpage, "scroll-down", 1}, 192 {back1page, "scroll-one-line-down", 1}, 193 {forw1page, "scroll-one-line-up", 1}, 194 {pagenext, "scroll-other-window", 1}, 195 {forwpage, "scroll-up", 1}, 196 {searchagain, "search-again", 0}, 197 {backsearch, "search-backward", 0}, 198 {forwsearch, "search-forward", 0}, 199 {ask_selfinsert, "self-insert-char", 1}, 200 {selfinsert, "self-insert-command", 1}, /* startup only */ 201 {sentencespace, "sentence-end-double-space", 0}, 202 #ifdef REGEX 203 {setcasefold, "set-case-fold-search", 0}, 204 #endif /* REGEX */ 205 {setcasereplace, "set-case-replace", 0}, 206 {set_default_mode, "set-default-mode", 1}, 207 {setfillcol, "set-fill-column", 1}, 208 {setmark, "set-mark-command", 0}, 209 {setprefix, "set-prefix-string", 1}, 210 {shellcommand, "shell-command", 1}, 211 {piperegion, "shell-command-on-region", 1}, 212 {shrinkwind, "shrink-window", 1}, 213 #ifdef NOTAB 214 {space_to_tabstop, "space-to-tabstop", 0}, 215 #endif /* NOTAB */ 216 {splitwind, "split-window-vertically", 0}, 217 {definemacro, "start-kbd-macro", 0}, 218 {spawncli, "suspend-emacs", 0}, 219 {usebuffer, "switch-to-buffer", 1}, 220 {poptobuffer, "switch-to-buffer-other-window", 1}, 221 {togglereadonly, "toggle-read-only", 0}, 222 {togglereadonlyall, "toggle-read-only-all", 0}, 223 {twiddle, "transpose-chars", 0}, 224 {transposepara, "transpose-paragraphs", 0}, 225 {transposeword, "transpose-words", 0}, 226 {undo, "undo", 0}, 227 {undo_add_boundary, "undo-boundary", 0}, 228 {undo_boundary_enable, "undo-boundary-toggle", 0}, 229 {undo_enable, "undo-enable", 0}, 230 {undo_dump, "undo-list", 0}, 231 {universal_argument, "universal-argument", 1}, 232 {upperregion, "upcase-region", 0}, 233 {upperword, "upcase-word", 1}, 234 {togglevisiblebell, "visible-bell", 0}, 235 {tagsvisit, "visit-tags-table", 0}, 236 {showcpos, "what-cursor-position", 0}, 237 {filewrite, "write-file", 1}, 238 {yank, "yank", 1}, 239 {NULL, NULL, 0} 240 }; 241 242 void 243 funmap_init(void) 244 { 245 struct funmap *fn; 246 247 for (fn = functnames; fn->fn_name != NULL; fn++) { 248 fn->fn_next = funs; 249 funs = fn; 250 } 251 } 252 253 int 254 funmap_add(PF fun, const char *fname, int fparams) 255 { 256 struct funmap *fn; 257 258 if ((fn = malloc(sizeof(*fn))) == NULL) 259 return (FALSE); 260 261 fn->fn_funct = fun; 262 fn->fn_name = fname; 263 fn->fn_nparams = fparams; 264 fn->fn_next = funs; 265 266 funs = fn; 267 return (TRUE); 268 } 269 270 /* 271 * Translate from function name to function pointer. 272 */ 273 PF 274 name_function(const char *fname) 275 { 276 struct funmap *fn; 277 278 for (fn = funs; fn != NULL; fn = fn->fn_next) { 279 if (strcmp(fn->fn_name, fname) == 0) 280 return (fn->fn_funct); 281 } 282 return (NULL); 283 } 284 285 const char * 286 function_name(PF fun) 287 { 288 struct funmap *fn; 289 290 for (fn = funs; fn != NULL; fn = fn->fn_next) { 291 if (fn->fn_funct == fun) 292 return (fn->fn_name); 293 } 294 return (NULL); 295 } 296 297 /* 298 * List possible function name completions. 299 */ 300 struct list * 301 complete_function_list(const char *fname) 302 { 303 struct funmap *fn; 304 struct list *head, *el; 305 int len; 306 307 len = strlen(fname); 308 head = NULL; 309 for (fn = funs; fn != NULL; fn = fn->fn_next) { 310 if (memcmp(fname, fn->fn_name, len) == 0) { 311 if ((el = malloc(sizeof(*el))) == NULL) { 312 free_file_list(head); 313 return (NULL); 314 } 315 el->l_name = strdup(fn->fn_name); 316 el->l_next = head; 317 head = el; 318 } 319 } 320 return (head); 321 } 322 323 /* 324 * Find number of parameters for function name. 325 */ 326 int 327 numparams_function(PF fun) 328 { 329 struct funmap *fn; 330 331 for (fn = funs; fn != NULL; fn = fn->fn_next) { 332 if (fn->fn_funct == fun) 333 return (fn->fn_nparams); 334 } 335 return (FALSE); 336 } 337