improve the command-line interface.

This commit is contained in:
okuji 1999-09-17 03:21:31 +00:00
parent 4ea54f2d0a
commit dfe653fc49
5 changed files with 285 additions and 136 deletions

View file

@ -1,3 +1,39 @@
1999-09-17 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
Killing, yanking and manipulating the history are supported.
* stage2/shared.h (cur_cmdline): Removed.
(MAX_CMDLINE): Moved near the beginning of the file.
(NEW_HEAPSIZE): Likewise.
(CMDLINE_BUFLEN): Set to MAX_CMDLINE.
(KILL_BUF): New macro.
(KILL_BUFLEN): Likewise.
(HISTORY_BUF): Likewise.
(HISTORY_SIZE): Likewise.
(HISTORY_BUFLEN): Likewise.
(MENU_BUF): Set to HISTORY_BUF + HISTORY_BUFLEN.
(MENU_BUFLEN): Set to 0x8000 + PASSWORD_BUF - HISTORY_BUF.
(strcpy): New macro.
(grub_strcpy): Delared.
* stage2/boot.c (cur_cmdline): Removed.
* stage2/char_io.c [!STAGE1_5] (grub_strcpy): New function.
[!STAGE1_5] (get_history): Likewise.
[!STAGE1_5] (add_history): Likewise.
[!STAGE1_5] (get_cmdline): Use BUF instead of CMDLINE for the
working buffer for the command-line.
A new function cl_insert is used to insert a string to the
command-line.
In the case where C-u or C-k is pressed, copy the string being
deleted to KILL.
If C-y is pressed, insert KILL to the command-line.
If C-p is pressed, fetch the previous command from the history
list HISTORY, and if C-n is pressed, fetch the next command from
it.
If LPOS is less than LLEN, add CMDLINE into the history list.
If C is equal to KEY_UP, set C to 16, and if C is equal to
KEY_DOWN, set C to 14.
[!STAGE1_5] (num_history): New variable.
1999-09-15 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp> 1999-09-15 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* stage2/size_test: Do not check for the size of Stage 2. * stage2/size_test: Do not check for the size of Stage 2.

2
NEWS
View file

@ -24,6 +24,8 @@ New in 0.5.93:
the second floppy drive. the second floppy drive.
* Integrated the netboot support in the Dresden version of GRUB. * Integrated the netboot support in the Dresden version of GRUB.
* FreeBSD support in the grub shell is improved. * FreeBSD support in the grub shell is improved.
* Killing (C-u and C-k), yanking (C-y) and manipulating the history
(C-p and C-n) are supported.
New in 0.5.92 - 1999-07-26: New in 0.5.92 - 1999-07-26:
* Bug fixes (i.e. Stage 1.5 can work fine again). * Bug fixes (i.e. Stage 1.5 can work fine again).

View file

@ -26,7 +26,6 @@
#include "imgact_aout.h" #include "imgact_aout.h"
#include "i386-elf.h" #include "i386-elf.h"
char *cur_cmdline;
static int cur_addr; static int cur_addr;
entry_func entry_addr; entry_func entry_addr;
static struct mod_list mll[99]; static struct mod_list mll[99];

View file

