--- libaitio/src/Attic/cli.c 2010/03/09 12:44:40 1.1 +++ libaitio/src/Attic/cli.c 2010/03/22 15:21:20 1.2 @@ -0,0 +1,226 @@ +/************************************************************************* +* (C) 2010 AITNET ltd - Sofia/Bulgaria - +* by Michael Pounov +* +* $Author: misho $ +* $Id: cli.c,v 1.2 2010/03/22 15:21:20 misho Exp $ +* +*************************************************************************/ +#include "global.h" + + +/* + * io_Cmd_Exit() Builtin helper function for Exit from Cli + * @cmds = Commands list + * @out = Output handle + * @args = Parsed arguments array + * return: 1 exit from Cli! +*/ +int io_Cmd_Exit(void *cmds, FILE *out, char ** __restrict args) +{ + return 1; +} + +/* + * io_Cmd_Help() Builtin helper function for Help screen + * @cmds = Commands list + * @out = Output handle + * @args = Parsed arguments array + * return: -1 error, 0 = ok +*/ +int io_Cmd_Help(void *cmds, FILE *out, char ** __restrict args) +{ + register int i; + ioCommands_t *commands = cmds; + + if (!cmds) + return -1; + + if (!args) { + fprintf(out, "\n"); + fflush(out); + for (i = 0; commands[i].cmd_name; i++) { + fprintf(out, "%s\t\t%s\n", commands[i].cmd_name, commands[i].cmd_doc); + fflush(out); + } + } else { + if (!args[1]) { + fprintf(out, "Help screen::\n"); + fflush(out); + } else + if (!strncmp(args[1], "---", 3)) + return 0; + + for (i = 0; commands[i].cmd_name; i++) { + if (args[1] && strcmp(args[1], commands[i].cmd_name)) + continue; + + fprintf(out, "%s%s\t\t%s\n", args[1] ? "Syntax::\n\t" : "", commands[i].cmd_name, + args[1] ? commands[i].cmd_help : commands[i].cmd_doc); + fflush(out); + } + } + + return 0; +} + +/* + * io_Cmd_Unsupported() Builtin helper function for unsupported commands + * @cmds = Commands list + * @out = Output handle + * @args = Parsed arguments array + * return: -1 error, 0 = ok, 1 exit from Cli! +*/ +int io_Cmd_Unsupported(void *cmds, FILE *out, char ** __restrict args) +{ + fprintf(out, "Command %s not supported in this version ...\n", args[0]); + fflush(out); + return 0; +} + +// ------------------------------------------------------------ + +/* + * io_Comp_Filename() Builtin helper function for filename completion arguments + * @text = Text line + * @state = Position state + * return: NULL not found filename, != NULL filename +*/ +char *io_Comp_Filename(const char *text, int state) +{ + return rl_filename_completion_function(text, state); +} + +// ------------------------------------------------------------ + +#pragma GCC visibility push(hidden) + +ioCommands_t io_stdCmds[] = { + { "test", io_Cmd_Unsupported, "Test - Don`t use default command structure!", "test ", io_Comp_Filename }, + { "-------", NULL, "---------------------", NULL, NULL }, + { "help", io_Cmd_Help, "Help screen", "help [command] ", NULL }, + { "exit", io_Cmd_Exit, "Exit from console", "exit ", NULL }, + { NULL, NULL, NULL, NULL } +}; + +#pragma GCC visibility pop + +// ------------------------------------------------------------ + +/* + * ioCLIComp() Initialize completion CLI features + * @cmdComplete = Completion function + * @cmdEntry = Compentry function + * return: none +*/ +inline void ioCLIComp(io_Completion_t *cmdComplete, io_CompEntry_t *cmdEntry) +{ + // command completon + rl_attempted_completion_function = cmdComplete; + rl_completion_entry_function = cmdEntry; +} + +/* + * ioCLIExec() Execute CLI main loop + * @cmdList = Commands list + * @out = Output handle + * @csPrompt = Prompt text + * return: -1 error, 0 = exit w/^+D, 1 done. +*/ +int ioCLIExec(ioCommands_t *cmdList, FILE *out, const char *csPrompt) +{ + char *line, *s, *t, **app, *items[20]; + int ret = 0; + register int i; + ioCommands_t *cmd = NULL; + + inline int inline_help() + { + io_Cmd_Help(cmdList ? cmdList : io_stdCmds, out, NULL); + rl_on_new_line(); + return 0; + } + + char **io_stdCompletion(const char *text, int start, int end) + { + register int i; + char **matches = NULL; + + char *cmdCompGet(const char *text, int state) + { + int len = strlen(text); + + for (i = state; cmdList[i].cmd_name; i++) { + if (strncmp(cmdList[i].cmd_name, "---", 3) && + !strncmp(cmdList[i].cmd_name, text, len)) + return strdup(cmdList[i].cmd_name); + } + + return NULL; + } + + if (!start) + matches = rl_completion_matches(text, cmdCompGet); + else + for (i = 0; cmdList[i].cmd_name; i++) { + if (!cmdList[i].cmd_comp) + continue; + if (!strncmp(rl_line_buffer, cmdList[i].cmd_name, strlen(cmdList[i].cmd_name))) + matches = rl_completion_matches(text, cmdList[i].cmd_comp); + } + + return matches; + } + char *io_stdCompEntry(const char *ignore, int invoking_key) + { + return NULL; + } + + rl_bind_key('?', inline_help); + if (!rl_attempted_completion_function) + ioCLIComp(io_stdCompletion, io_stdCompEntry); + + do { + line = readline(csPrompt); + if (!line) { // ^+d + fprintf(out, "\n"); + fflush(out); + break; + } + // clear whitespaces + for (s = line; isspace(*s); s++); + if (*s) { + for (t = s + strlen(s) - 1; t > s && isspace(*t); t--); + *++t = 0; + } + + if (*s) { + add_history(s); + + memset(items, 0, sizeof(char*) * 20); + for (app = items; app < items + 19 && (*app = strsep(&s, " \t")); *app ? app++ : app); + + /* + for (i = 0; i < 20; i++) + printf("i=%d %s\n", i, items[i]); + */ + + // exec_cmd ... + for (cmd = NULL, i = 0; cmdList[i].cmd_name; i++) + if (*items[0] && !strncmp(cmdList[i].cmd_name, items[0], strlen(items[0]))) { + cmd = &cmdList[i]; + break; + } + if (!cmd) { + fprintf(out, "Command '%s' not found!\n", items[0]); + fflush(out); + ret = -1; + } else + ret = cmd->cmd_func(cmdList, out, items); + } + + free(line); + } while (ret < 1); + + return ret; +}