improve the completion code.

This commit is contained in:
okuji 1999-09-18 22:28:36 +00:00
parent dc267a70d2
commit dc73edd77c
4 changed files with 250 additions and 130 deletions

View file

@ -1,3 +1,48 @@
1999-09-19 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
The completion code is heavily modified.
* stage2/char_io.c [!STAGE1_5] (get_cmdline): In the completion
code, use COMPLETION_BUFFER to get the completion instead of
writing to BUF directly.
Save the position of a possible equal character after a command
in EQUAL_POS and replace the equal character with a space
temporarily for the code simplicity.
At first, just get completions, and, if there is more than one
completions, then print the list of the completions.
* stage2/disk_io.c [!STAGE1_5] (do_completion): New variable.
[!STAGE1_5] (unique): Moved the definition near the beginning.
[!STAGE1_5] (unique_string): Likewise. And changed the type to
char *.
(check_BSD_parts) [!STAGE1_5]: If DO_COMPLETION is non-zero, do
not print anything.
(real_open_partition) [!STAGE1_5]: Likewise.
[!STAGE1_5] (print_fsys_type): Likewise.
[!STAGE1_5] (print_a_completion): The argument FILENAME is
renamed to NAME.
If DO_COMPLETION is non-zero, get the unique part from NAME and
set UNIQUE_STRING to it.
If DO_COMPLETION is zero, just print NAME.
Do not call printf unconditionally.
[!STAGE1_5] (print_completions): Accept two arguements
IS_FILENAME and IS_COMPLETION instead of FILENAME.
Set UNIQUE_STRING to UNIQUE_BUF.
Set DO_COMPLETION to IS_COMPLETION and set it to zero before
returning.
If IS_FILENAME is zero, then complete builtin commands and
return UNIQUE - 1.
Use BUF instead of FILENAME.
If IS_COMPLETION is non-zero, do not print anything.
Copy UNIQUE_STRING to PTR only if IS_COMPLETION and
*UNIQUE_STRING are non-zero.
* stage2/shared.h (COMPLETION_BUF): New macro.
(COMPLETION_BUFLEN): Likewise.
(UNIQUE_BUF): Likewise.
(UNIQUE_BUFLEN): Likewise.
(MENU_BUF): Set to UNIQUE_BUF + UNIQUE_BUFLEN.
(MENU_BUFLEN): Set to 0x8000 + PASSWORD_BUF - UNIQUE_BUF.
(print_completions): Adjusted to the definition.
1999-09-19 OKUJI Yoshinori <okuji@kuicr.kyoto-u.ac.jp>
* acinclude.m4 (grub_ASM_PREFIX_REQUIREMENT): Do not call

View file

