The CommandProcessor is the interface to install a run-time menu into an embedded system.
Dependents: A_CANAdapter USB2I2C
CommandProcessor.h
- Committer:
- WiredHome
- Date:
- 2012-11-08
- Revision:
- 17:abba63b079fb
- Parent:
- 16:4ce4f55213ac
File content as of revision 17:abba63b079fb:
/// @file CommandProcessor.h defined the interface to the CommandProcessor /// /// @mainpage The CommandProcessor /// /// The CommandProcessor is the interface to install a run-time menu into an embedded system. /// This contains the complete interface to the CommandProcessor. /// /// @version 1.05 /// /// @note The CommandProcessor is text-based, because it is intended to interact with a /// user. /// /// The menu is designed to be interactively accessed, perhaps via a console interface /// or a serial port. The actual interface to the user is provided by the application /// during initialization, so it can be connected to a serial port, or it could /// be interface to CAN, telnet, or by some other method. /// /// The CommandProcessor has a few special features: /// \li If the minimum number of characters of a command have been entered, the /// user does not have to type the entire command. (e.g. 'He' will execute /// the command for 'Help', if no other command beings with 'He'). /// \li If the user does not type the entire set of characters, the command /// will be rewritten to the output device with the entire command word. /// \li The user is not permitted to enter an incorrect command (e.g. If 'Help' /// is the only command started with 'Hel', the user cannot enter 'Heu'. /// The CommandProcessor will trap the 'u' and issue a beep). /// \li Simple editing of parameters to commands is permitted with \<bs\> to /// erase incorrect text. /// \li Tab completion of a command is available - so long as the user has /// typed at least the minimum number of unique characters. (e.g. 'He\<tab\>' /// will be replaced with 'Help') /// \li Command cancellation is available - just enter the \<esc\> key and /// the buffer is erased. /// \li The user is not permitted to enter text longer than the defined buffer, /// to avoid buffer overrun and the possible memory damaging results. /// /// The CommandProcessor is designed as a set of C functions, which makes it /// reusable in more systems (as C++ compilers are not always available for /// all micros). /// /// Example: /// @code /// extern "C" { /// #include "CommandProcessor.h" /// } /// /// RUNRESULT_T SignOnBanner(char *p); /// const CMD_T SignOnBannerCmd = { /// "About", "About this program ('About ?' for more details)", /// SignOnBanner, invisible}; /// /// RUNRESULT_T Who(char *p); /// const CMD_T WhoCmd = { /// "who", "Shows who is logged on, or 'who id' for specifics", /// Who, visible}; /// /// RUNRESULT_T SignOnBanner(char *p) /// { /// puts("\r\nThis great program was built " __DATE__ " " __TIME__ "."); /// if (*p == '?') /// puts("\r\nMore details shown here.\r\n"); /// return runok; /// } /// RUNRESULT_T Who(char *p) /// { /// printf("\r\nwho...\r\n"); /// if (*p) /// printf(" Sorry, no help for [%s]\r\n", p); /// return runok; /// } /// /// int main(int argc, char* argv[]) /// { /// CMDP_T * cp = GetCommandProcessor(); /// cp->Init(&SignOnBanner, /// CFG_ENABLE_TERMINATE | CFG_ENABLE_SYSTEM, /// 50, _kbhit, _getch, _putch, printf); /// cp->Add(&WhoCmd); /// /// while (cp->Run()) /// { /// ; /// } /// cp->End(); /// return 0; /// } /// @endcode /// /// /// @note Copyright &copr; 2011 by Smartware Computing, all rights reserved. /// Individuals may use this application for evaluation or non-commercial /// purposes. Within this restriction, changes may be made to this application /// as long as this copyright notice is retained. The user shall make /// clear that their work is a derived work, and not the original. /// Users of this application and sources accept this application "as is" and /// shall hold harmless Smartware Computing, for any undesired results while /// using this application - whether real or imagined. /// /// @author David Smart, Smartware Computing /// /// @note /// History /// v1.05 20111030 /// \li Added support for VT100 cursor code for up/down history access /// \li Fixed a bug related to not entering any parameters - causing it to think /// there were parameters anyway. /// v1.04 1 October 2011 /// \li Added configurable command line history for easy recall of previous commands /// \li Clean up dead-code /// v1.03 29 May 2011 /// \li Slightly improved internal documentation. No external interfaces affected. /// v1.02 2 May 2011 /// \li Track the longest command when added, so that the help printout /// is more nicely formatted. /// v1.01 22 April 2011 /// \li Moving 'About' content into the extended help, /// to free 'About' for application code that uses this library. /// \li Altered the _init api to permit a signon banner of the users choice /// and a config parameter for other features. /// /// v1.0 March 2011 /// \li Initial version /// #ifndef COMMANDPROCESSOR_H #define COMMANDPROCESSOR_H #define VERSION "1.05" #ifndef TRUE #define TRUE 1 ///< Definition for TRUE, if not already provided #define FALSE 0 ///< Definition for FALSE, if not already provided #endif /// @brief This type determines if menu items are visible to the Help system, or hidden. /// @details This is used in the definition of the menu item. typedef enum { invisible, ///< use this value to have invisible (hidden) a menu in the Help visible ///< use this value to have visible a menu in the Help } VISIBLE_T; ///< This determines if menu items are made visible in the Help system. /// Callbacks that are executed return a value to indicate if the menu /// should remain active typedef enum { runexit, ///< use this return value to cause the menu (perhaps the program) to exit runok ///< use this return value to keep the menu running } RUNRESULT_T; /// Adding items to the menu can succeed, or fail. typedef enum { addfailed, ///< this indicates the menu was not added (usually failure to allocate memory) addok ///< this indicates the menu was successfully added } ADDRESULT_T; /// Initialization can succeed, or fail. typedef enum { initfailed, ///< this indicates that the menu system was not initialized (usually failure to allocate memory) initok ///< this indicates that the menu system was successfully initialized } INITRESULT_T; /// Configuration options to control startup and some runtime behavior /// /// Permissible values are created by combining /// \li CFG_ENABLE_TERMINATE /// \li CFG_ENABLE_SYSTEM /// \li CFG_ECHO_ON /// \li CFG_CASE_INSENSITIVE typedef unsigned long CONFIG_T; #define CFG_ENABLE_TERMINATE 0x0001 ///<- Enable the exit option #define CFG_ENABLE_SYSTEM 0x0002 ///<- Enable various system options (help, etc) #define CFG_ECHO_ON 0x2000 ///<- Initialize with command prompt Echo on #define CFG_CASE_INSENSITIVE 0x4000 ///<- Enable case insensitive command entry /// This is the type for the basic callback, when a menu pick is activated. /// /// The callback function is executed when a command is entered on the menu and \<enter\> /// is signaled. If there is any additional text entered on the commandline, it is /// passed to the callback. /// /// example: /// "Test1 ab c 123 567" /// If "Test1" is a valid command, the corresponding function would be called /// passing to that function the string "ab c 123 567". Note that the delimiter space /// was removed. /// /// @param p is a pointer to a character string /// @returns RUNRESULT_T to indicate if the CommandProcessor should continue /// typedef RUNRESULT_T (*MENU_CALLBACK)(char *p); /// This defines the type for a single item to be added to the CommandProcessor menu. /// /// This is defined in the application code, and a pointer to this item is passed to the /// CommandProcessor to add this item to the menu system. /// /// example: /// @code /// const CMD_T WhoCmd = {"who", "Shows who is logged on, or 'who id' for specifics", Who, visible}; /// @endcode /// typedef const struct { char * command; ///< a pointer to the command to match (e.g. 'Help') char * helptext; ///< a pointer to some text to show when user types 'Help' MENU_CALLBACK callback; ///< the function to call when user enters this command VISIBLE_T visible; ///< a flag that determines if this command is visible in Help. } CMD_T; /// This is the CommandProcessor interface from the user application. /// /// The user aquires a handle to this set of functions with the GetCommandProcessor command. /// After this, the user may then initialize the CommandProcessor, add items to the menu, /// cause the CommandProcessor to run periodically, and if need be the application can end /// the CommandProcessor. /// typedef const struct { /// Init is the first function to call to configure the CommandProcessor. /// /// This function has a number of parameters, which make the CommandProcessor quite flexible. /// /// @param SignOnBanner function, which is used as a signon banner /// @param config enables various default menu items, based on the bit values, combine the following: /// \li CFG_ENABLE_TERMINATE - enables the Exit command /// \li CFG_ENABLE_SYSTEM - enables system commands Echo, Help, etc. /// \li CFG_ECHO_ON - initialize with echo on /// \li CFG_CASE_INSENSITIVE - Command Parser is case insensitive /// @param maxCmdLen sizes the buffer, and is the maximum number of characters in a single /// command, including all command arguments /// @param historyLen sets the number of items that can be recalled from history /// @param kbhit is a user provided function to detect if a character is available for the CommandProcessor, /// and when using standard io, you can typically use kbhit, or _kbhit as your system provides. /// @param getch is a user provided function that provides a single character to the CommandProcessor /// @param putch is a user provided function that permits the CommandProcessor to output a character /// @param puts is a user provided function that permits the CommandProcessor to output a string /// to which is automatically appended a \\n /// @returns INITRESULT_T to indicate if the init was successful or failed /// INITRESULT_T (*Init)( CMD_T *SignOnBanner, CONFIG_T config, int maxCmdLen, int historyLen, int (*kbhit)(void), int (*getch)(void), int (*putch)(int ch), int (*puts)(const char * s) ); /// Add is called to add an item to the CommandProcessor menu /// /// This passes in a reference to a user provided CMD_T item, which is /// added to the menu system. /// /// @param m is a pointer to the user provided menu /// @returns ADDRESULT_T to indicate if the add was successful or failed /// ADDRESULT_T (*Add)(CMD_T * m); /// Run is the primary runtime entry point for the CommandProcessor. /// /// This function should be called periodically - fast enough not to miss user input. /// This function always returns, so if not character is available for the CommandProcessor /// it will return very fast. If there is a character (as detected by the kbhit callback), /// then it will process that character and determine what to do. It may then execute one /// of the menu functions. In this case, CPU cycles spent are based on the function /// being executed. /// /// @returns RUNRESULT_T to indicate if the CommandProcessor should remain active or if the /// command that was executed is requesting the CommandProcessor to exit. /// RUNRESULT_T (*Run)(void); /// Echo command permits turning the echo on and off /// /// When interactive with the user, it is best to have echo on, so they can see /// the prompt, but if this is simply slaved to another program, then the echo /// might need to be off to best manage the stream. /// /// @param echo turns the echo on (non-zero) or off (zero) /// @returns RUNRESULT_T to indicate if the CommandProcessor should remain active or if the /// command that was executed is requesting the CommandProcessor to exit. /// RUNRESULT_T (*Echo)(int echo); /// End if the function to be called when you want to gracefully end the CommandProcessor. /// /// Calling this function causes the CommandProcessor to free any memory that was previously /// allocated by the Init and Add functions. RUNRESULT_T (*End)(void); ///< Called to shutdown the processor } CMDP_T; /// The CommandProcessor is the interface to install a run-time menu into an embedded system. /// This contains the complete interface to the CommandProcessor. /// /// @version 1.05 /// /// @note The CommandProcessor is text-based, because it is intended to interact with a /// user. /// /// The menu is designed to be interactively accessed, perhaps via a console interface /// or a serial port. The actual interface to the user is provided by the application /// during initialization, so it can be connected to a serial port, or it could /// be interface to CAN, telnet, or by some other method. /// /// The CommandProcessor has a few special features: /// \li If the minimum number of characters of a command have been entered, the /// user does not have to type the entire command. (e.g. 'He' will execute /// the command for 'Help', if no other command beings with 'He'). /// \li If the user does not type the entire set of characters, the command /// will be rewritten to the output device with the entire command word. /// \li The user is not permitted to enter an incorrect command (e.g. If 'Help' /// is the only command started with 'Hel', the user cannot enter 'Heu'. /// The CommandProcessor will trap the 'u' and issue a beep). /// \li Simple editing of parameters to commands is permitted with \<bs\> to /// erase incorrect text. /// \li Tab completion of a command is available - so long as the user has /// typed at least the minimum number of unique characters. (e.g. 'He\<tab\>' /// will be replaced with 'Help') /// \li Command cancellation is available - just enter the \<esc\> key and /// the buffer is erased. /// \li The user is not permitted to enter text longer than the defined buffer, /// to avoid buffer overrun and the possible memory damaging results. /// /// The CommandProcessor is designed as a set of C functions, which makes it /// reusable in more systems (as C++ compilers are not always available for /// all micros). /// /// Example: /// @code /// extern "C" { /// #include "CommandProcessor.h" /// } /// /// RUNRESULT_T About(char *p); /// const CMD_T AboutCmd = {"About", "About this program", About, invisible}; /// RUNRESULT_T Who(char *p); /// const CMD_T WhoCmd = {"who", "Shows who is logged on, or 'who id' for specifics", Who, visible}; /// /// RUNRESULT_T About(char *p) /// { /// (void)p; /// puts("\r\nThis program does really good things for the user.\r\n"); /// } /// /// RUNRESULT_T Who(char *p) /// { /// printf("\r\nwho...\r\n"); /// if (*p) /// printf(" Sorry, no help for [%s]\r\n", p); /// return runok; /// } /// /// int main(int argc, char* argv[]) /// { /// CMDP_T * cp = GetCommandProcessor(); /// cp->Init(AboutCmd, CFG_ENABLE_TERMINATE | CFG_ENABLE_SYSTEM | CFG_SIGNON_BANNER, /// 50, /// _kbhit, _getch, _putch, printf); /// cp->Add(&WhoCmd); /// /// while (cp->Run()) /// { /// ; /// } /// cp->End(); /// return 0; /// } /// @endcode /// /// @note Copyright © 2011 by Smartware Computing, all rights reserved. /// This program may be used by others as long as this copyright notice /// remains intact. /// @author David Smart /// /// GetCommandProcessor is called to get a handle to the CommandProcessor itself. /// /// Call this function to get a handle to the CommandProcessor. After this is done, then /// you can use that handle to activate the CommandProcessor methods. /// /// example: /// @code /// CMDP_T * cp = GetCommandProcessor(); /// cp->Init(AboutCmd, CFG_ENABLE_TERMINATE | CFG_ENABLE_SYSTEM | CFG_SIGNON_BANNER, /// 50, /// _kbhit, _getch, _putch, printf); /// @endcode /// /// @returns CMDP_T a handle to the CommandProcessor /// #ifdef WIN32 extern CMDP_T * GetCommandProcessor(void); #else // This is necessary for the mbed - not sure why. extern CMDP_T * GetCommandProcessor(void); #endif #endif // COMMANDPROCESSOR_H