From 94357f11bcab186bbdbb291cdda0f7acf61165e9 Mon Sep 17 00:00:00 2001 From: Steve Bennett Date: Wed, 17 Aug 2016 17:04:41 +1000 Subject: Add support for "-commands" to many commands This option returns a list of support subcommands and is useful for command line completion. Support added to: socket, namespace, tcl::prefix, string, dict, info Signed-off-by: Steve Bennett --- jim-aio.c | 2 +- jim-namespace.c | 2 +- jim-tclprefix.c | 2 +- jim.c | 67 ++++++++++++++++++++++++++++++++++++++++++++------------- jim.h | 2 ++ 5 files changed, 57 insertions(+), 18 deletions(-) diff --git a/jim-aio.c b/jim-aio.c index e8af2f3..93e0b41 100644 --- a/jim-aio.c +++ b/jim-aio.c @@ -1679,7 +1679,7 @@ static int JimAioSockCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } if (Jim_GetEnum(interp, argv[1], socktypes, &socktype, "socket type", JIM_ERRMSG) != JIM_OK) - return JIM_ERR; + return Jim_CheckShowCommands(interp, argv[1], socktypes); Jim_SetEmptyResult(interp); diff --git a/jim-namespace.c b/jim-namespace.c index bcc7259..9920488 100644 --- a/jim-namespace.c +++ b/jim-namespace.c @@ -217,7 +217,7 @@ static int JimNamespaceCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { - return JIM_ERR; + return Jim_CheckShowCommands(interp, argv[1], options); } switch (option) { diff --git a/jim-tclprefix.c b/jim-tclprefix.c index e041cc6..fd696b7 100644 --- a/jim-tclprefix.c +++ b/jim-tclprefix.c @@ -43,7 +43,7 @@ static int Jim_TclPrefixCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const return JIM_ERR; } if (Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) - return JIM_ERR; + return Jim_CheckShowCommands(interp, argv[1], options); switch (option) { case OPT_MATCH:{ diff --git a/jim.c b/jim.c index f3a423e..65b434e 100644 --- a/jim.c +++ b/jim.c @@ -12879,7 +12879,7 @@ static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar return JIM_ERR; } if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) - return JIM_ERR; + return Jim_CheckShowCommands(interp, argv[1], options); if (option == OPT_REFCOUNT) { if (argc != 3) { Jim_WrongNumArgs(interp, 2, argv, "object"); @@ -13631,7 +13631,7 @@ static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a } if (Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) - return JIM_ERR; + return Jim_CheckShowCommands(interp, argv[1], options); switch (option) { case OPT_LENGTH: @@ -14480,7 +14480,7 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg } if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) { - return JIM_ERR; + return Jim_CheckShowCommands(interp, argv[1], options); } switch (option) { @@ -14667,9 +14667,8 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?"); return JIM_ERR; } - if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) - != JIM_OK) { - return JIM_ERR; + if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return Jim_CheckShowCommands(interp, argv[1], commands); } /* Test for the most common commands first, just in case it makes a difference */ @@ -15544,36 +15543,74 @@ void Jim_MakeErrorMessage(Jim_Interp *interp) Jim_EvalObjVector(interp, 2, argv); } -static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, - const char *prefix, const char *const *tablePtr, const char *name) +/* + * Given a null terminated array of strings, returns an allocated, sorted + * copy of the array. + */ +static char **JimSortStringTable(const char *const *tablePtr) { int count; char **tablePtrSorted; - int i; + /* Find the size of the table */ for (count = 0; tablePtr[count]; count++) { } + /* Allocate one extra for the terminating NULL pointer */ + tablePtrSorted = Jim_Alloc(sizeof(char *) * (count + 1)); + memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count); + qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers); + tablePtrSorted[count] = NULL; + + return tablePtrSorted; +} + +static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, + const char *prefix, const char *const *tablePtr, const char *name) +{ + char **tablePtrSorted; + int i; + if (name == NULL) { name = "option"; } Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg); - tablePtrSorted = Jim_Alloc(sizeof(char *) * count); - memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count); - qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers); - for (i = 0; i < count; i++) { - if (i + 1 == count && count > 1) { + tablePtrSorted = JimSortStringTable(tablePtr); + for (i = 0; tablePtrSorted[i]; i++) { + if (tablePtrSorted[i + 1] == NULL && i > 0) { Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1); } Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL); - if (i + 1 != count) { + if (tablePtrSorted[i + 1]) { Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1); } } Jim_Free(tablePtrSorted); } + +/* + * If objPtr is "-commands" sets the Jim result as a sorted list of options in the table + * and returns JIM_OK. + * + * Otherwise returns JIM_ERR. + */ +int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr, const char *const *tablePtr) +{ + if (Jim_CompareStringImmediate(interp, objPtr, "-commands")) { + int i; + char **tablePtrSorted = JimSortStringTable(tablePtr); + Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); + for (i = 0; tablePtrSorted[i]; i++) { + Jim_ListAppendElement(interp, Jim_GetResult(interp), Jim_NewStringObj(interp, tablePtrSorted[i], -1)); + } + Jim_Free(tablePtrSorted); + return JIM_OK; + } + return JIM_ERR; +} + int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr, const char *const *tablePtr, int *indexPtr, const char *name, int flags) { diff --git a/jim.h b/jim.h index 5c8de22..183f970 100644 --- a/jim.h +++ b/jim.h @@ -842,6 +842,8 @@ JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg); JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr, const char * const *tablePtr, int *indexPtr, const char *name, int flags); +JIM_EXPORT int Jim_CheckShowCommands(Jim_Interp *interp, Jim_Obj *objPtr, + const char *const *tablePtr); JIM_EXPORT int Jim_ScriptIsComplete(Jim_Interp *interp, Jim_Obj *scriptObj, char *stateCharPtr); -- cgit v1.1