Re #1098: Modify help screen, change backspace input character, fix static and dynamic choice type argument handling

git-svn-id: https://svn.pjsip.org/repos/pjproject/branches/projects/cli@4302 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
Riza Sulistyo 2012-11-28 03:02:01 +00:00
parent f48b841e14
commit e02d0df8f6
5 changed files with 145 additions and 90 deletions

View File

@ -560,7 +560,8 @@ static pj_status_t pj_cli_add_choice_node(pj_cli_t *cli,
pj_strassign(&choice_val->value, &choice_attr->value);
} else if (!pj_stricmp2(&choice_attr->name, "desc")) {
pj_strassign(&choice_val->desc, &choice_attr->value);
}
}
choice_attr = choice_attr->next;
}
++(arg->stat_choice_cnt);
choice_node = choice_node->next;
@ -608,7 +609,7 @@ static pj_status_t pj_cli_add_arg_node(pj_cli_t *cli,
arg->type = PJ_CLI_ARG_TEXT;
} else if (!pj_stricmp2(&attr->value, "int")) {
arg->type = PJ_CLI_ARG_INT;
} else if (!pj_stricmp2(&attr->value, "CHOICE")) {
} else if (!pj_stricmp2(&attr->value, "choice")) {
/* Get choice value */
pj_cli_add_choice_node(cli, xml_node, arg, get_choice);
}
@ -732,11 +733,18 @@ static pj_status_t pj_cli_add_cmd_node(pj_cli_t *cli,
cmd->arg = (pj_cli_arg_spec *)pj_pool_zalloc(cli->pool, cmd->arg_cnt *
sizeof(pj_cli_arg_spec));
for (i = 0; i < cmd->arg_cnt; i++) {
unsigned j;
pj_strdup(cli->pool, &cmd->arg[i].name, &args[i].name);
pj_strdup(cli->pool, &cmd->arg[i].desc, &args[i].desc);
cmd->arg[i].id = args[i].id;
cmd->arg[i].type = args[i].type;
cmd->arg[i].optional = args[i].optional;
cmd->arg[i].get_dyn_choice = args[i].get_dyn_choice;
cmd->arg[i].stat_choice_cnt = args[i].stat_choice_cnt;
cmd->arg[i].stat_choice_val = args[i].stat_choice_val;
}
}
@ -1063,8 +1071,7 @@ static pj_status_t get_match_args(pj_cli_sess *sess,
arg = &cmd->arg[argc-1];
PJ_ASSERT_RETURN(arg, PJ_EINVAL);
if (arg->type == PJ_CLI_ARG_CHOICE) {
unsigned j;
pj_cli_dyn_choice_param dyn_choice_param;
unsigned j;
for (j=0; j < arg->stat_choice_cnt; ++j) {
pj_cli_arg_choice_val *choice_val = &arg->stat_choice_val[j];
@ -1080,20 +1087,28 @@ static pj_status_t get_match_args(pj_cli_sess *sess,
return status;
}
}
/* Get the dynamic choice values */
dyn_choice_param.sess = sess;
dyn_choice_param.cmd = cmd;
dyn_choice_param.arg_id = arg->id;
dyn_choice_param.max_cnt = PJ_CLI_MAX_CHOICE_VAL;
dyn_choice_param.pool = pool;
dyn_choice_param.cnt = 0;
if (arg->get_dyn_choice) {
pj_cli_dyn_choice_param dyn_choice_param;
static const pj_str_t choice_str = {"choice", 6};
(*arg->get_dyn_choice)(&dyn_choice_param);
for (j=0; j < dyn_choice_param.cnt; ++j) {
pj_cli_arg_choice_val *choice = &dyn_choice_param.choice[j];
pj_strassign(&info->hint[info->hint_cnt].name, &choice->value);
pj_strassign(&info->hint[info->hint_cnt].desc, &choice->desc);
++info->hint_cnt;
/* Get the dynamic choice values */
dyn_choice_param.sess = sess;
dyn_choice_param.cmd = cmd;
dyn_choice_param.arg_id = arg->id;
dyn_choice_param.max_cnt = PJ_CLI_MAX_CHOICE_VAL;
dyn_choice_param.pool = pool;
dyn_choice_param.cnt = 0;
(*arg->get_dyn_choice)(&dyn_choice_param);
for (j=0; j < dyn_choice_param.cnt; ++j) {
pj_cli_arg_choice_val *choice = &dyn_choice_param.choice[j];
if (!pj_strnicmp(&choice->value, cmd_val, cmd_val->slen)) {
pj_strassign(&info->hint[info->hint_cnt].name, &choice->value);
pj_strassign(&info->hint[info->hint_cnt].type, &choice_str);
pj_strassign(&info->hint[info->hint_cnt].desc, &choice->desc);
++info->hint_cnt;
}
}
}
} else {
if (cmd_val->slen == 0) {

View File

@ -78,6 +78,17 @@ typedef enum cmd_parse_state
ST_ARROWMODE
} cmd_parse_state;
/**
* This specify the state of output character parsing.
*/
typedef enum out_parse_state
{
OP_NORMAL,
OP_TYPE,
OP_SHORTCUT,
OP_CHOICE
} out_parse_state;
/**
* This structure contains the command line shown to the user.
*/
@ -365,10 +376,10 @@ static void send_ambi_arg(pj_cli_sess *sess,
struct cli_console_fe *fe = (struct cli_console_fe *)sess->fe;
console_recv_buf *recv_buf = &fe->input.recv_buf;
const pj_cli_hint_info *hint = info->hint;
pj_bool_t is_process_sc = PJ_FALSE;
pj_bool_t valid_type = PJ_FALSE;
out_parse_state parse_state = OP_NORMAL;
pj_ssize_t max_length = 0;
const pj_str_t sc_type = pj_str("SC");
static const pj_str_t sc_type = {"sc", 2};
static const pj_str_t choice_type = {"choice", 6};
send_data.ptr = &data[0];
send_data.slen = 0;
@ -390,46 +401,46 @@ static void send_ambi_arg(pj_cli_sess *sess,
}
for (i=0;i<info->hint_cnt;++i) {
if ((&hint[i].type) && (hint[i].type.slen > 0)) {
valid_type = PJ_TRUE;
pj_strcat2(&send_data, "\r\n ");
if ((&hint[i].type) && (hint[i].type.slen > 0)) {
if (pj_stricmp(&hint[i].type, &sc_type) == 0) {
if (is_process_sc) {
pj_strcat2(&send_data, ", ");
} else {
pj_strcat2(&send_data, "\r\n\t Shorcut: ");
is_process_sc = PJ_TRUE;
}
pj_strcat(&send_data, &hint[i].name);
parse_state = OP_SHORTCUT;
} else if (pj_stricmp(&hint[i].type, &choice_type) == 0) {
parse_state = OP_CHOICE;
} else {
is_process_sc = PJ_FALSE;
parse_state = OP_TYPE;
}
} else {
valid_type = PJ_FALSE;
is_process_sc = PJ_FALSE;
} else {
parse_state = OP_NORMAL;
}
switch (parse_state) {
case OP_CHOICE:
pj_strcat2(&send_data, "[");
pj_strcat(&send_data, &hint[i].name);
pj_strcat2(&send_data, "]");
break;
case OP_TYPE:
pj_strcat2(&send_data, "<");
pj_strcat(&send_data, &hint[i].type);
pj_strcat2(&send_data, ">");
break;
default:
pj_strcat(&send_data, &hint[i].name);
break;
}
if (!is_process_sc) {
pj_strcat2(&send_data, "\r\n\t");
if (valid_type) {
pj_strcat2(&send_data, "<");
pj_strcat(&send_data, &hint[i].type);
pj_strcat2(&send_data, ">");
} else {
pj_strcat(&send_data, &hint[i].name);
}
if ((&hint[i].desc) && (hint[i].desc.slen > 0)) {
if (!valid_type) {
for (j=0;j<(max_length-hint[i].name.slen);++j) {
pj_strcat2(&send_data, " ");
}
if ((&hint[i].desc) && (hint[i].desc.slen > 0)) {
if (parse_state != OP_TYPE) {
for (j=0;j<(max_length-hint[i].name.slen);++j) {
pj_strcat2(&send_data, " ");
}
pj_strcat2(&send_data, "\t");
pj_strcat(&send_data, &hint[i].desc);
}
pj_strcat2(&send_data, " ");
pj_strcat(&send_data, &hint[i].desc);
}
}
}
pj_strcat2(&send_data, "\r\n");
pj_strcat(&send_data, &fe->cfg.prompt_str);
if (with_last_cmd)

View File

@ -196,6 +196,17 @@ enum terminal_cmd
TC_DEL = 127
};
/**
* This specify the state of output character parsing.
*/
typedef enum out_parse_state
{
OP_NORMAL,
OP_TYPE,
OP_SHORTCUT,
OP_CHOICE
} out_parse_state;
/**
* This structure contains the command line shown to the user.
*/
@ -754,10 +765,10 @@ static void send_ambi_arg(cli_telnet_sess *sess,
char data[1028];
struct cli_telnet_fe *fe = (struct cli_telnet_fe *)sess->base.fe;
const pj_cli_hint_info *hint = info->hint;
pj_bool_t is_process_sc = PJ_FALSE;
pj_bool_t valid_type = PJ_FALSE;
out_parse_state parse_state = OP_NORMAL;
pj_ssize_t max_length = 0;
const pj_str_t sc_type = pj_str("SC");
static const pj_str_t sc_type = {"sc", 2};
static const pj_str_t choice_type = {"choice", 6};
send_data.ptr = &data[0];
send_data.slen = 0;
@ -778,46 +789,46 @@ static void send_ambi_arg(cli_telnet_sess *sess,
}
for (i=0;i<info->hint_cnt;++i) {
if ((&hint[i].type) && (hint[i].type.slen > 0)) {
valid_type = PJ_TRUE;
pj_strcat2(&send_data, "\r\n ");
if ((&hint[i].type) && (hint[i].type.slen > 0)) {
if (pj_stricmp(&hint[i].type, &sc_type) == 0) {
if (is_process_sc) {
pj_strcat2(&send_data, ", ");
} else {
pj_strcat2(&send_data, "\r\n\t Shorcut: ");
is_process_sc = PJ_TRUE;
}
pj_strcat(&send_data, &hint[i].name);
parse_state = OP_SHORTCUT;
} else if (pj_stricmp(&hint[i].type, &choice_type) == 0) {
parse_state = OP_CHOICE;
} else {
is_process_sc = PJ_FALSE;
parse_state = OP_TYPE;
}
} else {
valid_type = PJ_FALSE;
is_process_sc = PJ_FALSE;
} else {
parse_state = OP_NORMAL;
}
switch (parse_state) {
case OP_CHOICE:
pj_strcat2(&send_data, "[");
pj_strcat(&send_data, &hint[i].name);
pj_strcat2(&send_data, "]");
break;
case OP_TYPE:
pj_strcat2(&send_data, "<");
pj_strcat(&send_data, &hint[i].name);
pj_strcat2(&send_data, ">");
break;
default:
pj_strcat(&send_data, &hint[i].name);
break;
}
if (!is_process_sc) {
pj_strcat2(&send_data, "\r\n\t");
if (valid_type) {
pj_strcat2(&send_data, "<");
pj_strcat(&send_data, &hint[i].type);
pj_strcat2(&send_data, ">");
} else {
pj_strcat(&send_data, &hint[i].name);
}
if ((&hint[i].desc) && (hint[i].desc.slen > 0)) {
if (!valid_type) {
for (j=0;j<(max_length-hint[i].name.slen);++j) {
pj_strcat2(&send_data, " ");
}
if ((&hint[i].desc) && (hint[i].desc.slen > 0)) {
if (parse_state != OP_TYPE) {
for (j=0;j<(max_length-hint[i].name.slen);++j) {
pj_strcat2(&send_data, " ");
}
pj_strcat2(&send_data, "\t");
pj_strcat(&send_data, &hint[i].desc);
}
pj_strcat2(&send_data, " ");
pj_strcat(&send_data, &hint[i].desc);
}
}
}
pj_strcat2(&send_data, "\r\n");
pj_strcat(&send_data, &fe->cfg.prompt_str);
if (with_last_cmd)
@ -1290,7 +1301,7 @@ static pj_bool_t telnet_sess_on_data_read(pj_activesock_t *asock,
case ST_NORMAL:
if (*cdata == IAC) {
sess->parse_state = ST_IAC;
} else if (*cdata == '\b') {
} else if (*cdata == 127) {
is_valid = handle_backspace(sess, cdata);
} else if (*cdata == 27) {
sess->parse_state = ST_ESC;

View File

@ -89,6 +89,17 @@ static pj_status_t quit_app(pj_cli_cmd_val *cval)
return PJ_CLI_EEXIT;
}
static void get_codec_list(pj_cli_dyn_choice_param *param)
{
if (param->arg_id == 3) {
param->cnt = 2;
pj_strdup2(param->pool, &param->choice[0].value, "iLbc");
pj_strdup2(param->pool, &param->choice[0].desc, "iLbc Codec");
pj_strdup2(param->pool, &param->choice[1].value, "g729");
pj_strdup2(param->pool, &param->choice[1].desc, "g729 Codec");
}
}
static struct cmd_xml_t cmd_xmls[] = {
{"<CMD name='sayhello' id='1' sc=' ,h , ,, sh ,' desc='Will say hello'>"
" <ARG name='whom' type='text' desc='Whom to say hello to'/>"
@ -116,6 +127,13 @@ static struct cmd_xml_t cmd_xmls[] = {
" </CMD>"
"</CMD>",
NULL},
{"<CMD name='disable_codec' id='8' desc='Disable codec'>"
" <ARG name='codec_list' type='choice' id='3' desc='Codec list'>"
" <CHOICE value='g711' desc='G711 Codec'/>"
" <CHOICE value='g722' desc='G722 Codec'/>"
" </ARG>"
"</CMD>",
NULL},
{"<CMD name='quit_app' id='999' sc='qa' desc='Quit the application'>"
"</CMD>",
&quit_app},
@ -158,7 +176,7 @@ int main()
for (i = 0; i < sizeof(cmd_xmls)/sizeof(cmd_xmls[0]); i++) {
xml = pj_str(cmd_xmls[i].xml);
status = pj_cli_add_cmd_from_xml(cli, NULL, &xml,
cmd_xmls[i].handler, NULL, NULL);
cmd_xmls[i].handler, NULL, get_codec_list);
if (status != PJ_SUCCESS)
goto on_return;
}

View File

@ -28,5 +28,5 @@
* E.g.:
* #include "playfile.c"
*/
#include "clidemo.c"
#include "icedemo.c"