Author: stepan
Date: Thu Jun  3 19:36:15 2010
New Revision: 133
URL: http://tracker.coreboot.org/trac/filo/changeset/133

Log:
initial tab completion support. device matching fails, so only commands can be 
completed so far. 
Signed-off-by: Stefan Reinauer <[email protected]>

Modified:
   trunk/filo/fs/vfs.c
   trunk/filo/main/grub/completions.c

Modified: trunk/filo/fs/vfs.c
==============================================================================
--- trunk/filo/fs/vfs.c Mon May 24 23:59:35 2010        (r132)
+++ trunk/filo/fs/vfs.c Thu Jun  3 19:36:15 2010        (r133)
@@ -240,3 +240,71 @@
 {
        devclose();
 }
+
+int dir(char *dirname)
+{
+       char *dev = 0;
+       const char *path;
+       int len;
+       int retval = 0;
+       int reopen;
+
+       path = strchr(dirname, ':');
+       if (path) {
+               len = path - dirname;
+               path++;
+               dev = malloc(len + 1);
+               memcpy(dev, dirname, len);
+               dev[len] = '\0';
+       } else {
+               /* No colon is given. Is this device or dirname? */
+               if (dirname[0] == '/') {
+                       /* Anything starts with '/' must be a dirname */
+                       dev = 0;
+                       path = dirname;
+               } else {
+                       dev = strdup(dirname);
+                       path = 0;
+               }
+       }
+       debug("dev=%s, path=%s\n", dev, path);
+
+       if (dev && dev[0]) {
+               if (!devopen(dev, &reopen)) {
+                       fsys = 0;
+                       goto out;
+               }
+               if (!reopen)
+                       fsys = 0;
+       }
+
+       if (path) {
+               if (!fsys || fsys == &nullfs) {
+                       if (!mount_fs())
+                               goto out;
+               }
+               using_devsize = 0;
+               if (!path[0]) {
+                       printf("No dirname is given.\n");
+                       goto out;
+               }
+       } else {
+               fsys = &nullfs;
+       }
+
+       filepos = 0;
+       errnum = 0;
+
+       /* set "dir" function to list completions */
+       print_possibilities = 1;
+
+       retval = fsys->dir_func((char *) path);
+
+out:
+       if (dev)
+               free(dev);
+
+       return retval;
+}
+
+

Modified: trunk/filo/main/grub/completions.c
==============================================================================
--- trunk/filo/main/grub/completions.c  Mon May 24 23:59:35 2010        (r132)
+++ trunk/filo/main/grub/completions.c  Thu Jun  3 19:36:15 2010        (r133)
@@ -22,11 +22,47 @@
 #include <libpayload.h>
 #include <config.h>
 #include <grub/shared.h>
+#define current_slice 0
 
 static int do_completion;
 static int unique;
 static char *unique_string;
 
+static int incomplete, disk_choice;
+static enum
+{
+       PART_UNSPECIFIED = 0,
+       PART_DISK,
+       PART_CHOSEN,
+} part_choice;
+
+int
+real_open_partition (int flags)
+{
+       errnum = ERR_NONE;
+       return 1;
+}
+
+int
+open_partition (void)
+{
+       return real_open_partition (0);
+}
+
+char *
+set_device (char *device)
+{
+       int result = 0;
+
+       if (result) {
+               return device + 1;
+       } else {
+               if (!*device)
+                       incomplete = 1;
+               errnum = ERR_DEV_FORMAT;
+       }
+       return 0;
+}
 
 /* If DO_COMPLETION is true, just print NAME. Otherwise save the unique
    part into UNIQUE_STRING.  */
