fix some bugs in the command-line.

This commit is contained in:
okuji 1999-09-17 11:49:43 +00:00
parent dfe653fc49
commit d6279335bb
4 changed files with 202 additions and 171 deletions

View file

@ -1,3 +1,14 @@
1999-09-17 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* stage2/char_io.c [!STAGE1_5] (get_cmdline): The argument
COMPLETION is renamed to READLINE.
Do not initialize KILL here.
TAB, C-a, C-e, C-f, C-b, C-u, C-k, C-y, C-p and C-n are handled
only if READLINE is non-zero.
If ECHO_CHAR is not NUL, do not remove the leading spaces in BUF.
Add CMDLINE into the history list only if READLINE is non-zero.
* stage2/stage2.c (cmain): Initialize the kill buffer.
1999-09-17 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
Killing, yanking and manipulating the history are supported.

View file

@ -220,7 +220,7 @@ add_history (const char *cmdline, int no)
If ECHO_CHAR is nonzero, echo it instead of the typed character. */
int
get_cmdline (char *prompt, char *cmdline, int maxlen,
int echo_char, int completion)
int echo_char, int readline)
{
int ystart, yend, xend, lpos, c;
/* The length of PROMPT. */
@ -331,7 +331,6 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
}
lpos = llen;
grub_strcpy (buf, cmdline);
*kill = 0;
cl_init ();
@ -366,90 +365,181 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
}
c = ASCII_CHAR (c);
/* If READLINE is non-zero, handle readline-like key bindings. */
if (readline)
{
switch (c)
{
case 9: /* TAB lists completions */
{
int i, j = 0, llen_old = llen;
/* Find the first word. */
while (buf[j] == ' ')
j++;
while (buf[j] && buf[j] != '=' && buf[j] != ' ')
j++;
/* Since the command line cannot have a '\n', we're OK to
use C. */
c = buf[lpos];
cl_kill_to_end ();
/* goto part after line here */
yend = ((llen + plen) / 79) + ystart;
putchar ('\n');
gotoxy (0, getxy () & 0xff);
if (lpos > j)
{
for (i = lpos; i > 0 && buf[i - 1] != ' '; i--);
if (i <= j)
i = j + 1;
/* print possible completions */
print_completions (buf + i);
/* if somebody in print_completions has added something,
account for that */
while (buf[lpos])
lpos++, llen_old++;
}
else
{
/* Print the command list. */
struct builtin **builtin;
for (builtin = builtin_table; *builtin != 0; builtin++)
{
/* Do not print the name if it cannot be run in
the command-line interface. */
if (! ((*builtin)->flags & BUILTIN_CMDLINE))
continue;
grub_printf ("%s ", (*builtin)->name);
}
}
/* restore command-line */
buf[lpos] = c;
llen = llen_old;
cl_init ();
}
break;
case 1: /* C-a go to beginning of line */
lpos = 0;
cl_setcpos ();
break;
case 5: /* C-e go to end of line */
lpos = llen;
cl_setcpos ();
break;
case 6: /* C-f forward one character */
if (lpos < llen)
{
lpos++;
cl_setcpos ();
}
break;
case 2: /* C-b backward one character */
if (lpos > 0)
{
lpos--;
cl_setcpos ();
}
break;
case 21: /* C-u kill to beginning of line */
if (lpos == 0)
break;
/* Copy the string being deleted to KILL. */
grub_memmove (kill, buf, lpos);
kill[lpos] = 0;
grub_memmove (buf, buf + lpos, llen - lpos + 1);
lpos = llen - lpos;
cl_setcpos ();
cl_kill_to_end ();
lpos = 0;
cl_setcpos ();
cl_print (buf, echo_char);
cl_setcpos ();
break;
case 11: /* C-k kill to end of line */
if (lpos == llen)
break;
/* Copy the string being deleted to KILL. */
grub_memmove (kill, buf + lpos, llen - lpos + 1);
cl_kill_to_end ();
break;
case 25: /* C-y yank the kill buffer */
cl_insert (kill);
break;
case 16: /* C-p fetch the previous command */
{
char *p;
if (history < 0)
/* Save the working buffer. */
grub_strcpy (cmdline, buf);
else if (grub_strcmp (get_history (history), buf) != 0)
/* If BUF is modified, add it into the history list. */
add_history (buf, history);
history++;
p = get_history (history);
if (! p)
{
history--;
break;
}
lpos = 0;
cl_setcpos ();
cl_kill_to_end ();
grub_strcpy (buf, p);
llen = grub_strlen (buf);
lpos = llen;
cl_print (buf, 0);
cl_setcpos ();
}
break;
case 14: /* C-n fetch the next command */
{
char *p;
if (history < 0)
{
break;
}
else if (grub_strcmp (get_history (history), buf) != 0)
/* If BUF is modified, add it into the history list. */
add_history (buf, history);
history--;
p = get_history (history);
if (! p)
p = cmdline;
lpos = 0;
cl_setcpos ();
cl_kill_to_end ();
grub_strcpy (buf, p);
llen = grub_strlen (buf);
lpos = llen;
cl_print (buf, 0);
cl_setcpos ();
}
break;
}
}
/* ESC, C-d and C-h are always handled. Actually C-d is not
functional if READLINE is zero, as the cursor cannot go
backward, but that's ok. */
switch (c)
{
case 27: /* ESC immediately return 1 */
case 27: /* ESC immediately return 1 */
return 1;
case 9: /* TAB lists completions */
if (completion)
{
int i, j = 0, llen_old = llen;
/* Find the first word. */
while (buf[j] == ' ')
j++;
while (buf[j] && buf[j] != '=' && buf[j] != ' ')
j++;
/* Since the command line cannot have a '\n', we're OK to
use C. */
c = buf[lpos];
cl_kill_to_end ();
/* goto part after line here */
yend = ((llen + plen) / 79) + ystart;
putchar ('\n');
gotoxy (0, getxy () & 0xff);
if (lpos > j)
{
for (i = lpos; i > 0 && buf[i - 1] != ' '; i--);
if (i <= j)
i = j + 1;
/* print possible completions */
print_completions (buf + i);
/* if somebody in print_completions has added something,
account for that */
while (buf[lpos])
lpos++, llen_old++;
}
else
{
/* Print the command list. */
struct builtin **builtin;
for (builtin = builtin_table; *builtin != 0; builtin++)
{
/* Do not print the name if it cannot be run in
the command-line interface. */
if (! ((*builtin)->flags & BUILTIN_CMDLINE))
continue;
grub_printf ("%s ", (*builtin)->name);
}
}
/* restore command-line */
buf[lpos] = c;
llen = llen_old;
cl_init ();
}
break;
case 1: /* C-a go to beginning of line */
lpos = 0;
cl_setcpos ();
break;
case 5: /* C-e go to end of line */
lpos = llen;
cl_setcpos ();
break;
case 6: /* C-f forward one character */
if (lpos < llen)
{
lpos++;
cl_setcpos ();
}
break;
case 2: /* C-b backward one character */
if (lpos > 0)
{
lpos--;
cl_setcpos ();
}
break;
case 4: /* C-d delete character under cursor */
if (lpos == llen)
break;
@ -477,87 +567,6 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
}
}
break;
case 21: /* C-u kill to beginning of line */
if (lpos == 0)
break;
/* Copy the string being deleted to KILL. */
grub_memmove (kill, buf, lpos);
kill[lpos] = 0;
grub_memmove (buf, buf + lpos, llen - lpos + 1);
lpos = llen - lpos;
cl_setcpos ();
cl_kill_to_end ();
lpos = 0;
cl_setcpos ();
cl_print (buf, echo_char);
cl_setcpos ();
break;
case 11: /* C-k kill to end of line */
if (lpos == llen)
break;
/* Copy the string being deleted to KILL. */
grub_memmove (kill, buf + lpos, llen - lpos + 1);
cl_kill_to_end ();
break;
case 25: /* C-y yank the kill buffer */
cl_insert (kill);
break;
case 16: /* C-p fetch the previous command */
{
char *p;
if (history < 0)
/* Save the working buffer. */
grub_strcpy (cmdline, buf);
else if (grub_strcmp (get_history (history), buf) != 0)
/* If BUF is modified, add it into the history list. */
add_history (buf, history);
history++;
p = get_history (history);
if (! p)
{
history--;
break;
}
lpos = 0;
cl_setcpos ();
cl_kill_to_end ();
grub_strcpy (buf, p);
llen = grub_strlen (buf);
lpos = llen;
cl_print (buf, 0);
cl_setcpos ();
}
break;
case 14: /* C-n fetch the next command */
{
char *p;
if (history < 0)
{
break;
}
else if (grub_strcmp (get_history (history), buf) != 0)
/* If BUF is modified, add it into the history list. */
add_history (buf, history);
history--;
p = get_history (history);
if (! p)
p = cmdline;
lpos = 0;
cl_setcpos ();
cl_kill_to_end ();
grub_strcpy (buf, p);
llen = grub_strlen (buf);
lpos = llen;
cl_print (buf, 0);
cl_setcpos ();
}
break;
default: /* insert printable character into line */
if (c >= ' ' && c <= '~')
{
@ -574,12 +583,19 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
yend = ((llen + plen) / 79) + ystart;
putchar ('\n');
gotoxy (0, getxy () & 0xff);
/* remove leading spaces */
for (lpos = 0; buf[lpos] == ' '; lpos++);
/* If ECHO_CHAR is NUL, remove the leading spaces. */
lpos = 0;
if (! echo_char)
while (buf[lpos] == ' ')
lpos++;
/* Copy the working buffer to CMDLINE. */
grub_memmove (cmdline, buf + lpos, llen - lpos + 1);
if (lpos < llen)
/* If the readline-like feature is turned on and CMDLINE is not
empty, add it into the history list. */
if (readline && lpos < llen)
add_history (cmdline, 0);
return 0;

View file

@ -612,9 +612,9 @@ char *grub_strcpy (char *dest, const char *src);
/* misc */
void init_page (void);
void print_error (void);
char *convert_to_ascii (char *buf, int c,...);
char *convert_to_ascii (char *buf, int c, ...);
int get_cmdline (char *prompt, char *cmdline, int maxlen,
int echo_char, int completion);
int echo_char, int history);
int substring (char *s1, char *s2);
int get_based_digit (int c, int base);
int safe_parse_maxint (char **str_ptr, int *myint_ptr);

View file

@ -572,7 +572,11 @@ cmain (void)
{
int config_len, menu_len, num_entries;
char *config_entries, *menu_entries;
char *kill = (char *) KILL_BUF;
/* Initialize the kill buffer. */
*kill = 0;
/* Never return. */
for (;;)
{