@ -373,57 +373,65 @@ get_cmdline (char *prompt, char *cmdline, int maxlen,
{
case 9: /* TAB lists completions */
{
int i, j = 0, llen_old = llen;
int i;
/* POS points to the first space after a command. */
int pos = 0;
int ret;
char *completion_buffer = (char *) COMPLETION_BUF;
int equal_pos = -1;
int is_filename;
/* Find the first word. */
while (buf[j] == ' ')
j++;
while (buf[j] && buf[j] != '=' && buf[j] != ' ')
j++;
while (buf[pos] == ' ')
pos++;
while (buf[pos] && buf[pos] != '=' && buf[pos] != ' ')
pos++;
/* Since the command line cannot have a '\n', we're OK to
use C. */
c = buf[lpos];
is_filename = (lpos > pos);
cl_kill_to_end ();
/* Find the position of the equal character after a
command, and replace it with a space. */
for (i = pos; buf[i] && buf[i] != ' '; i++)
if (buf[i] == '=')
{
equal_pos = i;
buf[i] = ' ';
break;
}
/* goto part after line here */
/* Find the position of the first character in this
word. */
for (i = lpos; i > 0 && buf[i - 1] != ' '; i--)
;
/* Copy this word to COMPLETION_BUFFER and do the
completion. */
grub_memmove (completion_buffer, buf + i, lpos - i);
completion_buffer[lpos - i] = 0;
ret = print_completions (is_filename, 1);
if (ret >= 0)
{
/* Found, so insert COMPLETION_BUFFER. */
cl_insert (completion_buffer + lpos - i);
if (ret > 0)
{
/* There is more than one candidates, so print
the list. */
/* Go to the part after the line here. */
yend = ((llen + plen) / 79) + ystart;
putchar ('\n');
grub_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);
print_completions (is_filename, 0);
}
}
/* restore command-line */
buf[lpos] = c;
llen = llen_old;
/* Restore the command-line. */
if (equal_pos >= 0)
buf[equal_pos] = '=';
cl_init ();
}
break;

View file

@ -30,6 +30,11 @@ void (*debug_fs) (int) = NULL;
void (*debug_fs_func) (int) = NULL;
int print_possibilities;
static int do_completion;
static int unique;
static char *unique_string;
#endif
int fsmax;
@ -406,9 +411,12 @@ check_BSD_parts (int flags)
{
if (!got_part)
{
if (! do_completion)
printf ("[BSD sub-partitions immediately follow]\n");
got_part = 1;
}
if (! do_completion)
printf (" BSD Partition num: \'%c\', ", part_no + 'a');
check_and_print_mount ();
}
@ -537,6 +545,7 @@ real_open_partition (int flags)
else if (flags)
{
current_partition |= 0xFFFF;
if (! do_completion)
printf (" Partition num: %d, ", slice_no);
if (! IS_PC_SLICE_TYPE_BSD (current_slice))
check_and_print_mount ();
@ -632,10 +641,6 @@ open_partition (void)
/* XX used for device completion in 'set_device' and 'print_completions' */
static int incomplete, disk_choice;
#ifndef STAGE1_5
static int unique;
static char unique_string[128]; /* XXX Don't know yet */
#endif
static enum
{
PART_UNSPECIFIED = 0,
@ -957,6 +962,8 @@ setup_part (char *filename)
void
print_fsys_type (void)
{
if (! do_completion)
{
printf (" Filesystem type ");
if (fsys_type != NUM_FSYS)
@ -968,37 +975,38 @@ print_fsys_type (void)
printf ("using whole disk\n");
else
printf ("partition type 0x%x\n", current_slice);
}
}
#endif /* STAGE1_5 */
#ifndef STAGE1_5
/*
* print_a_completion saves what has been printed to unique_string
* printf's with a leading ' '.
*/
/* If DO_COMPLETION is true, just print NAME. Otherwise save the unique
part into UNIQUE_STRING. */
void
print_a_completion (char *filename)
print_a_completion (char *name)
{
char *f = filename;
char *u = unique_string;
if (! *u && unique == 0)
if (do_completion)
{
/* copy first string, this is unique. */
while ((*u++ = *f++))
char *buf = unique_string;
if (! unique)
while ((*buf++ = *name++))
;
}
else
{
while (*u && (*u == *f))
u++, f++;
/* mismatch, strip it. */
*u = '\0';
while (*buf && (*buf == *name))
{
buf++;
name++;
}
unique++;
/* mismatch, strip it. */
*buf = '\0';
}
}
else
grub_printf (" %s", name);
printf (" %s", filename);
unique++;
}
/*
@ -1006,27 +1014,66 @@ print_a_completion (char *filename)
* any sane combination of the two.
*/
void
print_completions (char *filename)
int
print_completions (int is_filename, int is_completion)
{
char *ptr = filename;
char *buf = (char *) COMPLETION_BUF;
char *ptr = buf;
*unique_string = '\0';
unique_string = (char *) UNIQUE_BUF;
*unique_string = 0;
unique = 0;
do_completion = is_completion;
if (*filename == '/' || (ptr = set_device (filename)) || incomplete)
if (! is_filename)
{
/* Print the completions of builtin commands. */
struct builtin **builtin;
if (! is_completion)
grub_printf (" Possible commands are:");
for (builtin = builtin_table; (*builtin); builtin++)
{
/* If *BUILTIN cannot be run in the command-line, skip it. */
if (! ((*builtin)->flags & BUILTIN_CMDLINE))
continue;
if (substring (buf, (*builtin)->name) <= 0)
print_a_completion ((*builtin)->name);
}
if (is_completion && *unique_string)
{
if (unique == 1)
{
char *u = unique_string + grub_strlen (unique_string);
*u++ = ' ';
*u = 0;
}
grub_strcpy (buf, unique_string);
}
do_completion = 0;
return unique - 1;
}
if (*buf == '/' || (ptr = set_device (buf)) || incomplete)
{
errnum = 0;
if (*filename != '/' && (incomplete || !*ptr))
if (*buf != '/' && (incomplete || ! *ptr))
{
if (!part_choice)
if (! part_choice)
{
/* disk completions */
int disk_no, i, j;
struct geometry geom;
printf (" Possible disks are: ");
if (! is_completion)
grub_printf (" Possible disks are: ");
for (i = (ptr && (*(ptr-2) == 'h' && *(ptr-1) == 'd') ? 1 : 0);
i < (ptr && (*(ptr-2) == 'f' && *(ptr-1) == 'd') ? 1 : 2);
@ -1035,8 +1082,8 @@ print_completions (char *filename)
for (j = 0; j < 8; j++)
{
disk_no = (i * 0x80) + j;
if ((disk_choice || disk_no == current_drive) &&
! get_diskinfo (disk_no, &geom))
if ((disk_choice || disk_no == current_drive)
&& ! get_diskinfo (disk_no, &geom))
{
char dev_name[4];
@ -1049,7 +1096,9 @@ print_completions (char *filename)
}
}
ptr = filename;
if (is_completion && *unique_string)
{
ptr = buf;
while (*ptr != '(')
ptr--;
ptr++;
@ -1067,14 +1116,16 @@ print_completions (char *filename)
&& ('0' <= *ptr && *ptr <= '8'))
*(ptr + 1) = ')', *(ptr + 2) = '\0';
putchar ('\n');
grub_putchar ('\n');
}
}
else
{
/* partition completions */
if (part_choice == PART_DISK)
{
printf (" Possible partitions are:\n");
if (! is_completion)
grub_printf (" Possible partitions are:\n");
real_open_partition (1);
}
else
@ -1084,7 +1135,7 @@ print_completions (char *filename)
check_and_print_mount ();
/* FIXME: Can talk about linux only, do we need
to know about syntax here? */
ptr = filename;
ptr = buf;
while (*ptr)
ptr++;
if (*(ptr - 1) != ')')
@ -1098,21 +1149,27 @@ print_completions (char *filename)
else if (*ptr == '/')
{
/* filename completions */
printf (" Possible files are:");
dir (filename);
{
char *u = unique_string;
if (! is_completion)
grub_printf (" Possible files are:");
if (*u)
dir (buf);
if (is_completion && *unique_string)
{
while (*ptr++)
;
ptr += grub_strlen (ptr);
while (*ptr != '/')
ptr--;
ptr++;
while ((*ptr++ = *u++))
;
if (unique == 1)
{
char *u = unique_string + grub_strlen (unique_string);
*u++ = ' ';
*u = 0;
}
grub_strcpy (ptr, unique_string);
}
}
else
@ -1120,6 +1177,8 @@ print_completions (char *filename)
}
print_error ();
do_completion = 0;
return unique - 1;
}
#endif /* STAGE1_5 */

View file

@ -105,9 +105,17 @@ extern char *grub_scratch_mem;
#define HISTORY_SIZE 5
#define HISTORY_BUFLEN (MAX_CMDLINE * HISTORY_SIZE)
/* The buffer for the completion. */
#define COMPLETION_BUF (HISTORY_BUF + HISTORY_BUFLEN)
#define COMPLETION_BUFLEN MAX_CMDLINE
/* The buffer for the unique string. */
#define UNIQUE_BUF (COMPLETION_BUF + COMPLETION_BUFLEN)
#define UNIQUE_BUFLEN MAX_CMDLINE
/* The buffer for the menu entries. */
#define MENU_BUF (HISTORY_BUF + HISTORY_BUFLEN)
#define MENU_BUFLEN (0x8000 + PASSWORD_BUF - HISTORY_BUF)
#define MENU_BUF (UNIQUE_BUF + UNIQUE_BUFLEN)
#define MENU_BUFLEN (0x8000 + PASSWORD_BUF - UNIQUE_BUF)
/*
* Linux setup parameters
@ -659,7 +667,7 @@ void print_fsys_type (void);
/* Display device and filename completions. */
void print_a_completion (char *filename);
void print_completions (char *filename);
int print_completions (int is_filename, int is_completion);
/* Copies the current partition data to the desired address. */
void copy_current_part_entry (char *buf);