一 目的
为了使linux下的程序在运行中的命令行界面输入命令时具有自动补齐和历史记录功能,比如像asterisk的控制台界面。
二 实现方法
实现方法相对于在远端实现(参见:为在telnet自己TCP服务器程序的界面上实现shell一样的自动补齐和历史记录的功能)要简单的多,因为有第三方库可以使用—libedit库,这个库可以处理很多与控制台界面有关的东西。Asterisk用的就是这个,最开始以为asterisk的这种方式可以远程使用,后来看了下源码发现只能在本地使用,因为它绑定的键位是本机键盘,在远端(一般是telnet)的”↑””↓”上翻下翻键无法是被检测到的。
三 详细实现
Cli.c
static History *el_hist; //命令历史记录列表
static EditLine *el; //本地编辑功能的主要实体
//用于显示提示符的回调函数
static char *cli_prompt(EditLine * el)
{
static char prompt[200];
sprintf(prompt, "CLI>");
return prompt;
}
//用于自动补齐的回调函数
static char *cli_complete(EditLine * el, int ch)
{
int len = 0;
printf("input is
return 0;
}
static int ngn_all_zeros(char *s)
{
while (*s) {
if (*s > 32)
return 0;
s++;
}
return 1;
}
int ngn_el_initialize(void)
{
HistEvent ev; //libedit事件
//char *editor = getenv("NGN_EDITOR");
char *editor = (char *) ("vim"); //设置编辑器
if (el != NULL)
el_end(el); //重置el
if (el_hist != NULL)
history_end(el_hist); //重置el_list
el = el_init("ngn", stdin, stdout, stderr);
el_set(el, EL_PROMPT, cli_prompt); //挂载提示符函数
el_set(el, EL_EDITMODE, 1);
el_set(el, EL_EDITOR, editor ? editor : "vim");
el_hist = history_init(); //初始化el_hist
if (!el || !el_hist)
return -1;
/* 设置命令历史记录长度为100 */
history(el_hist, &ev, H_SETSIZE, 100);
el_set(el, EL_HIST, history, el_hist);
//绑定键位到对应的回调函数,一下主要是绑定自动补齐的函数
el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
/* Bind
el_set(el, EL_BIND, "^I", "ed-complete", NULL);
/* Bind ? to command completion */
el_set(el, EL_BIND, "?", "ed-complete", NULL);
/* Bind ^D to redisplay */
el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
int num;
const char *buf;
Tokenizer *tok;
int ncontinuation;
while ((buf = el_gets(el, &num)) != NULL && num != 0) {
history(el_hist, &ev, H_ENTER, buf);
printf("input is: %s", buf);
ngn_cli_command(STDOUT_FILENO, buf);
}
return 0;
}
在main.c中调用
ngn_el_initialize();