使用GNU ReadLine Library实现命令解析器
时间:2010-05-31 来源:creatory
使用GNU ReadLine Library实现命令解析器(历史记录,Tab自动补全等)
#include <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/errno.h> #include <readline/readline.h>
#include <readline/history.h> extern char *getwd ();
extern char *xmalloc (); /* The names of functions that actually do the manipulation. */
int com_list (char*);
int com_view (char*);
int com_rename (char*);
int com_stat (char*);
int com_pwd (char*);
int com_delete (char*);
int com_help (char*);
int com_cd (char*);
int com_quit (char*); /* A structure which contains information on the commands this program
can understand. */ typedef struct {
char *name; /* User printable name of the function. */
Function *func; /* Function to call to do the job. */
char *doc; /* Documentation for this function. */
} COMMAND; COMMAND commands[] = {
{ "cd", com_cd, "Change to directory DIR" },
{ "delete", com_delete, "Delete FILE" },
{ "help", com_help, "Display this text" },
{ "?", com_help, "Synonym for `help'" },
{ "list", com_list, "List files in DIR" },
{ "ls", com_list, "Synonym for `list'" },
{ "pwd", com_pwd, "Print the current working directory" },
{ "quit", com_quit, "Quit using Fileman" },
{ "rename", com_rename, "Rename FILE to NEWNAME" },
{ "stat", com_stat, "Print out statistics on FILE" },
{ "view", com_view, "View the contents of FILE" },
{ (char *)NULL, (Function *)NULL, (char *)NULL }
}; /* Forward declarations. */
char *stripwhite ();
COMMAND *find_command (); /* The name of this program, as taken from argv[0]. */
char *progname; /* When non-zero, this global means the user is done using this program. */
int done; int
main (argc, argv)
int argc;
char **argv;
{
char *line, *s; progname = argv[0]; initialize_readline (); /* Bind our completer. */ /* Loop reading and executing lines until the user quits. */
for ( ; done == 0; )
{
line = readline ("Jimmy: "); if (!line)
break; /* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
s = stripwhite (line); if (*s)
{
add_history (s);
execute_line (s);
} free (line);
}
exit (0);
} /* Execute a command line. */
int
execute_line (line)
char *line;
{
register int i;
COMMAND *command;
char *word; /* Isolate the command word. */
i = 0;
while (line[i] && isspace (line[i]))
i++;
word = line + i; while (line[i] && !isspace (line[i]))
i++; if (line[i])
line[i++] = '\0'; command = find_command (word); if (!command)
{
fprintf (stderr, "%s: No such command for FileMan.\n", word);
return (-1);
} /* Get argument to command, if any. */
while (isspace (line[i]))
i++; word = line + i; /* Call the function. */
return ((*(command->func)) (word));
} /* Look up NAME as the name of a command, and return a pointer to that
command. Return a NULL pointer if NAME isn't a command name. */
COMMAND *
find_command (char* name)
{
int i; for (i = 0; commands[i].name; i++)
if (strcmp (name, commands[i].name) == 0)
return (&commands[i]); return ((COMMAND *)NULL);
} /* Strip whitespace from the start and end of STRING. Return a pointer
into STRING. */
char *
stripwhite (char* string)
{
char *s, *t; for (s = string; isspace (*s); s++)
;
if (*s == 0)
return (s); t = s + strlen (s) - 1;
while (t > s && isspace (*t))
t--;
*++t = '\0'; return s;
}
/* Tell the GNU Readline library how to complete. We want to try to complete
on command names if this is the first word in the line, or on filenames
if not. */
initialize_readline ()
{
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = "FileMan";
} /* **************************************************************** */
/* */
/* FileMan Commands */
/* */
/* **************************************************************** */ /* String to pass to system (). This is for the LIST, VIEW and RENAME
commands. */
static char syscom
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/errno.h> #include <readline/readline.h>
#include <readline/history.h> extern char *getwd ();
extern char *xmalloc (); /* The names of functions that actually do the manipulation. */
int com_list (char*);
int com_view (char*);
int com_rename (char*);
int com_stat (char*);
int com_pwd (char*);
int com_delete (char*);
int com_help (char*);
int com_cd (char*);
int com_quit (char*); /* A structure which contains information on the commands this program
can understand. */ typedef struct {
char *name; /* User printable name of the function. */
Function *func; /* Function to call to do the job. */
char *doc; /* Documentation for this function. */
} COMMAND; COMMAND commands[] = {
{ "cd", com_cd, "Change to directory DIR" },
{ "delete", com_delete, "Delete FILE" },
{ "help", com_help, "Display this text" },
{ "?", com_help, "Synonym for `help'" },
{ "list", com_list, "List files in DIR" },
{ "ls", com_list, "Synonym for `list'" },
{ "pwd", com_pwd, "Print the current working directory" },
{ "quit", com_quit, "Quit using Fileman" },
{ "rename", com_rename, "Rename FILE to NEWNAME" },
{ "stat", com_stat, "Print out statistics on FILE" },
{ "view", com_view, "View the contents of FILE" },
{ (char *)NULL, (Function *)NULL, (char *)NULL }
}; /* Forward declarations. */
char *stripwhite ();
COMMAND *find_command (); /* The name of this program, as taken from argv[0]. */
char *progname; /* When non-zero, this global means the user is done using this program. */
int done; int
main (argc, argv)
int argc;
char **argv;
{
char *line, *s; progname = argv[0]; initialize_readline (); /* Bind our completer. */ /* Loop reading and executing lines until the user quits. */
for ( ; done == 0; )
{
line = readline ("Jimmy: "); if (!line)
break; /* Remove leading and trailing whitespace from the line.
Then, if there is anything left, add it to the history list
and execute it. */
s = stripwhite (line); if (*s)
{
add_history (s);
execute_line (s);
} free (line);
}
exit (0);
} /* Execute a command line. */
int
execute_line (line)
char *line;
{
register int i;
COMMAND *command;
char *word; /* Isolate the command word. */
i = 0;
while (line[i] && isspace (line[i]))
i++;
word = line + i; while (line[i] && !isspace (line[i]))
i++; if (line[i])
line[i++] = '\0'; command = find_command (word); if (!command)
{
fprintf (stderr, "%s: No such command for FileMan.\n", word);
return (-1);
} /* Get argument to command, if any. */
while (isspace (line[i]))
i++; word = line + i; /* Call the function. */
return ((*(command->func)) (word));
} /* Look up NAME as the name of a command, and return a pointer to that
command. Return a NULL pointer if NAME isn't a command name. */
COMMAND *
find_command (char* name)
{
int i; for (i = 0; commands[i].name; i++)
if (strcmp (name, commands[i].name) == 0)
return (&commands[i]); return ((COMMAND *)NULL);
} /* Strip whitespace from the start and end of STRING. Return a pointer
into STRING. */
char *
stripwhite (char* string)
{
char *s, *t; for (s = string; isspace (*s); s++)
;
if (*s == 0)
return (s); t = s + strlen (s) - 1;
while (t > s && isspace (*t))
t--;
*++t = '\0'; return s;
}
/* Tell the GNU Readline library how to complete. We want to try to complete
on command names if this is the first word in the line, or on filenames
if not. */
initialize_readline ()
{
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = "FileMan";
} /* **************************************************************** */
/* */
/* FileMan Commands */
/* */
/* **************************************************************** */ /* String to pass to system (). This is for the LIST, VIEW and RENAME
commands. */
static char syscom
相关阅读 更多 +