mirror of https://github.com/djcb/mu.git
server: support readline history / persistence
When using readline, remember the last 50 commands; persist.
This commit is contained in:
parent
20ce7b7066
commit
8d6d151090
|
@ -39,6 +39,8 @@ init_paths_xdg ()
|
||||||
{
|
{
|
||||||
RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, g_get_user_cache_dir() +
|
RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, g_get_user_cache_dir() +
|
||||||
Sepa + Mu + Sepa + XapianDir);
|
Sepa + Mu + Sepa + XapianDir);
|
||||||
|
RuntimePaths.emplace(MU_RUNTIME_PATH_CACHE, g_get_user_cache_dir() +
|
||||||
|
Sepa + Mu);
|
||||||
RuntimePaths.emplace(MU_RUNTIME_PATH_MIMECACHE, g_get_user_cache_dir() +
|
RuntimePaths.emplace(MU_RUNTIME_PATH_MIMECACHE, g_get_user_cache_dir() +
|
||||||
Sepa + Mu + Sepa + PartsDir);
|
Sepa + Mu + Sepa + PartsDir);
|
||||||
RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, g_get_user_cache_dir() +
|
RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, g_get_user_cache_dir() +
|
||||||
|
@ -51,6 +53,7 @@ static void
|
||||||
init_paths_muhome (const char *muhome)
|
init_paths_muhome (const char *muhome)
|
||||||
{
|
{
|
||||||
RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, muhome + Sepa + XapianDir);
|
RuntimePaths.emplace(MU_RUNTIME_PATH_XAPIANDB, muhome + Sepa + XapianDir);
|
||||||
|
RuntimePaths.emplace(MU_RUNTIME_PATH_CACHE, muhome);
|
||||||
RuntimePaths.emplace(MU_RUNTIME_PATH_MIMECACHE, muhome + Sepa + PartsDir);
|
RuntimePaths.emplace(MU_RUNTIME_PATH_MIMECACHE, muhome + Sepa + PartsDir);
|
||||||
RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, muhome + Sepa + LogDir);
|
RuntimePaths.emplace(MU_RUNTIME_PATH_LOGDIR, muhome + Sepa + LogDir);
|
||||||
RuntimePaths.emplace(MU_RUNTIME_PATH_BOOKMARKS, muhome + Sepa + Bookmarks);
|
RuntimePaths.emplace(MU_RUNTIME_PATH_BOOKMARKS, muhome + Sepa + Bookmarks);
|
||||||
|
|
|
@ -47,6 +47,7 @@ void mu_runtime_uninit (void);
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MU_RUNTIME_PATH_XAPIANDB, /* mu xapian db path */
|
MU_RUNTIME_PATH_XAPIANDB, /* mu xapian db path */
|
||||||
MU_RUNTIME_PATH_BOOKMARKS, /* mu bookmarks file path */
|
MU_RUNTIME_PATH_BOOKMARKS, /* mu bookmarks file path */
|
||||||
|
MU_RUNTIME_PATH_CACHE, /* mu cache path for attachments etc. */
|
||||||
MU_RUNTIME_PATH_MIMECACHE, /* mu cache path for attachments etc. */
|
MU_RUNTIME_PATH_MIMECACHE, /* mu cache path for attachments etc. */
|
||||||
MU_RUNTIME_PATH_LOGDIR, /* mu path for log files */
|
MU_RUNTIME_PATH_LOGDIR, /* mu path for log files */
|
||||||
|
|
||||||
|
@ -59,7 +60,7 @@ typedef enum {
|
||||||
* @return ma string which should be not be modified/freed, or NULL in
|
* @return ma string which should be not be modified/freed, or NULL in
|
||||||
* case of error.
|
* case of error.
|
||||||
*/
|
*/
|
||||||
const char* mu_runtime_path (MuRuntimePath path);
|
const char* mu_runtime_path (MuRuntimePath path);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -1279,35 +1279,68 @@ make_command_map (Context& context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static std::string
|
struct Readline {
|
||||||
read_line (Context& context)
|
Readline (const std::string& histpath, size_t max_lines);
|
||||||
{
|
~Readline();
|
||||||
// if we don't have readline, use the simple version.
|
std::string read_line(bool& do_quit);
|
||||||
#ifndef HAVE_LIBREADLINE
|
void save_line(const std::string& line);
|
||||||
std::cout << ";; mu> ";
|
std::string histpath_;
|
||||||
std::string line;
|
size_t max_lines_{0};
|
||||||
if (!std::getline(std::cin, line))
|
};
|
||||||
context.do_quit = true;
|
|
||||||
return line;
|
|
||||||
#else /*!HAVE_LIBREADLINE*/
|
|
||||||
|
|
||||||
|
/// Wrapper around readline (if available) or nothing otherwise.
|
||||||
|
#if defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY) && defined(bla)
|
||||||
|
Readline::Readline (const std::string& histpath, size_t max_lines):
|
||||||
|
histpath_{histpath}, max_lines_{max_lines}
|
||||||
|
{
|
||||||
|
rl_bind_key('\t', rl_insert); // default (filenames) is not useful
|
||||||
|
using_history();
|
||||||
|
read_history (histpath_.c_str());
|
||||||
|
|
||||||
|
if (max_lines_ > 0)
|
||||||
|
stifle_history(max_lines_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Readline::~Readline () {
|
||||||
|
write_history(histpath_.c_str());
|
||||||
|
if (max_lines_ > 0)
|
||||||
|
history_truncate_file (histpath_.c_str(), max_lines_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Readline::read_line(bool& do_quit)
|
||||||
|
{
|
||||||
auto buf = readline(";; mu% ");
|
auto buf = readline(";; mu% ");
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
context.do_quit = true;
|
do_quit = true;
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
#ifdef HAVE_READLINE_HISTORY
|
|
||||||
else if (buf[0])
|
|
||||||
add_history(buf);
|
|
||||||
#endif /*HAVE_LIBREADLINE_HISTORY*/
|
|
||||||
|
|
||||||
std::string line{buf};
|
std::string line{buf};
|
||||||
::free (buf);
|
::free (buf);
|
||||||
|
|
||||||
return line;
|
return line;
|
||||||
#endif /*HAVE_LIBREADLINE*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Readline::save_line(const std::string& line)
|
||||||
|
{
|
||||||
|
add_history(line.c_str());
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Readline::Readline (const std::string& histpath, size_t max_lines) {}
|
||||||
|
Readline::~Readline() {}
|
||||||
|
void Readline::save_line(const std::string& line) {}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
Readline::read_line(bool& do_quit)
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
std::cout << ";; mu> ";
|
||||||
|
if (!std::getline(std::cin, line))
|
||||||
|
do_quit = true;
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
#endif // ! defined(HAVE_LIBREADLINE) && defined(HAVE_READLINE_HISTORY)
|
||||||
|
|
||||||
|
|
||||||
MuError
|
MuError
|
||||||
mu_cmd_server (MuConfig *opts, GError **err) try
|
mu_cmd_server (MuConfig *opts, GError **err) try
|
||||||
|
@ -1322,6 +1355,9 @@ mu_cmd_server (MuConfig *opts, GError **err) try
|
||||||
Context context{opts};
|
Context context{opts};
|
||||||
context.command_map = make_command_map (context);
|
context.command_map = make_command_map (context);
|
||||||
|
|
||||||
|
const auto histpath{std::string{mu_runtime_path(MU_RUNTIME_PATH_CACHE)} + "/history"};
|
||||||
|
Readline readline(histpath, 50);
|
||||||
|
|
||||||
install_sig_handler();
|
install_sig_handler();
|
||||||
std::cout << ";; Welcome to the " << PACKAGE_STRING << " command-server\n"
|
std::cout << ";; Welcome to the " << PACKAGE_STRING << " command-server\n"
|
||||||
<< ";; Use (help) to get a list of commands, (quit) to quit.\n";
|
<< ";; Use (help) to get a list of commands, (quit) to quit.\n";
|
||||||
|
@ -1330,11 +1366,14 @@ mu_cmd_server (MuConfig *opts, GError **err) try
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
try {
|
try {
|
||||||
line = read_line(context);
|
line = readline.read_line(context.do_quit);
|
||||||
if (line.find_first_not_of(" \t") == std::string::npos)
|
if (line.find_first_not_of(" \t") == std::string::npos)
|
||||||
continue; // skip whitespace-only lines
|
continue; // skip whitespace-only lines
|
||||||
|
|
||||||
invoke(context.command_map, Sexp::parse(line));
|
auto call{Sexp::parse(line)};
|
||||||
|
readline.save_line(line);
|
||||||
|
|
||||||
|
invoke(context.command_map, call);
|
||||||
|
|
||||||
} catch (const Error& er) {
|
} catch (const Error& er) {
|
||||||
std::cerr << ";; error: " << er.what() << "\n";
|
std::cerr << ";; error: " << er.what() << "\n";
|
||||||
|
@ -1343,7 +1382,14 @@ mu_cmd_server (MuConfig *opts, GError **err) try
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_READLINE_HISTORY
|
||||||
|
const auto history{std::string{mu_runtime_path(MU_RUNTIME_PATH_CACHE)} + "/history"};
|
||||||
|
read_history (history.c_str());
|
||||||
|
stifle_history(20); // remember last 20.
|
||||||
|
#endif /*HAVE_READLINE_HISTORY*/
|
||||||
|
|
||||||
return MU_OK;
|
return MU_OK;
|
||||||
|
|
||||||
} catch (const Error& er) {
|
} catch (const Error& er) {
|
||||||
g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", er.what());
|
g_set_error(err, MU_ERROR_DOMAIN, MU_ERROR, "%s", er.what());
|
||||||
return MU_ERROR;
|
return MU_ERROR;
|
||||||
|
|
Loading…
Reference in New Issue