@ -184,6 +184,31 @@ init_page (void)
version_string, mbi.mem_lower, mbi.mem_upper); version_string, mbi.mem_lower, mbi.mem_upper);
} }
/* The number of the history entries. */
static int num_history = 0;
/* Get the NOth history. If NO is less than zero or greater than or
equal to NUM_HISTORY, return NULL. Otherwise return a valid string. */
static char *
get_history (int no)
{
if (no < 0 || no >= num_history)
return 0;
return (char *) HISTORY_BUF + MAX_CMDLINE * no;
}
/* Add CMDLINE to the history buffer. */
static void
add_history (const char *cmdline, int no)
{
grub_memmove ((char *) HISTORY_BUF + MAX_CMDLINE * (no + 1),
(char *) HISTORY_BUF + MAX_CMDLINE * no,
MAX_CMDLINE * (num_history - no));
grub_strcpy ((char *) HISTORY_BUF + MAX_CMDLINE * no, cmdline);
if (num_history < HISTORY_SIZE)
num_history++;
}
/* Don't use this with a MAXLEN greater than 1600 or so! The problem /* Don't use this with a MAXLEN greater than 1600 or so! The problem
is that GET_CMDLINE depends on the everything fitting on the screen is that GET_CMDLINE depends on the everything fitting on the screen
@ -198,8 +223,16 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
int echo_char, int completion) int echo_char, int completion)
{ {
int ystart, yend, xend, lpos, c; int ystart, yend, xend, lpos, c;
/* The length of PROMPT. */
int plen = 0; int plen = 0;
/* The length of the command-line. */
int llen = 0; int llen = 0;
/* The index for the history. */
int history = -1;
/* The working buffer for the command-line. */
char *buf = (char *) CMDLINE_BUF;
/* The kill buffer. */
char *kill = (char *) KILL_BUF;
/* nested function definition for code simplicity */ /* nested function definition for code simplicity */
static void cl_print (char *str, int echo_char) static void cl_print (char *str, int echo_char)
@ -219,6 +252,7 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
} }
} }
} }
/* nested function definition for code simplicity */ /* nested function definition for code simplicity */
static void cl_setcpos (void) static void cl_setcpos (void)
{ {
@ -238,7 +272,7 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
yend = ystart; yend = ystart;
xend = 0; xend = 0;
cl_print (prompt, 0); cl_print (prompt, 0);
cl_print (cmdline, echo_char); cl_print (buf, echo_char);
cl_setcpos (); cl_setcpos ();
} }
@ -246,7 +280,7 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
static void cl_kill_to_end () static void cl_kill_to_end ()
{ {
int i; int i;
cmdline[lpos] = 0; buf[lpos] = 0;
for (i = lpos; i <= llen; i++) for (i = lpos; i <= llen; i++)
{ {
if (i && ((i + plen) % 79) == 0) if (i && ((i + plen) % 79) == 0)
@ -257,10 +291,35 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
cl_setcpos (); cl_setcpos ();
} }
while (prompt[plen]) static void cl_insert (const char *str)
plen++; {
while (cmdline[llen]) int l = grub_strlen (str);
llen++;
if (llen + l < maxlen)
{
if (lpos == llen)
{
grub_memmove (buf + lpos, str, l + 1);
cl_print (buf + lpos, echo_char);
lpos += l;
cl_setcpos ();
}
else
{
grub_memmove (buf + lpos + l, buf + lpos, llen - lpos + 1);
grub_memmove (buf + lpos, str, l);
cl_setcpos ();
cl_print (buf + lpos, echo_char);
lpos += l;
cl_setcpos ();
}
llen += l;
}
}
plen = grub_strlen (prompt);
llen = grub_strlen (cmdline);
if (maxlen > MAX_CMDLINE) if (maxlen > MAX_CMDLINE)
{ {
maxlen = MAX_CMDLINE; maxlen = MAX_CMDLINE;
@ -271,6 +330,8 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
} }
} }
lpos = llen; lpos = llen;
grub_strcpy (buf, cmdline);
*kill = 0;
cl_init (); cl_init ();
@ -284,6 +345,12 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
case KEY_RIGHT: case KEY_RIGHT:
c = 6; c = 6;
break; break;
case KEY_UP:
c = 16;
break;
case KEY_DOWN:
c = 14;
break;
case KEY_HOME: case KEY_HOME:
c = 1; c = 1;
break; break;
@ -296,7 +363,6 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
case KEY_BACKSPACE: case KEY_BACKSPACE:
c = 8; c = 8;
break; break;
default:
} }
c = ASCII_CHAR (c); c = ASCII_CHAR (c);
@ -311,14 +377,14 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
int i, j = 0, llen_old = llen; int i, j = 0, llen_old = llen;
/* Find the first word. */ /* Find the first word. */
while (cmdline[j] == ' ') while (buf[j] == ' ')
j++; j++;
while (cmdline[j] && cmdline[j] != '=' && cmdline[j] != ' ') while (buf[j] && buf[j] != '=' && buf[j] != ' ')
j++; j++;
/* Since the command line cannot have a '\n', we're OK to /* Since the command line cannot have a '\n', we're OK to
use C. */ use C. */
c = cmdline[lpos]; c = buf[lpos];
cl_kill_to_end (); cl_kill_to_end ();
@ -330,14 +396,14 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
if (lpos > j) if (lpos > j)
{ {
for (i = lpos; i > 0 && cmdline[i - 1] != ' '; i--); for (i = lpos; i > 0 && buf[i - 1] != ' '; i--);
if (i <= j) if (i <= j)
i = j + 1; i = j + 1;
/* print possible completions */ /* print possible completions */
print_completions (cmdline + i); print_completions (buf + i);
/* if somebody in print_completions has added something, /* if somebody in print_completions has added something,
account for that */ account for that */
while (cmdline[lpos]) while (buf[lpos])
lpos++, llen_old++; lpos++, llen_old++;
} }
else else
@ -357,7 +423,7 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
} }
/* restore command-line */ /* restore command-line */
cmdline[lpos] = c; buf[lpos] = c;
llen = llen_old; llen = llen_old;
cl_init (); cl_init ();
} }
@ -373,7 +439,7 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
case 6: /* C-f forward one character */ case 6: /* C-f forward one character */
if (lpos < llen) if (lpos < llen)
{ {
lpos ++; lpos++;
cl_setcpos (); cl_setcpos ();
} }
break; break;
@ -387,7 +453,7 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
case 4: /* C-d delete character under cursor */ case 4: /* C-d delete character under cursor */
if (lpos == llen) if (lpos == llen)
break; break;
lpos ++; lpos++;
/* fallthrough is on purpose! */ /* fallthrough is on purpose! */
case 8: /* C-h backspace */ case 8: /* C-h backspace */
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
@ -396,8 +462,7 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
if (lpos > 0) if (lpos > 0)
{ {
int i; int i;
for (i = lpos - 1; i < llen; i++) grub_memmove (buf + lpos - 1, buf + lpos, llen - lpos + 1);
cmdline[i] = cmdline[i + 1];
i = lpos; i = lpos;
lpos = llen - 1; lpos = llen - 1;
cl_setcpos (); cl_setcpos ();
@ -407,7 +472,7 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
cl_setcpos (); cl_setcpos ();
if (lpos != llen) if (lpos != llen)
{ {
cl_print (cmdline + lpos, echo_char); cl_print (buf + lpos, echo_char);
cl_setcpos (); cl_setcpos ();
} }
} }
@ -415,50 +480,92 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
case 21: /* C-u kill to beginning of line */ case 21: /* C-u kill to beginning of line */
if (lpos == 0) if (lpos == 0)
break; break;
{ /* Copy the string being deleted to KILL. */
int i; grub_memmove (kill, buf, lpos);
for (i = 0; i < (llen - lpos); i++) kill[lpos] = 0;
cmdline[i] = cmdline[lpos + i]; grub_memmove (buf, buf + lpos, llen - lpos + 1);
}
lpos = llen - lpos; lpos = llen - lpos;
cl_setcpos (); cl_setcpos ();
/* fallthrough on purpose! */
case 11: /* C-k kill to end of line */
if (lpos < llen)
{
cl_kill_to_end (); cl_kill_to_end ();
if (c == 21)
{
lpos = 0; lpos = 0;
cl_setcpos (); cl_setcpos ();
cl_print (cmdline, echo_char); 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 (); 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; break;
default: /* insert printable character into line */ default: /* insert printable character into line */
if (llen < (maxlen - 1) && c >= ' ' && c <= '~') if (c >= ' ' && c <= '~')
{ {
if (lpos == llen) char str[2];
{
cmdline[lpos] = c; str[0] = c;
cmdline[lpos + 1] = 0; str[1] = 0;
cl_print (cmdline + lpos, echo_char); cl_insert (str);
lpos ++;
cl_setcpos ();
}
else
{
int i;
for (i = llen; i >= lpos; i--)
cmdline[i + 1] = cmdline[i];
cmdline[lpos] = c;
cl_setcpos ();
cl_print (cmdline + lpos, echo_char);
lpos++;
cl_setcpos ();
}
llen++;
} }
} }
} }
@ -469,23 +576,11 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
gotoxy (0, getxy () & 0xff); gotoxy (0, getxy () & 0xff);
/* remove leading spaces */ /* remove leading spaces */
/* use c and lpos as indexes now */ for (lpos = 0; buf[lpos] == ' '; lpos++);
for (lpos = 0; cmdline[lpos] == ' '; lpos++);
if (lpos != 0) grub_memmove (cmdline, buf + lpos, llen - lpos + 1);
{ if (lpos < llen)
c = 0; add_history (cmdline, 0);
do
{
cmdline[c] = cmdline[lpos];
c++;
lpos++;
}
while (cmdline[lpos]);
/* Zero-terminate the string. */
cmdline[c] = 0;
}
return 0; return 0;
} }
@ -753,4 +848,11 @@ grub_memset (void *start, int c, int len)
return errnum ? NULL : start; return errnum ? NULL : start;
} }
char *
grub_strcpy (char *dest, const char *src)
{
grub_memmove (dest, src, grub_strlen (src) + 1);
return dest;
}
#endif /* ! STAGE1_5 */ #endif /* ! STAGE1_5 */

