improve the completion code.
This commit is contained in:
parent
dc267a70d2
commit
dc73edd77c
4 changed files with 250 additions and 130 deletions
45
ChangeLog
45
ChangeLog
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
151
stage2/disk_io.c
151
stage2/disk_io.c
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue