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:
parent
f48b841e14
commit
e02d0df8f6
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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, ¶m->choice[0].value, "iLbc");
|
||||
pj_strdup2(param->pool, ¶m->choice[0].desc, "iLbc Codec");
|
||||
pj_strdup2(param->pool, ¶m->choice[1].value, "g729");
|
||||
pj_strdup2(param->pool, ¶m->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;
|
||||
}
|
||||
|
|
|
@ -28,5 +28,5 @@
|
|||
* E.g.:
|
||||
* #include "playfile.c"
|
||||
*/
|
||||
#include "clidemo.c"
|
||||
#include "icedemo.c"
|
||||
|
||||
|
|
Loading…
Reference in New Issue