View file

@ -48,6 +48,11 @@ extern char *grub_scratch_mem;
#define MAXINT 0x7FFFFFFF #define MAXINT 0x7FFFFFFF
/* Maximum command line size. Before you blindly increase this value,
see the comment in char_io.c (get_cmdline). */
#define MAX_CMDLINE 1600
#define NEW_HEAPSIZE 1500
/* 512-byte scratch area */ /* 512-byte scratch area */
#define SCRATCHADDR RAW_ADDR (0x77e00) #define SCRATCHADDR RAW_ADDR (0x77e00)
#define SCRATCHSEG RAW_SEG (0x77e0) #define SCRATCHSEG RAW_SEG (0x77e0)
@ -89,12 +94,20 @@ extern char *grub_scratch_mem;
/* The buffer for the command-line. */ /* The buffer for the command-line. */
#define CMDLINE_BUF (PASSWORD_BUF + PASSWORD_BUFLEN) #define CMDLINE_BUF (PASSWORD_BUF + PASSWORD_BUFLEN)
/* Make sure that this is larger than NEW_HEAPSIZE defined below. */ #define CMDLINE_BUFLEN MAX_CMDLINE
#define CMDLINE_BUFLEN 0x600
/* The kill buffer for the command-line. */
#define KILL_BUF (CMDLINE_BUF + CMDLINE_BUFLEN)
#define KILL_BUFLEN MAX_CMDLINE
/* The history buffer for the command-line. */
#define HISTORY_BUF (KILL_BUF + KILL_BUFLEN)
#define HISTORY_SIZE 5
#define HISTORY_BUFLEN (MAX_CMDLINE * HISTORY_SIZE)
/* The buffer for the menu entries. */ /* The buffer for the menu entries. */
#define MENU_BUF (CMDLINE_BUF + CMDLINE_BUFLEN) #define MENU_BUF (HISTORY_BUF + HISTORY_BUFLEN)
#define MENU_BUFLEN (0x8000 + PASSWORD_BUF - MENU_BUF) #define MENU_BUFLEN (0x8000 + PASSWORD_BUF - HISTORY_BUF)
/* /*
* Linux setup parameters * Linux setup parameters
@ -272,6 +285,7 @@ extern char *grub_scratch_mem;
#define strcmp grub_strcmp #define strcmp grub_strcmp
#define tolower grub_tolower #define tolower grub_tolower
#define strlen grub_strlen #define strlen grub_strlen
#define strcpy grub_strcpy
#endif /* WITHOUT_LIBC_STUBS */ #endif /* WITHOUT_LIBC_STUBS */
@ -448,11 +462,6 @@ extern char *err_list[];
typedef void (*entry_func) (int, int, int, int, int, int) typedef void (*entry_func) (int, int, int, int, int, int)
__attribute__ ((noreturn)); __attribute__ ((noreturn));
/* Maximum command line size. Before you blindly increase this value,
see the comment in char_io.c (get_cmdline). */
#define MAX_CMDLINE 1600
#define NEW_HEAPSIZE 1500
extern char *cur_cmdline;
extern entry_func entry_addr; extern entry_func entry_addr;
/* Enter the stage1.5/stage2 C code after the stack is set up. */ /* Enter the stage1.5/stage2 C code after the stack is set up. */
@ -598,6 +607,7 @@ char *grub_strstr (const char *s1, const char *s2);
int grub_memcmp (const char *s1, const char *s2, int n); int grub_memcmp (const char *s1, const char *s2, int n);
int grub_strcmp (const char *s1, const char *s2); int grub_strcmp (const char *s1, const char *s2);
int grub_strlen (const char *str); int grub_strlen (const char *str);
char *grub_strcpy (char *dest, const char *src);
/* misc */ /* misc */
void init_page (void); void init_page (void);