Shell: added command line editing with history (#232374);
authorMartin Vidner <mvidner@suse.cz>
Mon, 5 Feb 2007 16:03:44 +0000 (16:03 +0000)
committerMartin Vidner <mvidner@suse.cz>
Mon, 5 Feb 2007 16:03:44 +0000 (16:03 +0000)
exit on EOF (#230211, #235709).

doc/zypper.8
package/zypper.changes
src/Makefile.am
src/zypper.cc

index 3d9a4d7..a369118 100644 (file)
@@ -20,7 +20,7 @@ zypper provides a number of \fBcommands\fR. Each command accepts the option flag
 .TP
 .B shell (sh)
 Starts a shell for entering multiple commands in one session.
-(NEW, beware of bugs!)
+End it by "exit", "quit", or Ctrl-D.
 
 .LP 
 .B Package Management Commands
@@ -253,6 +253,9 @@ Operates on a different root directory.
 .TP
 .B /var/lib/zypp/cache
 Directory for storing metadata contained in installation sources.
+.TP
+.B ~/.zypper_history
+Command history for the shell.
 
 .SH "EXIT CODES"
 .LP
index f1c3c71..7edf828 100644 (file)
@@ -1,4 +1,10 @@
 -------------------------------------------------------------------
+Mon Feb  5 17:00:25 CET 2007 - mvidner@suse.cz
+
+- Shell: added command line editing with history (#232374);
+  exit on EOF (#230211, #235709).
+
+-------------------------------------------------------------------
 Fri Feb  2 13:29:27 CET 2007 - jkupec@suse.cz
 
 - Non-interactive mode turns on --skip-interactive as well
index 2c6858d..e371876 100644 (file)
@@ -61,7 +61,7 @@ zypper_SOURCES =      zypper.cc zmart-sources.cc zmart-misc.cc \
        zypper-getopt.h \
        zypper-getopt.cc \
        zmart.h
-zypper_LDADD = $(ZYPP_LIBS) -lboost_regex
+zypper_LDADD = $(ZYPP_LIBS) -lboost_regex -lreadline
 
 if BUILD_CHECKPATCHES
 zypp_checkpatches_SOURCES =    zypp-checkpatches.cc zmart-sources.cc \
index ff72a26..9c1f930 100644 (file)
@@ -15,6 +15,8 @@
 #include <iterator>
 
 #include <unistd.h>
+#include <readline/readline.h>
+#include <readline/history.h>
 
 #include "zmart.h"
 #include "zmart-sources.h"
@@ -466,7 +468,8 @@ int one_command(const string& command, int argc, char **argv)
       );
   }
   else if (!command.empty()) { // empty command is treated earlier
-    cerr << _("Unknown command") << " '" << command << "'." << endl << endl;
+    if (command != "help")     // #235709
+      cerr << _("Unknown command") << " '" << command << "'." << endl << endl;
     cerr << help_commands;
     return ZYPPER_EXIT_ERR_SYNTAX;
   }
@@ -952,13 +955,51 @@ int safe_one_command(const string& command, int argc, char **argv)
   return ret;
 }
 
+// Read a string. "\004" (^D) on EOF.
+string readline_getline ()
+{
+  // A static variable for holding the line.
+  static char *line_read = NULL;
+
+  /* If the buffer has already been allocated,
+     return the memory to the free pool. */
+  if (line_read) {
+    free (line_read);
+    line_read = NULL;
+  }
+
+  /* Get a line from the user. */
+  line_read = readline ("zypper> ");
+
+  /* If the line has any text in it,
+     save it on the history. */
+  if (line_read && *line_read)
+    add_history (line_read);
+
+  if (line_read)
+    return line_read;
+  else
+    return "\004";
+}
+
 void command_shell ()
 {
+  string histfile;
+  try {
+    Pathname p (getenv ("HOME"));
+    p /= ".zypper_history";
+    histfile = p.asString ();
+  } catch (...) {
+    // no history
+  }
+  using_history ();
+  if (!histfile.empty ())
+    read_history (histfile.c_str ());
+
   bool loop = true;
   while (loop) {
     // read a line
-    cerr << "zypper> " << flush;
-    string line = zypp::str::getline (cin);
+    string line = readline_getline ();
     cerr_vv << "Got: " << line << endl;
     // reset optind etc
     optind = 0;
@@ -968,13 +1009,15 @@ void command_shell ()
     char **sh_argv = args.argv ();
 
     string command = sh_argv[0]? sh_argv[0]: "";
-    // TODO check empty command
 
-    if (command == "exit")
+    if (command == "exit" || command == "quit" || command == "\004")
       loop = false;
     else
       safe_one_command (command, sh_argc, sh_argv);
   }
+
+  if (!histfile.empty ())
+    write_history (histfile.c_str ());
 }
 
 int main(int argc, char **argv)