summaryrefslogtreecommitdiff
path: root/lib/utils
diff options
context:
space:
mode:
authorDirk-Jan C. Binnema <djcb@djcbsoftware.nl>2020-05-25 18:32:10 +0300
committerDirk-Jan C. Binnema <djcb@djcbsoftware.nl>2020-05-25 18:34:42 +0300
commitb60cfc7df28faab8d51a4832e650710e8a45e1e9 (patch)
treeb84d620c3fc573895b31abd0a6a139cfdce1e6f9 /lib/utils
parent57d38aa7070ad9cb108bfffb1cf17f99f79c1322 (diff)
mu-server: restore readline-support
Restore readline support for `mu server' (but _only_ when readline is found and when in tty mode)
Diffstat (limited to 'lib/utils')
-rw-r--r--lib/utils/Makefile.am2
-rw-r--r--lib/utils/mu-readline.cc131
-rw-r--r--lib/utils/mu-readline.hh54
3 files changed, 187 insertions, 0 deletions
diff --git a/lib/utils/Makefile.am b/lib/utils/Makefile.am
index 5a638ac..9faf5fe 100644
--- a/lib/utils/Makefile.am
+++ b/lib/utils/Makefile.am
@@ -53,6 +53,8 @@ libmu_utils_la_SOURCES= \
mu-log.h \
mu-command-parser.cc \
mu-command-parser.hh \
+ mu-readline.cc \
+ mu-readline.hh \
mu-sexp-parser.cc \
mu-sexp-parser.hh \
mu-str.c \
diff --git a/lib/utils/mu-readline.cc b/lib/utils/mu-readline.cc
new file mode 100644
index 0000000..2fcd224
--- /dev/null
+++ b/lib/utils/mu-readline.cc
@@ -0,0 +1,131 @@
+/*
+** Copyright (C) 2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
+**
+** 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 3, 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 "mu-readline.hh"
+#include "config.h"
+
+#include <iostream>
+#include <unistd.h>
+#include <string>
+#include <glib.h>
+#include <glib/gprintf.h>
+
+#ifdef HAVE_LIBREADLINE
+# if defined(HAVE_READLINE_READLINE_H)
+# include <readline/readline.h>
+# elif defined(HAVE_READLINE_H)
+# include <readline.h>
+# else /* !defined(HAVE_READLINE_H) */
+extern char *readline ();
+# endif /* !defined(HAVE_READLINE_H) */
+char *cmdline = NULL;
+#else /* !defined(HAVE_READLINE_READLINE_H) */
+/* no readline */
+#endif /* HAVE_LIBREADLINE */
+
+#ifdef HAVE_READLINE_HISTORY
+# if defined(HAVE_READLINE_HISTORY_H)
+# include <readline/history.h>
+# elif defined(HAVE_HISTORY_H)
+# include <history.h>
+# else /* !defined(HAVE_HISTORY_H) */
+extern void add_history ();
+extern int write_history ();
+extern int read_history ();
+# endif /* defined(HAVE_READLINE_HISTORY_H) */
+/* no history */
+#endif /* HAVE_READLINE_HISTORY */
+
+
+#if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY)
+#define HAVE_READLINE (1)
+#else
+#define HAVE_READLINE (0)
+#endif
+
+using namespace Mu;
+
+static bool is_a_tty{};
+static std::string hist_path;
+static size_t max_lines{};
+
+void
+Mu::setup_readline (const std::string& histpath, size_t maxlines)
+{
+ is_a_tty = !!::isatty(::fileno(stdout));
+ hist_path = histpath;
+ max_lines = maxlines;
+
+#if HAVE_READLINE
+ rl_bind_key('\t', rl_insert); // default (filenames) is not useful
+ using_history();
+ read_history(hist_path.c_str());
+
+ if (max_lines > 0)
+ stifle_history(max_lines);
+#endif /*HAVE_READLINE*/
+}
+
+
+void
+Mu::shutdown_readline ()
+{
+#if HAVE_READLINE
+ if (!is_a_tty)
+ return;
+
+ write_history(hist_path.c_str());
+ if (max_lines > 0)
+ history_truncate_file (hist_path.c_str(), max_lines);
+#endif /*HAVE_READLINE*/
+}
+
+
+std::string
+Mu::read_line(bool& do_quit)
+{
+#if HAVE_READLINE
+ if (is_a_tty) {
+ auto buf = readline(";; mu% ");
+ if (!buf) {
+ do_quit = true;
+ return {};
+ }
+ std::string line{buf};
+ ::free(buf);
+ return line;
+ }
+#endif /*HAVE_READLINE*/
+
+ std::string line;
+ std::cout << ";; mu> ";
+ if (!std::getline(std::cin, line))
+ do_quit = true;
+
+ return line;
+}
+
+
+void
+Mu::save_line(const std::string& line) {
+#if HAVE_READLINE
+ if (is_a_tty)
+ add_history(line.c_str());
+#endif /*HAVE_READLINE*/
+}
diff --git a/lib/utils/mu-readline.hh b/lib/utils/mu-readline.hh
new file mode 100644
index 0000000..f892f28
--- /dev/null
+++ b/lib/utils/mu-readline.hh
@@ -0,0 +1,54 @@
+/*
+** Copyright (C) 2020 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
+**
+** 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 3, 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 <string>
+
+namespace Mu {
+
+/**
+ * Setup readline when available & on tty.
+ *
+ * @param histpath path to the history file
+ * @param max_lines maximum number of history to save
+ */
+void setup_readline(const std::string &histpath, size_t max_lines);
+
+/**
+ * Shutdown readline
+*
+ */
+void shutdown_readline();
+
+
+/**
+ * Read a command line
+ *
+ * @param do_quit recceives whether we should quit.
+ *
+ * @return the string read or empty
+ */
+std::string read_line(bool &do_quit);
+
+/**
+ * Save a line to history (or do nothing when readline is not active)
+ *
+ * @param line a line.
+ */
+void save_line(const std::string &line);
+
+} // namespace Mu