fish: Don't eat words when completing case-insensitive paths (RHBZ#582993).
[libguestfs.git] / fish / fish.c
index 32d6f9f..3cf334e 100644 (file)
@@ -28,6 +28,7 @@
 #include <assert.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <locale.h>
 
 #ifdef HAVE_LIBREADLINE
 #include <readline/readline.h>
@@ -60,7 +61,9 @@ static void script (int prompt);
 static void cmdline (char *argv[], int optind, int argc);
 static void initialize_readline (void);
 static void cleanup_readline (void);
+#ifdef HAVE_LIBREADLINE
 static void add_history_line (const char *);
+#endif
 
 /* Currently open libguestfs handle. */
 guestfs_h *g;
@@ -68,10 +71,10 @@ guestfs_h *g;
 int read_only = 0;
 int quit = 0;
 int verbose = 0;
-int echo_commands = 0;
 int remote_control_listen = 0;
 int remote_control = 0;
 int exit_on_error = 1;
+int command_num = 0;
 
 int
 launch (guestfs_h *_g)
@@ -322,7 +325,7 @@ main (int argc, char *argv[])
       exit (EXIT_SUCCESS);
 
     case 'x':
-      echo_commands = 1;
+      guestfs_set_trace (g, 1);
       break;
 
     case HELP_OPTION:
@@ -378,6 +381,8 @@ main (int argc, char *argv[])
       strcat (cmd, " -v");
     if (!guestfs_get_autosync (g))
       strcat (cmd, " -n");
+    if (guestfs_get_trace (g))
+      strcat (cmd, " -x");
 
     if (verbose)
       fprintf (stderr,
@@ -766,6 +771,15 @@ cmdline (char *argv[], int optind, int argc)
     fprintf (stderr, _("%s: empty command on command line\n"), program_name);
     exit (EXIT_FAILURE);
   }
+
+  /* Allow -cmd on the command line to mean (temporarily) override
+   * the normal exit on error (RHBZ#578407).
+   */
+  if (cmd[0] == '-') {
+    exit_on_error = 0;
+    cmd++;
+  }
+
   params = &argv[optind];
 
   /* Search for end of command list or ":" ... */
@@ -773,10 +787,12 @@ cmdline (char *argv[], int optind, int argc)
     optind++;
 
   if (optind == argc) {
-    if (issue_command (cmd, params, NULL) == -1) exit (EXIT_FAILURE);
+    if (issue_command (cmd, params, NULL) == -1 && exit_on_error)
+        exit (EXIT_FAILURE);
   } else {
     argv[optind] = NULL;
-    if (issue_command (cmd, params, NULL) == -1) exit (EXIT_FAILURE);
+    if (issue_command (cmd, params, NULL) == -1 && exit_on_error)
+      exit (EXIT_FAILURE);
     cmdline (argv, optind+1, argc);
   }
 }
@@ -789,12 +805,8 @@ issue_command (const char *cmd, char *argv[], const char *pipecmd)
   int pid = 0;
   int i, r;
 
-  if (echo_commands) {
-    printf ("%s", cmd);
-    for (i = 0; argv[i] != NULL; ++i)
-      printf (" %s", argv[i]);
-    printf ("\n");
-  }
+  /* This counts the commands issued, starting at 1. */
+  command_num++;
 
   /* For | ... commands.  Annoyingly we can't use popen(3) here. */
   if (pipecmd) {
@@ -1072,6 +1084,21 @@ display_builtin_command (const char *cmd)
              cmd);
 }
 
+/* This is printed when the user types in an unknown command for the
+ * first command issued.  A common case is the user doing:
+ *   guestfish disk.img
+ * expecting guestfish to open 'disk.img' (in fact, this tried to
+ * run a command 'disk.img').
+ */
+void
+extended_help_message (void)
+{
+  fprintf (stderr,
+           _("Did you mean to open a disk image?  guestfish -a disk.img\n"
+             "For a list of commands:             guestfish -h\n"
+             "For complete documentation:         man guestfish\n"));
+}
+
 void
 free_strings (char **argv)
 {
@@ -1287,6 +1314,13 @@ initialize_readline (void)
 
   rl_readline_name = "guestfish";
   rl_attempted_completion_function = do_completion;
+
+  /* Note that .inputrc (or /etc/inputrc) is not read until the first
+   * call the readline(), which happens later.  Therefore, these
+   * provide default values which can be overridden by the user if
+   * they wish.
+   */
+  (void) rl_variable_bind ("completion-ignore-case", "on");
 #endif
 }
 
@@ -1304,19 +1338,23 @@ cleanup_readline (void)
     }
     close (fd);
 
+#ifdef HAVE_APPEND_HISTORY
     (void) append_history (nr_history_lines, histfile);
+#else
+    (void) write_history (histfile);
+#endif
   }
 #endif
 }
 
+#ifdef HAVE_LIBREADLINE
 static void
 add_history_line (const char *line)
 {
-#ifdef HAVE_LIBREADLINE
   add_history (line);
   nr_history_lines++;
-#endif
 }
+#endif
 
 int
 xwrite (int fd, const void *v_buf, size_t len)