2 * lesskey [-o output] [input]
5 * If no input file is specified, standard input is used.
6 * If no output file is specified, $HOME/.less is used.
8 * The .less file is used to specify (to "less") user-defined
9 * key bindings. Basically any sequence of 1 to MAX_CMDLEN
10 * keystrokes may be bound to an existing less function.
12 * The input file is an ascii file consisting of a
13 * sequence of lines of the form:
14 * string <whitespace> action [chars] <newline>
16 * "string" is a sequence of command characters which form
17 * the new user-defined command. The command
19 * 1. The actual character itself.
20 * 2. A character preceded by ^ to specify a
21 * control character (e.g. ^X means control-X).
22 * 3. Any character (other than an octal digit) preceded by
23 * a \ to specify the character itself (characters which
24 * must be preceded by \ include ^, \, and whitespace.
25 * 4. A backslash followed by one to three octal digits
26 * to specify a character by its octal value.
27 * "action" is the name of a "less" action, from the table below.
28 * "chars" is an optional sequence of characters which is treated
29 * as keyboard input after the command is executed.
31 * Blank lines and lines which start with # are ignored.
34 * The output file is a non-ascii file, consisting of
35 * zero or more byte sequences of the form:
38 * string <0> <action|A_EXTRA> chars <0>
40 * "string" is the command string.
41 * "<0>" is one null byte.
42 * "<action>" is one byte containing the action code (the A_xxx value).
43 * If action is ORed with A_EXTRA, the action byte is followed
44 * by the null-terminated "chars" string.
51 char usertable[MAX_USERCMD];
59 "back-bracket", A_B_BRACKET,
60 "back-line", A_B_LINE,
61 "back-line-force", A_BF_LINE,
62 "back-screen", A_B_SCREEN,
63 "back-scroll", A_B_SCROLL,
64 "back-search", A_B_SEARCH,
65 "back-window", A_B_WINDOW,
67 "display-flag", A_DISP_OPTION,
68 "display-option", A_DISP_OPTION,
71 "first-cmd", A_FIRSTCMD,
72 "firstcmd", A_FIRSTCMD,
73 "flush-repaint", A_FREPAINT,
74 "forw-bracket", A_F_BRACKET,
75 "forw-forever", A_F_FOREVER,
76 "forw-line", A_F_LINE,
77 "forw-line-force", A_FF_LINE,
78 "forw-screen", A_F_SCREEN,
79 "forw-scroll", A_F_SCROLL,
80 "forw-search", A_F_SEARCH,
81 "forw-window", A_F_WINDOW,
83 "goto-line", A_GOLINE,
84 "goto-mark", A_GOMARK,
86 "index-file", A_INDEX_FILE,
87 "invalid", A_UINVALID,
88 "next-file", A_NEXT_FILE,
89 "noaction", A_NOACTION,
92 "prev-file", A_PREV_FILE,
95 "repaint-flush", A_FREPAINT,
96 "repeat-search", A_AGAIN_SEARCH,
97 "repeat-search-all", A_T_AGAIN_SEARCH,
98 "reverse-search", A_REVERSE_SEARCH,
99 "reverse-search-all", A_T_REVERSE_SEARCH,
100 "set-mark", A_SETMARK,
103 "toggle-flag", A_OPT_TOGGLE,
104 "toggle-option", A_OPT_TOGGLE,
105 "version", A_VERSION,
114 char *p; /* {{ Can't be register since we use &p }} */
115 register char *up; /* Pointer into usertable */
116 FILE *desc; /* Description file (input) */
117 FILE *out; /* Output file */
118 int linenum; /* Line number in input file */
119 char *currcmd; /* Start of current command string */
125 extern char *getenv();
128 * Process command line arguments.
131 while (--argc > 0 && **(++argv) == '-')
136 outfile = &argv[0][2];
137 if (*outfile == '\0')
153 * Open the input file, or use standard input if none specified.
157 if ((desc = fopen(*argv, "r")) == NULL)
166 * Read the input file, one line at a time.
167 * Each line consists of a command string,
168 * followed by white space, followed by an action name.
173 while (fgets(line, sizeof(line), desc) != NULL)
178 * Skip leading white space.
179 * Replace the final newline with a null byte.
180 * Ignore blank lines and comment lines.
183 while (*p == ' ' || *p == '\t')
185 for (i = 0; p[i] != '\n' && p[i] != '\0'; i++)
188 if (*p == '#' || *p == '\0')
192 * Parse the command string and store it in the usertable.
197 if (up >= usertable + MAX_USERCMD)
199 fprintf(stderr, "too many commands, line %d\n",
203 if (up >= currcmd + MAX_CMDLEN)
205 fprintf(stderr, "command too long on line %d\n",
213 } while (*p != ' ' && *p != '\t' && *p != '\0');
216 * Terminate the command string with a null byte.
221 * Skip white space between the command string
222 * and the action name.
223 * Terminate the action name with a null byte if it
224 * is followed by whitespace or a # comment.
228 fprintf(stderr, "missing whitespace on line %d\n",
233 while (*p == ' ' || *p == '\t')
235 for (j = 0; p[j] != ' ' && p[j] != '\t' &&
236 p[j] != '#' && p[j] != '\0'; j++)
241 * Parse the action name and store it in the usertable.
243 for (i = 0; cmdnames[i].cn_name != NULL; i++)
244 if (strcmp(cmdnames[i].cn_name, p) == 0)
246 if (cmdnames[i].cn_name == NULL)
248 fprintf(stderr, "unknown action <%s> on line %d\n",
253 *up++ = cmdnames[i].cn_action;
256 * See if an extra string follows the action name.
258 for (j = j+1; p[j] == ' ' || p[j] == '\t'; j++)
264 * OR the special value A_EXTRA into the action byte.
265 * Put the extra string after the action byte.
276 fprintf(stderr, "%d errors; no output produced\n", errors);
281 * Write the output file.
282 * If no output file was specified, use "$HOME/.less"
287 if (p == NULL || *p == '\0')
289 fprintf(stderr, "cannot find $HOME - using current directory\n");
291 strcpy(line, "_less");
293 strcpy(line, ".less");
299 strcat(line, "\\_less");
301 strcat(line, "/.less");
306 if ((out = fopen(outfile, "w")) == NULL)
309 fwrite((char *)usertable, 1, up-usertable, out);
314 * Parse one character of a string.
327 if (*++p >= '0' && *p <= '7')
330 * Parse an octal number.
335 ch = 8*ch + (*p - '0');
336 while (*++p >= '0' && *p <= '7' && ++i < 3);
341 * Backslash followed by a char just means that char.
347 * Carat means CONTROL.
350 return (CONTROL(p[1]));
358 fprintf(stderr, "usage: lesskey [-o output] [input]\n");