/*------------------------------------------------------------------------- * C-Pluff, a plug-in framework for C * Copyright 2007 Johannes Lehtinen * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *-----------------------------------------------------------------------*/ // GNU readline based command line input #include #include #include #include #include #include "console.h" static cp_plugin_info_t **plugins = NULL; static char *cp_console_compl_cmdgen(const char *text, int state) { static int counter; static int textlen; if (!state) { counter = 0; textlen = strlen(text); } while (commands[counter].name != NULL && strncmp(text, commands[counter].name, textlen)) { counter++; } if (commands[counter].name == NULL) { return NULL; } else { char *buffer = strdup(commands[counter].name); counter++; return buffer; } } static char *cp_console_compl_flagsgen(const char *text, int state) { static int counter; static int textlen; if (!state) { counter = 0; textlen = strlen(text); } while(load_flags[counter].name != NULL && strncmp(text, load_flags[counter].name, textlen)) { counter++; } if (load_flags[counter].name == NULL) { return NULL; } else { char *buffer = strdup(load_flags[counter].name); counter++; return buffer; } } static char *cp_console_compl_loggen(const char *text, int state) { static int counter; static int textlen; if (!state) { counter = 0; textlen = strlen(text); } while (log_levels[counter].name != NULL && strncmp(text, log_levels[counter].name, textlen)) { counter++; } if (log_levels[counter].name == NULL) { return NULL; } else { char *buffer = strdup(log_levels[counter].name); counter++; return buffer; } } static char *cp_console_compl_plugingen(const char *text, int state) { static int counter; static int textlen; if (!state) { counter = 0; textlen = strlen(text); if (plugins != NULL) { cp_release_info(context, plugins); } plugins = cp_get_plugins_info(context, NULL, NULL); } if (plugins != NULL) { while (plugins[counter] != NULL && strncmp(text, plugins[counter]->identifier, textlen)) { counter++; } if (plugins[counter] == NULL) { cp_release_info(context, plugins); plugins = NULL; return NULL; } else { char *buffer = strdup(plugins[counter]->identifier); counter++; return buffer; } } else { return NULL; } } static char **cp_console_completion(const char *text, int start, int end) { int cs, ce; char **matches = NULL; // Search for start and end of command for (cs = 0; cs < start && isspace(rl_line_buffer[cs]); cs++); for (ce = cs; ce <= start && !isspace(rl_line_buffer[ce]); ce++); // If no command entered yet, use command completion if (ce >= start) { matches = rl_completion_matches(text, cp_console_compl_cmdgen); rl_attempted_completion_over = 1; } // Otherwise check if known command and complete accordingly else { int j = 0; while (commands[j].name != NULL && strncmp(rl_line_buffer + cs, commands[j].name, ce - cs)) { j++; } if (commands[j].name != NULL) { switch(commands[j].arg_completion) { case CPC_COMPL_FILE: break; case CPC_COMPL_FLAG: matches = rl_completion_matches(text, cp_console_compl_flagsgen); rl_attempted_completion_over = 1; break; case CPC_COMPL_LOG_LEVEL: matches = rl_completion_matches(text, cp_console_compl_loggen); rl_attempted_completion_over = 1; break; case CPC_COMPL_PLUGIN: matches = rl_completion_matches(text, cp_console_compl_plugingen); rl_attempted_completion_over = 1; break; default: rl_attempted_completion_over = 1; break; } } else { rl_attempted_completion_over = 1; } } return matches; } CP_HIDDEN void cmdline_init(void) { rl_readline_name = PACKAGE_NAME; rl_attempted_completion_function = cp_console_completion; } CP_HIDDEN char *cmdline_input(const char *prompt) { static char *cmdline = NULL; // Free previously returned command line, if any if (cmdline != NULL) { free(cmdline); cmdline = NULL; } // Obtain new command line and record it for history cmdline = readline(prompt); if (cmdline != NULL && *cmdline != '\0') { add_history(cmdline); } return cmdline; } CP_HIDDEN void cmdline_destroy(void) { if (plugins != NULL) { cp_release_info(context, plugins); plugins = NULL; } }