2016-09-01 16:42:28 +00:00
|
|
|
#ifdef CS_REPL_USE_READLINE
|
|
|
|
#ifndef CS_REPL_HAS_EDIT
|
|
|
|
#define CS_REPL_HAS_EDIT
|
|
|
|
/* use the GNU readline library */
|
|
|
|
|
2016-09-02 21:15:05 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2016-09-01 16:42:28 +00:00
|
|
|
#include <ostd/string.hh>
|
|
|
|
#include <ostd/maybe.hh>
|
|
|
|
|
|
|
|
#include <readline/readline.h>
|
|
|
|
#include <readline/history.h>
|
|
|
|
|
2016-09-11 21:33:02 +00:00
|
|
|
static CsState *rd_cs = nullptr;
|
|
|
|
|
2016-09-02 21:15:05 +00:00
|
|
|
static char *ln_complete_list(char const *buf, int state) {
|
|
|
|
static ostd::ConstCharRange cmd;
|
|
|
|
static ostd::PointerRange<CsIdent *> itr;
|
|
|
|
|
|
|
|
if (!state) {
|
|
|
|
cmd = get_complete_cmd(buf);
|
2016-09-12 18:04:59 +00:00
|
|
|
itr = rd_cs->get_idents();
|
2016-09-02 21:15:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (; !itr.empty(); itr.pop_front()) {
|
|
|
|
CsIdent *id = itr.front();
|
|
|
|
if (!id->is_command()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ostd::ConstCharRange idname = id->get_name();
|
|
|
|
if (idname.size() <= cmd.size()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (idname.slice(0, cmd.size()) == cmd) {
|
|
|
|
itr.pop_front();
|
|
|
|
return strdup(idname.data());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char **ln_complete(char const *buf, int, int) {
|
|
|
|
rl_attempted_completion_over = 1;
|
|
|
|
return rl_completion_matches(buf, ln_complete_list);
|
|
|
|
}
|
|
|
|
|
2016-09-02 23:49:31 +00:00
|
|
|
void ln_hint() {
|
2016-09-11 21:33:02 +00:00
|
|
|
CsCommand *cmd = get_hint_cmd(*rd_cs, rl_line_buffer);
|
2016-09-02 23:49:31 +00:00
|
|
|
if (!cmd) {
|
|
|
|
rl_redisplay();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ostd::String old = rl_line_buffer;
|
|
|
|
ostd::String args = old;
|
|
|
|
args += " [";
|
|
|
|
fill_cmd_args(args, cmd->get_args());
|
|
|
|
args += "] ";
|
|
|
|
rl_extend_line_buffer(args.size());
|
|
|
|
rl_replace_line(args.data(), 0);
|
|
|
|
rl_redisplay();
|
|
|
|
rl_replace_line(old.data(), 0);
|
|
|
|
}
|
|
|
|
|
2016-09-11 21:33:02 +00:00
|
|
|
static void init_lineedit(CsState &cs, ostd::ConstCharRange) {
|
|
|
|
rd_cs = &cs;
|
2016-09-02 21:15:05 +00:00
|
|
|
rl_attempted_completion_function = ln_complete;
|
2016-09-02 23:49:31 +00:00
|
|
|
rl_redisplay_function = ln_hint;
|
2016-09-01 16:42:28 +00:00
|
|
|
}
|
|
|
|
|
2016-09-11 21:33:02 +00:00
|
|
|
static ostd::Maybe<ostd::String> read_line(CsState &, CsSvar *pr) {
|
2016-09-01 16:42:28 +00:00
|
|
|
auto line = readline(pr->get_value().data());
|
|
|
|
if (!line) {
|
|
|
|
return ostd::String();
|
|
|
|
}
|
|
|
|
ostd::String ret = line;
|
|
|
|
free(line);
|
2017-01-25 00:57:33 +00:00
|
|
|
return std::move(ret);
|
2016-09-01 16:42:28 +00:00
|
|
|
}
|
|
|
|
|
2016-09-11 21:33:02 +00:00
|
|
|
static void add_history(CsState &, ostd::ConstCharRange line) {
|
2016-09-01 16:42:28 +00:00
|
|
|
/* backed by ostd::String so it's terminated */
|
|
|
|
add_history(line.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|