1 /* $OpenBSD: funmap.c,v 1.59 2019/07/11 18:20:18 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 = variable length # parameters (unused at moment) 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", 0}, 52 {delbword, "backward-kill-word", 0}, 53 {gotobop, "backward-paragraph", 0}, 54 {backword, "backward-word", 0}, 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", 0}, 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", 0}, 86 {deblank, "delete-blank-lines", 0}, 87 {forwdel, "delete-char", 0}, 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 {lowerregion, "downcase-region", 0}, 102 {lowerword, "downcase-word", 0}, 103 {showversion, "emacs-version", 0}, 104 {finishmacro, "end-kbd-macro", 0}, 105 {gotoeob, "end-of-buffer", 0}, 106 {gotoeol, "end-of-line", 0}, 107 {enlargewind, "enlarge-window", 0}, 108 {NULL, "esc prefix", 0}, /* internal */ 109 {evalbuffer, "eval-current-buffer", 0}, 110 {evalexpr, "eval-expression", 0}, 111 {swapmark, "exchange-point-and-mark", 0}, 112 {extend, "execute-extended-command", 1}, 113 {fillpara, "fill-paragraph", 0}, 114 {filevisitalt, "find-alternate-file", 1}, 115 {filevisit, "find-file", 1}, 116 {poptofile, "find-file-other-window", 1}, 117 {filevisitro, "find-file-read-only", 1}, 118 {findtag, "find-tag", 1}, 119 {forwchar, "forward-char", 0}, 120 {gotoeop, "forward-paragraph", 0}, 121 {forwword, "forward-word", 0}, 122 {bindtokey, "global-set-key", 2}, 123 {unbindtokey, "global-unset-key", 1}, 124 {globalwdtoggle, "global-wd-mode", 0}, 125 {gotoline, "goto-line", 1}, 126 {help_help, "help-help", 0}, 127 {indent, "indent-current-line", 0}, 128 {insert, "insert", 1}, 129 {bufferinsert, "insert-buffer", 1}, 130 {fileinsert, "insert-file", 1}, 131 {fillword, "insert-with-wrap", 1}, /* startup only */ 132 {backisearch, "isearch-backward", 1}, 133 {forwisearch, "isearch-forward", 1}, 134 {joinline, "join-line", 0}, 135 {justone, "just-one-space", 0}, 136 {ctrlg, "keyboard-quit", 0}, 137 {killbuffer_cmd, "kill-buffer", 1}, 138 {killline, "kill-line", 0}, 139 {killpara, "kill-paragraph", 0}, 140 {killregion, "kill-region", 0}, 141 {delfword, "kill-word", 0}, 142 {toggleleavetmp, "leave-tmpdir-backups", 0}, 143 {linenotoggle, "line-number-mode", 0}, 144 {listbuffers, "list-buffers", 0}, 145 {evalfile, "load", 1}, 146 {localbind, "local-set-key", 1}, 147 {localunbind, "local-unset-key", 1}, 148 {makebkfile, "make-backup-files", 0}, 149 {makedir, "make-directory", 1}, 150 {markpara, "mark-paragraph", 0}, 151 {markbuffer, "mark-whole-buffer", 0}, 152 {do_meta, "meta-key-mode", 0}, /* better name, anyone? */ 153 {negative_argument, "negative-argument", 1}, 154 {enewline, "newline", 0}, 155 {lfindent, "newline-and-indent", 0}, 156 {forwline, "next-line", 0}, 157 #ifdef NOTAB 158 {notabmode, "no-tab-mode", 0}, 159 #endif /* NOTAB */ 160 {notmodified, "not-modified", 0}, 161 {openline, "open-line", 0}, 162 {nextwind, "other-window", 0}, 163 {overwrite_mode, "overwrite-mode", 0}, 164 {poptag, "pop-tag-mark", 0}, 165 {prefixregion, "prefix-region", 0}, 166 {backline, "previous-line", 0}, 167 {prevwind, "previous-window", 0}, 168 {spawncli, "push-shell", 0}, 169 {showcwdir, "pwd", 0}, 170 {queryrepl, "query-replace", 1}, 171 #ifdef REGEX 172 {re_queryrepl, "query-replace-regexp", 1}, 173 #endif /* REGEX */ 174 {quote, "quoted-insert", 1}, 175 #ifdef REGEX 176 {re_searchagain, "re-search-again", 0}, 177 {re_backsearch, "re-search-backward", 0}, 178 {re_forwsearch, "re-search-forward", 0}, 179 #endif /* REGEX */ 180 {reposition, "recenter", 0}, 181 {redraw, "redraw-display", 0}, 182 #ifdef REGEX 183 {replstr, "replace-string", 2}, 184 #endif /* REGEX */ 185 {revertbuffer, "revert-buffer", 0}, 186 {filesave, "save-buffer", 0}, 187 {quit, "save-buffers-kill-emacs", 0}, 188 {savebuffers, "save-some-buffers", 0}, 189 {backpage, "scroll-down", 0}, 190 {back1page, "scroll-one-line-down", 0}, 191 {forw1page, "scroll-one-line-up", 0}, 192 {pagenext, "scroll-other-window", 0}, 193 {forwpage, "scroll-up", 0}, 194 {searchagain, "search-again", 0}, 195 {backsearch, "search-backward", 0}, 196 {forwsearch, "search-forward", 0}, 197 {ask_selfinsert, "self-insert-char", 1}, 198 {selfinsert, "self-insert-command", 1}, /* startup only */ 199 {sentencespace, "sentence-end-double-space", 0}, 200 #ifdef REGEX 201 {setcasefold, "set-case-fold-search", 0}, 202 #endif /* REGEX */ 203 {setcasereplace, "set-case-replace", 0}, 204 {set_default_mode, "set-default-mode", 1}, 205 {setfillcol, "set-fill-column", 1}, 206 {setmark, "set-mark-command", 0}, 207 {setprefix, "set-prefix-string", 1}, 208 {shellcommand, "shell-command", 1}, 209 {piperegion, "shell-command-on-region", 0}, 210 {shrinkwind, "shrink-window", 0}, 211 #ifdef NOTAB 212 {space_to_tabstop, "space-to-tabstop", 0}, 213 #endif /* NOTAB */ 214 {splitwind, "split-window-vertically", 0}, 215 {definemacro, "start-kbd-macro", 0}, 216 {spawncli, "suspend-emacs", 0}, 217 {usebuffer, "switch-to-buffer", 1}, 218 {poptobuffer, "switch-to-buffer-other-window", 1}, 219 {togglereadonly, "toggle-read-only", 0}, 220 {togglereadonlyall, "toggle-read-only-all", 0}, 221 {twiddle, "transpose-chars", 0}, 222 {transposepara, "transpose-paragraphs", 0}, 223 {transposeword, "transpose-words", 0}, 224 {undo, "undo", 0}, 225 {undo_add_boundary, "undo-boundary", 0}, 226 {undo_boundary_enable, "undo-boundary-toggle", 0}, 227 {undo_enable, "undo-enable", 0}, 228 {undo_dump, "undo-list", 0}, 229 {universal_argument, "universal-argument", 1}, 230 {upperregion, "upcase-region", 0}, 231 {upperword, "upcase-word", 0}, 232 {togglevisiblebell, "visible-bell", 0}, 233 {tagsvisit, "visit-tags-table", 0}, 234 {showcpos, "what-cursor-position", 0}, 235 {filewrite, "write-file", 1}, 236 {yank, "yank", 0}, 237 {NULL, NULL, 0} 238 }; 239 240 void 241 funmap_init(void) 242 { 243 struct funmap *fn; 244 245 for (fn = functnames; fn->fn_name != NULL; fn++) { 246 fn->fn_next = funs; 247 funs = fn; 248 } 249 } 250 251 int 252 funmap_add(PF fun, const char *fname, int fparams) 253 { 254 struct funmap *fn; 255 256 if ((fn = malloc(sizeof(*fn))) == NULL) 257 return (FALSE); 258 259 fn->fn_funct = fun; 260 fn->fn_name = fname; 261 fn->fn_nparams = fparams; 262 fn->fn_next = funs; 263 264 funs = fn; 265 return (TRUE); 266 } 267 268 /* 269 * Translate from function name to function pointer. 270 */ 271 PF 272 name_function(const char *fname) 273 { 274 struct funmap *fn; 275 276 for (fn = funs; fn != NULL; fn = fn->fn_next) { 277 if (strcmp(fn->fn_name, fname) == 0) 278 return (fn->fn_funct); 279 } 280 return (NULL); 281 } 282 283 const char * 284 function_name(PF fun) 285 { 286 struct funmap *fn; 287 288 for (fn = funs; fn != NULL; fn = fn->fn_next) { 289 if (fn->fn_funct == fun) 290 return (fn->fn_name); 291 } 292 return (NULL); 293 } 294 295 /* 296 * List possible function name completions. 297 */ 298 struct list * 299 complete_function_list(const char *fname) 300 { 301 struct funmap *fn; 302 struct list *head, *el; 303 int len; 304 305 len = strlen(fname); 306 head = NULL; 307 for (fn = funs; fn != NULL; fn = fn->fn_next) { 308 if (memcmp(fname, fn->fn_name, len) == 0) { 309 if ((el = malloc(sizeof(*el))) == NULL) { 310 free_file_list(head); 311 return (NULL); 312 } 313 el->l_name = strdup(fn->fn_name); 314 el->l_next = head; 315 head = el; 316 } 317 } 318 return (head); 319 } 320 321 /* 322 * Find number of parameters for function name. 323 */ 324 int 325 numparams_function(PF fun) 326 { 327 struct funmap *fn; 328 329 for (fn = funs; fn != NULL; fn = fn->fn_next) { 330 if (fn->fn_funct == fun) 331 return (fn->fn_nparams); 332 } 333 return (FALSE); 334 } 335