This patch introduces a way for completers to retrieve the
current vshControl object by using the vshGetCompleterCtl()
macro. When readline is enabled, the main method stores the
vshControl pointer in a variable that is file-global to virsh.c.
Then, that pointer can be retrieved by the _vshGetCompleterCtl()
function, which is mapped to by the macro. If readline is not
enabled, the macro simply maps to NULL.
---
tools/virsh.c | 28 +++++++++++++++++++++++++---
tools/virsh.h | 8 ++++++++
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 2ac0875..972cc5d 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -95,6 +95,15 @@ static char *progname;
static const vshCmdGrp cmdGroups[];
+#if WITH_READLINE
+static vshControl *completer_ctl;
+
+vshControl *
+_vshGetCompleterCtl(void) {
+ return completer_ctl;
+}
+#endif
+
/* Bypass header poison */
#undef strdup
@@ -3005,7 +3014,7 @@ vshReadlineCommandGenerator(const char *text, int state)
}
static char *
-vshDelegateToCustomCompleter(const vshCmdOptDef *opt,
+vshDelegateToCustomCompleter(const vshCmdOptDef *opt, bool reconnect,
const char *text, int state)
{
static int list_index;
@@ -3018,6 +3027,10 @@ vshDelegateToCustomCompleter(const vshCmdOptDef *opt,
return NULL;
if (opt->completer) {
+ vshControl *ctl = completer_ctl;
+ if ((!ctl->conn || disconnected) && reconnect)
+ vshReconnect(ctl);
+
list_index = 0;
completions = opt->completer(opt->completer_flags);
}
@@ -3131,7 +3144,9 @@ vshReadlineOptionsGenerator(const char *text, int state)
return NULL;
if (waiting_for_flag_arg) {
- char* res = vshDelegateToCustomCompleter(curr_opt, text, substate);
+ bool may_connect = !(cmd->flags & VSH_CMD_FLAG_NOCONNECT);
+ char* res = vshDelegateToCustomCompleter(curr_opt, may_connect,
+ text, substate);
substate++;
/* if we're in a flag's argument, we don't
* want to show other flags */
@@ -3159,7 +3174,9 @@ vshReadlineOptionsGenerator(const char *text, int state)
/* we don't need to ignore args without custom completers,
* since vshDelegateToCustomCompleter will do this for us */
- res = vshDelegateToCustomCompleter(opt, text, substate);
+ bool may_connect = !(cmd->flags & VSH_CMD_FLAG_NOCONNECT);
+ res = vshDelegateToCustomCompleter(opt, may_connect,
+ text, substate);
substate++;
if (res) {
return res;
@@ -3801,9 +3818,14 @@ int
main(int argc, char **argv)
{
vshControl _ctl, *ctl = &_ctl;
+
const char *defaultConn;
bool ret = true;
+#if WITH_READLINE
+ completer_ctl = ctl;
+#endif
+
memset(ctl, 0, sizeof(vshControl));
ctl->imode = true; /* default is interactive mode */
ctl->log_fd = -1; /* Initialize log file descriptor */
diff --git a/tools/virsh.h b/tools/virsh.h
index 113d1e5..a8977ab 100644
--- a/tools/virsh.h
+++ b/tools/virsh.h
@@ -180,6 +180,14 @@ struct _vshCmdOptDef {
* readline file completer */
# define VSH_COMPLETE_AS_FILE (1 << 8)
+vshControl * _vshGetCompleterCtl(void);
+
+#if WITH_READLINE
+# define vshGetCompleterCtl() _vshGetCompleterCtl()
+#else
+# define vshGetCompleterCtl() NULL
+#endif
+
/*
* vshCmdOpt - command options
*
--
1.8.3.2