/[grub]/grub2/normal/cmdline.c
ViewVC logotype

Diff of /grub2/normal/cmdline.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.15 by subdino, Mon Jul 4 13:50:10 2005 UTC revision 1.16 by okuji, Fri Aug 12 19:53:33 2005 UTC
# Line 133  grub_history_replace (int pos, char *s) Line 133  grub_history_replace (int pos, char *s)
133    hist_lines[pos] = grub_strdup (s);    hist_lines[pos] = grub_strdup (s);
134  }  }
135    
 /* Try to complete the string in BUF, return the characters that  
    should be added to the string.  This command outputs the possible  
    completions, in that case set RESTORE to 1 so the caller can  
    restore the prompt.  */  
 static char *  
 grub_tab_complete (char *buf, int *restore)  
 {  
   char *pos = buf;  
   char *path;  
     
   char *found = 0;  
   int begin;  
   int end;  
   int len;  
   int numfound = 0;  
   
   /* The disk that is used for grub_partition_iterate.  */  
   grub_device_t partdev;  
                   
   /* String that is added when matched.  */  
   char *matchstr;  
   
   auto void print_simple_completion (char *comp);  
   auto void print_partition_completion (char *comp);  
   auto int NESTED_FUNC_ATTR add_completion (const char *comp, const char *match,  
                                             const char *what,  
                                             void (*print_completion) (char *));  
   auto int iterate_commands (grub_command_t cmd);  
   auto int iterate_dev (const char *devname);  
   auto int iterate_part (const grub_partition_t p);  
   auto int iterate_dir (const char *filename, int dir);  
     
   
   
   void print_simple_completion (char *comp)  
     {  
       grub_printf (" %s", comp);  
     }  
   
   void print_partition_completion (char *comp)  
     {  
       grub_print_partinfo (partdev, comp);  
       grub_errno = 0;  
     }  
   
   /* Add a string to the list of possible completions.  COMP is the  
      string that should be added.  If this string completely matches  
      add the string MATCH to the input after adding COMP.  The string  
      WHAT contains a discription of the kind of data that is added.  
      Use PRINT_COMPLETION to show the completions if there are  
      multiple matches.  XXX: Because of a bug in gcc it is required to  
      use __regparm__ in some cases.  */  
   
   int NESTED_FUNC_ATTR add_completion (const char *comp, const char *match,  
                                        const char *what,  
                                        void (*print_completion) (char *))  
     {  
       /* Bug in strncmp then len ==0.  */  
       if (!len || grub_strncmp (pos, comp, len) == 0)  
         {  
           numfound++;  
           
           if (numfound == 1)  
             {  
               begin = len;  
               found = grub_strdup (comp);  
               end = grub_strlen (found);  
               matchstr = (char *) match;  
             }  
           /* Multiple matches found, print the first instead of completing.  */  
           else if (numfound == 2)  
             {  
               grub_printf ("\nPossible %s are:\n", what);  
               print_completion (found);  
             }  
               
           if (numfound > 1)  
             {  
               char *s1 = found;  
               const char *s2 = comp;  
               int cnt = 0;  
               
               print_completion ((char *) comp);  
                               
               /* Find out how many characters match.  */  
               while ((cnt < end) && *s1 && *s2 && (*s1 == *s2))  
                 {  
                   s1++;  
                   s2++;  
                   cnt++;  
                 }            
               end = cnt;  
             }  
         }  
   
       return 0;  
     }  
   
   int iterate_part (const grub_partition_t p)  
     {  
       add_completion (grub_partition_get_name (p), ")", "partitions",  
                       print_partition_completion);  
       return 0;  
     }  
   
   int iterate_dir (const char *filename, int dir)  
     {  
       if (!dir)  
         add_completion (filename, " ", "files", print_simple_completion);  
       else  
         {  
           char fname[grub_strlen (filename) + 2];  
           grub_strcpy (fname, filename);  
           grub_sprintf (fname, "%s/", filename);  
           add_completion (fname, "", "files", print_simple_completion);  
         }  
       return 0;  
     }  
   
   int iterate_dev (const char *devname)  
     {  
       grub_device_t dev;  
         
       /* Complete the partition part.  */  
       dev = grub_device_open (devname);  
         
       if (dev)  
         {  
           if (dev->disk && dev->disk->has_partitions)  
             add_completion (devname, ",", "disks", print_simple_completion);  
           else  
             add_completion (devname, ")", "disks", print_simple_completion);  
         }  
   
       grub_errno = GRUB_ERR_NONE;  
       return 0;  
     }  
   
   int iterate_commands (grub_command_t cmd)  
     {  
       if (grub_command_find (cmd->name))  
         {  
           if (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE)  
             add_completion (cmd->name, " ", "commands",  
                             print_simple_completion);  
         }  
       return 0;  
     }  
     
   /* Remove blank space on the beginning of the line.  */  
   while (*pos == ' ')  
     pos++;  
   
   /* Check if the string is a command or path.  */  
   path = grub_strchr (pos, ' ');  
         
   if (!path)  
     {  
       /* Tab complete a command.  */  
       len = grub_strlen (pos);  
         
       grub_iterate_commands (iterate_commands);  
     }  
   else  
     {  
       pos = path;  
   
       /* Remove blank space on the beginning of the line.  */  
       while (*pos == ' ')  
         pos++;  
           
       /* Check if this is a completion for a device name.  */  
       if (*pos == '(' && !grub_strchr (pos, ')'))  
         {  
           /* Check if this is a device or partition.  */  
           char *partition = grub_strchr (++pos, ',');  
                           
           if (!partition)  
             {  
               /* Complete the disk part.  */  
               len = grub_strlen (pos);  
               grub_disk_dev_iterate (iterate_dev);  
               if (grub_errno)  
                 goto fail;  
             }  
           else  
             {  
               *partition = '\0';  
   
               /* Complete the partition part.  */  
               partdev = grub_device_open (pos);  
               *partition = ',';  
               grub_errno = GRUB_ERR_NONE;  
     
               if (partdev)  
                 {  
                   if (partdev->disk && partdev->disk->has_partitions)  
                     {  
                       pos = partition + 1;  
                       len = grub_strlen (pos);  
                         
                       grub_partition_iterate (partdev->disk, iterate_part);  
                       if (grub_errno)  
                         grub_errno = 0;  
                     }  
   
                   grub_device_close (partdev);  
                 }  
               else  
                 goto fail;  
             }  
         }  
       else  
         {  
           char *device = grub_file_get_device_name (pos);  
           grub_device_t dev;  
           grub_fs_t fs;  
   
           dev = grub_device_open (device);  
           if (!dev)  
             goto fail;  
                           
           fs = grub_fs_probe (dev);  
           if (grub_errno)  
             goto fail;  
   
           pos = grub_strrchr (pos, '/');  
           if (pos)  
             {  
               char *dir;  
               char *dirfile;  
               pos++;  
               len = grub_strlen (pos);  
                 
               dir = grub_strchr (path, '/');  
               if (!dir)  
                 {  
                   *restore = 0;  
                   return 0;  
                 }  
   
               dir = grub_strdup (dir);  
   
               /* Cut away the filename part.  */  
               dirfile = grub_strrchr (dir, '/');  
               dirfile[1] = '\0';  
                 
               /* Tab complete a file.  */  
               (fs->dir) (dev, dir, iterate_dir);  
               if (dev)  
                 grub_device_close (dev);  
   
               grub_free (device);  
               grub_free (dir);  
   
               if (grub_errno)  
                 goto fail;  
             }  
           else  
             {  
               found = grub_strdup ("/");  
               matchstr = "";  
               numfound = 1;  
               begin = 0;  
               end = 1;  
             }  
         }  
                       
     }  
   
   /* If more than one match is found those matches will be printed and  
      the prompt should be restored.  */  
   if (numfound > 1)  
     *restore = 1;  
   else  
     *restore = 0;  
   
   /* Return the part that matches.  */  
   if (end && found)  
     {  
       char *insert;  
       insert = grub_malloc (end - begin + 1 + sizeof (matchstr));  
       grub_strncpy (insert, found + begin, end - begin);  
       insert[end - begin] = '\0';  
       if (numfound == 1)  
         grub_strcat (insert, matchstr);  
       grub_free (found);  
   
       return insert;  
     }  
   
  fail:  
   grub_free (found);  
   grub_errno = GRUB_ERR_NONE;  
   
   return 0;  
 }  
   
136  void  void
137  grub_cmdline_run (int nested)  grub_cmdline_run (int nested)
138  {  {
# Line 607  grub_cmdline_get (const char *prompt, ch Line 309  grub_cmdline_get (const char *prompt, ch
309                  buf[lpos] = '\0';                  buf[lpos] = '\0';
310                                    
311    
312                  insert = grub_tab_complete (buf, &restore);                  insert = grub_normal_do_completion (buf, &restore);
313                  /* Restore the original string.  */                  /* Restore the original string.  */
314                  buf[lpos] = backup;                  buf[lpos] = backup;
315                                    

Legend:
Removed from v.1.15  
changed lines
  Added in v.1.16

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26