summaryrefslogtreecommitdiffstats
path: root/fish
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2009-04-14 15:52:04 +0100
committerRichard Jones <rjones@redhat.com>2009-04-14 15:52:04 +0100
commitd268e64fe76944dc042e7ec68a65e59a6cff16ce (patch)
tree7ec8cfe1d097c1eb17f37d08e1ae5baf636a8b67 /fish
parent374af1d1c85580a7768967bf2f199f10182b011e (diff)
downloadlibguestfs-d268e64fe76944dc042e7ec68a65e59a6cff16ce.tar.gz
libguestfs-d268e64fe76944dc042e7ec68a65e59a6cff16ce.tar.xz
libguestfs-d268e64fe76944dc042e7ec68a65e59a6cff16ce.zip
Added bindings for GNU readline.
Diffstat (limited to 'fish')
-rw-r--r--fish/Makefile.am3
-rw-r--r--fish/completion.c142
-rw-r--r--fish/fish.c111
-rw-r--r--fish/fish.h3
4 files changed, 251 insertions, 8 deletions
diff --git a/fish/Makefile.am b/fish/Makefile.am
index b9c51b88..11598b8a 100644
--- a/fish/Makefile.am
+++ b/fish/Makefile.am
@@ -19,11 +19,12 @@ bin_PROGRAMS = guestfish
guestfish_SOURCES = \
cmds.c \
+ completion.c \
fish.c \
fish.h
guestfish_CFLAGS = \
-I$(top_builddir)/src -Wall \
-DGUESTFS_DEFAULT_PATH='"$(libdir)/guestfs"'
-guestfish_LDADD = $(top_builddir)/src/libguestfs.la
+guestfish_LDADD = $(top_builddir)/src/libguestfs.la $(LIBREADLINE)
CLEANFILES = *~
diff --git a/fish/completion.c b/fish/completion.c
new file mode 100644
index 00000000..150b1aaa
--- /dev/null
+++ b/fish/completion.c
@@ -0,0 +1,142 @@
+/* libguestfs generated file
+ * WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.
+ * ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_LIBREADLINE
+#include <readline/readline.h>
+#endif
+
+#include "fish.h"
+
+#ifdef HAVE_LIBREADLINE
+
+static const char *commands[] = {
+ "add",
+ "add-cdrom",
+ "add-drive",
+ "aug-close",
+ "aug-defnode",
+ "aug-defvar",
+ "aug-get",
+ "aug-init",
+ "aug-insert",
+ "aug-load",
+ "aug-ls",
+ "aug-match",
+ "aug-mv",
+ "aug-rm",
+ "aug-save",
+ "aug-set",
+ "autosync",
+ "cat",
+ "cdrom",
+ "chmod",
+ "chown",
+ "command",
+ "command-lines",
+ "config",
+ "exists",
+ "file",
+ "get-autosync",
+ "get-path",
+ "get-verbose",
+ "is-dir",
+ "is-file",
+ "kill-subprocess",
+ "launch",
+ "list-devices",
+ "list-partitions",
+ "ll",
+ "ls",
+ "lvcreate",
+ "lvm-remove-all",
+ "lvs",
+ "lvs-full",
+ "mkdir",
+ "mkdir-p",
+ "mkfs",
+ "mount",
+ "mounts",
+ "path",
+ "pvcreate",
+ "pvs",
+ "pvs-full",
+ "read-lines",
+ "rm",
+ "rm-rf",
+ "rmdir",
+ "run",
+ "set-autosync",
+ "set-path",
+ "set-verbose",
+ "sfdisk",
+ "sync",
+ "touch",
+ "umount",
+ "umount-all",
+ "unmount",
+ "unmount-all",
+ "verbose",
+ "vgcreate",
+ "vgs",
+ "vgs-full",
+ "write-file",
+ NULL
+};
+
+static char *
+generator (const char *text, int state)
+{
+ static int index, len;
+ const char *name;
+
+ if (!state) {
+ index = 0;
+ len = strlen (text);
+ }
+
+ while ((name = commands[index]) != NULL) {
+ index++;
+ if (strncasecmp (name, text, len) == 0)
+ return strdup (name);
+ }
+
+ return NULL;
+}
+
+#endif /* HAVE_LIBREADLINE */
+
+char **do_completion (const char *text, int start, int end)
+{
+ char **matches = NULL;
+
+#ifdef HAVE_LIBREADLINE
+ if (start == 0)
+ matches = rl_completion_matches (text, generator);
+#endif
+
+ return matches;
+}
diff --git a/fish/fish.c b/fish/fish.c
index b0d91c79..51a3d50d 100644
--- a/fish/fish.c
+++ b/fish/fish.c
@@ -29,6 +29,11 @@
#include <inttypes.h>
#include <assert.h>
+#ifdef HAVE_LIBREADLINE
+#include <readline/readline.h>
+#include <readline/history.h>
+#endif
+
#include <guestfs.h>
#include "fish.h"
@@ -46,6 +51,9 @@ static void script (int prompt);
static void cmdline (char *argv[], int optind, int argc);
static int issue_command (const char *cmd, char *argv[]);
static int parse_size (const char *str, off_t *size_rtn);
+static void initialize_readline (void);
+static void cleanup_readline (void);
+static void add_history_line (const char *);
/* Currently open libguestfs handle. */
guestfs_h *g;
@@ -114,6 +122,8 @@ main (int argc, char *argv[])
char *p;
int c;
+ initialize_readline ();
+
/* guestfs_create is meant to be a lightweight operation, so
* it's OK to do it early here.
*/
@@ -208,6 +218,8 @@ main (int argc, char *argv[])
else
cmdline (argv, optind, argc);
+ cleanup_readline ();
+
exit (0);
}
@@ -254,13 +266,50 @@ shell_script (void)
script (0);
}
+#define FISH "><fs> "
+
+static char *line_read = NULL;
+
+static char *
+rl_gets (int prompt)
+{
+#ifdef HAVE_LIBREADLINE
+
+ if (line_read) {
+ free (line_read);
+ line_read = NULL;
+ }
+
+ line_read = readline (prompt ? FISH : "");
+
+ if (prompt && line_read && *line_read)
+ add_history_line (line_read);
+
+#else /* !HAVE_LIBREADLINE */
+
+ static char buf[8192];
+ int len;
+
+ if (prompt) printf (FISH);
+ line_read = fgets (buf, sizeof buf, stdin);
+
+ if (line_read) {
+ len = strlen (line_read);
+ if (len > 0 && buf[len-1] == '\n') buf[len-1] = '\0';
+ }
+
+#endif /* !HAVE_LIBREADLINE */
+
+ return line_read;
+}
+
static void
script (int prompt)
{
- char buf[8192];
+ char *buf;
char *cmd;
char *argv[64];
- int len, i;
+ int i;
if (prompt)
printf ("\n"
@@ -272,15 +321,12 @@ script (int prompt)
"\n");
while (!quit) {
- if (prompt) printf ("><fs> ");
- if (fgets (buf, sizeof buf, stdin) == NULL) {
+ buf = rl_gets (prompt);
+ if (!buf) {
quit = 1;
break;
}
- len = strlen (buf);
- if (len > 0 && buf[len-1] == '\n') buf[len-1] = '\0';
-
/* Split the buffer up at whitespace. */
cmd = strtok (buf, " \t");
if (cmd == NULL)
@@ -544,3 +590,54 @@ parse_string_list (const char *str)
return argv;
}
+
+#ifdef HAVE_LIBREADLINE
+static char histfile[1024];
+static int nr_history_lines = 0;
+#endif
+
+static void
+initialize_readline (void)
+{
+#ifdef HAVE_LIBREADLINE
+ const char *home;
+
+ home = getenv ("HOME");
+ if (home) {
+ snprintf (histfile, sizeof histfile, "%s/.guestfish", home);
+ using_history ();
+ (void) read_history (histfile);
+ }
+
+ rl_readline_name = "guestfish";
+ rl_attempted_completion_function = do_completion;
+#endif
+}
+
+static void
+cleanup_readline (void)
+{
+#ifdef HAVE_LIBREADLINE
+ int fd;
+
+ if (histfile[0] != '\0') {
+ fd = open (histfile, O_WRONLY|O_CREAT, 0644);
+ if (fd == -1) {
+ perror (histfile);
+ return;
+ }
+ close (fd);
+
+ (void) append_history (nr_history_lines, histfile);
+ }
+#endif
+}
+
+static void
+add_history_line (const char *line)
+{
+#ifdef HAVE_LIBREADLINE
+ add_history (line);
+ nr_history_lines++;
+#endif
+}
diff --git a/fish/fish.h b/fish/fish.h
index 3997d6d4..86e5e357 100644
--- a/fish/fish.h
+++ b/fish/fish.h
@@ -40,4 +40,7 @@ extern void list_commands (void);
extern void display_command (const char *cmd);
extern int run_action (const char *cmd, int argc, char *argv[]);
+/* in completion.c (auto-generated) */
+extern char **do_completion (const char *text, int start, int end);
+
#endif /* FISH_H */