@@ -62,7 +98,6 @@
 
 int print_completions(int is_filename, int is_completion)
 {
-#ifdef CONFIG_EXPERIMENTAL
        char *buf = (char *) COMPLETION_BUF;
        char *ptr = buf;
 
@@ -71,10 +106,162 @@
        unique = 0;
        do_completion = is_completion;
 
-#warning FIXME implement print_completions
-       // FIXME: This function is a dummy, returning an error.
-       errnum = ERR_BAD_FILENAME;
+       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 + strlen 
(unique_string);
+                               *u++ = ' ';
+                               *u = 0;
+                       }
+                       strcpy (buf, unique_string);
+               }
+
+               if (!is_completion)
+                       grub_putchar ('\n');
+
+               print_error();
+               do_completion = 0;
+               if (errnum)
+                       return -1;
+               else
+                       return unique - 1;
+       }
+
+       if (*buf == '/' || (ptr = set_device (buf)) || incomplete) {
+               errnum = 0;
+               if (*buf == '(' && (incomplete || ! *ptr)) {
+                       if (!part_choice) {
+                               /* disk completions */
+                               int disk_no, i, j;
+
+                               if (!is_completion)
+                                       grub_printf (" Possible disks are: ");
+
+                               if (!ptr
+                                       || *(ptr-1) != 'd'
+                                       || *(ptr-2) != 'n' /* netboot? */
+                                       || *(ptr-2) != 'c') {
+                                       for (i = (ptr && (*(ptr-1) == 'd' && 
*(ptr-2) == 'h') ? 1:0);
+                                            i < (ptr && (*(ptr-1) == 'd' && 
*(ptr-2) == 'f') ?  1:2);
+                                            i++) {
+                                               for (j = 0; j < 8; j++) {
+                                                       if ((disk_choice)) { // 
TODO check geometry
+                                                               char 
dev_name[8];
+                                                               sprintf 
(dev_name, "%cd%d", i ?  'h':'f', j);
+                                                               
print_a_completion(dev_name);
+                                                       }
+                                               }
+                                       }
+                               }
+
+#if 0
+                               if (cdrom_drive != GRUB_INVALID_DRIVE
+                                   && (disk_choice || cdrom_drive == 
current_drive)
+                                   && (!ptr
+                                       || *(ptr-1) == '('
+                                       || (*(ptr-1) == 'd' && *(ptr-2) == 
'c')))
+                                       print_a_completion("cd");
+#endif
+
+                               if (is_completion && *unique_string) {
+                                       ptr = buf;
+                                       while (*ptr != '(')
+                                               ptr--;
+                                       ptr++;
+                                       strcpy (ptr, unique_string);
+                                       if (unique == 1) {
+                                               ptr += strlen (ptr);
+                                               if (*unique_string == 'h') {
+                                                       *ptr++ = ',';
+                                                       *ptr = 0;
+                                               } else {
+                                                       *ptr++ = ')';
+                                                       *ptr = 0;
+                                               }
+                                       }
+                               }
+
+                               if (!is_completion)
+                                       grub_putchar('\n');
+                       } else {
+                               /* Partition completions */
+                               if (part_choice == PART_CHOSEN
+                                   && open_partition()
+                                   && ! IS_PC_SLICE_TYPE_BSD(current_slice)) {
+                                       unique = 1;
+                                       ptr = buf + strlen(buf);
+                                       if (*(ptr - 1) != ')') {
+                                               *ptr++ = ')';
+                                               *ptr = 0;
+                                       }
+                               } else {
+                                       if (!is_completion)
+                                               grub_printf (" Possible 
partitions are:\n");
+                                       real_open_partition(1);
+                                       if (is_completion && *unique_string) {
+                                               ptr = buf;
+                                               while (*ptr++ != ',')
+                                                       ;
+                                               strcpy (ptr, unique_string);
+                                       }
+                               }
+                       }
+               } else if (ptr && *ptr == '/') {
+                       /* filename completions */
+                       if (!is_completion)
+                               grub_printf (" Possible files are:");
+                       dir(buf);
+
+                       if (is_completion && *unique_string) {
+                               ptr += strlen (ptr);
+                               while (*ptr != '/')
+                                       ptr--;
+                               ptr++;
+
+                               strcpy(ptr, unique_string);
+
+                               if (unique == 1) {
+                                       ptr += strlen (unique_string);
+
+                                       /* Check if the file UNIQUE_STRING is a 
directory.  */
+                                       *ptr = '/';
+                                       *(ptr + 1) = 0;
+
+                                       dir (buf);
+
+                                       /* Restore the original unique value. */
+                                       unique = 1;
+
+                                       if (errnum) {
+                                               /* regular file */
+                                               errnum = 0;
+                                               *ptr = ' ';
+                                               *(ptr + 1) = 0;
+                                       }
+                               }
+                       }
+
+                       if (!is_completion)
+                               grub_putchar ('\n');
+
+               } else {
+                       errnum = ERR_BAD_FILENAME;
+               }
+       }
 
        print_error();
        do_completion = 0;
@@ -82,9 +269,4 @@
                return -1;
        else
                return unique - 1;
-#else
-       errnum = ERR_BAD_FILENAME;
-       print_error();
-       return -1;
-#endif
 }

-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to