Skip to content

Commit a55d39e

Browse files
committed
Add option to have peristent history
Signed-off-by: Yan Burman <[email protected]>
1 parent 417b901 commit a55d39e

File tree

3 files changed

+45
-4
lines changed

3 files changed

+45
-4
lines changed

examples/cli.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ int main(int argc, char *argv[])
160160
.history_size = 10,
161161
.app_name = "example_cli",
162162
.prompt = "my_cli",
163+
.hist_file = "/tmp/icli_history",
163164
.cmd_hook = cli_cmd_hook,
164165
.out_hook = cli_out_hook,
165166
.err_hook = cli_err_hook};

icli.c

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <assert.h>
3232
#include <sys/queue.h>
3333
#include <termios.h>
34+
#include <errno.h>
3435

3536
#include <editline/readline.h>
3637

@@ -71,7 +72,7 @@ struct icli {
7172
struct icli_command *curr_cmd;
7273
char *curr_prompt;
7374
const char *prompt;
74-
75+
const char *hist_file;
7576
int rows;
7677
int cols;
7778
int curr_row;
@@ -936,6 +937,7 @@ int icli_register_command(struct icli_command_params *params, struct icli_comman
936937
int icli_init(struct icli_params *params)
937938
{
938939
memset(&icli, 0, sizeof(icli));
940+
int ret = 0;
939941

940942
icli.root_cmd = calloc(1, sizeof(struct icli_command));
941943
if (!icli.root_cmd) {
@@ -951,20 +953,48 @@ int icli_init(struct icli_params *params)
951953
icli.user_data = params->user_data;
952954

953955
icli.prompt = strdup(params->prompt);
956+
if (!icli.prompt) {
957+
icli_api_printf("Unable to allocate memory for prompt\n");
958+
ret = -1;
959+
goto err;
960+
}
961+
962+
if (params->hist_file) {
963+
icli.hist_file = strdup(params->hist_file);
964+
if (!icli.hist_file) {
965+
icli_api_printf("Unable to allocate memory for hist_file\n");
966+
ret = -1;
967+
goto err;
968+
}
969+
}
954970

955971
icli.cmd_hook = params->cmd_hook;
956972
icli.out_hook = params->out_hook;
957973
icli.err_hook = params->err_hook;
958974

959975
/* Allow conditional parsing of the ~/.inputrc file. */
960976
rl_readline_name = strdup(params->app_name);
977+
if (!rl_readline_name) {
978+
icli_api_printf("Unable to allocate memory for rl_readline_name\n");
979+
ret = -1;
980+
goto err;
981+
}
961982

962983
/* Tell the completer that we want a crack first. */
963984
rl_attempted_completion_function = icli_completion;
964985

965986
using_history();
966987
stifle_history(params->history_size);
967988

989+
if (icli.hist_file) {
990+
ret = read_history(icli.hist_file);
991+
if (ret && ret != ENOENT) {
992+
icli_api_printf("Unable to read history from %s (%d)\n", icli.hist_file, ret);
993+
ret = -1;
994+
goto err;
995+
}
996+
}
997+
968998
rl_get_screen_size(&icli.rows, &icli.cols);
969999

9701000
icli_build_prompt(icli.curr_cmd);
@@ -977,7 +1007,7 @@ int icli_init(struct icli_params *params)
9771007
.argc = 1,
9781008
.argv = execute_args}};
9791009
struct icli_command *commands[array_len(cmd_params)] = {};
980-
int ret = icli_register_commands(cmd_params, commands, array_len(cmd_params));
1010+
ret = icli_register_commands(cmd_params, commands, array_len(cmd_params));
9811011
if (ret) {
9821012
goto err;
9831013
}
@@ -1001,8 +1031,6 @@ void icli_cleanup(void)
10011031
{
10021032
icli_clean_command(icli.root_cmd);
10031033

1004-
rl_callback_handler_remove();
1005-
10061034
HISTORY_STATE *hist_state = history_get_history_state();
10071035
HIST_ENTRY **mylist = history_list();
10081036

@@ -1012,13 +1040,24 @@ void icli_cleanup(void)
10121040
free(mylist);
10131041
free(hist_state);
10141042

1043+
if (icli.hist_file) {
1044+
int ret = write_history(icli.hist_file);
1045+
if (ret)
1046+
icli_api_printf("Unable to save history to %s (%d)\n", icli.hist_file, ret);
1047+
}
1048+
10151049
clear_history();
10161050

1051+
rl_callback_handler_remove();
1052+
10171053
free(rl_readline_name);
10181054
rl_readline_name = "";
10191055

10201056
free((void *)icli.prompt);
10211057
free((void *)icli.curr_prompt);
1058+
free((void *)icli.hist_file);
1059+
1060+
memset(&icli, 0, sizeof(icli));
10221061
}
10231062

10241063
void icli_run(void)

icli.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ struct icli_params {
5656
int history_size; /**< how many commands to keep in history */
5757
const char *app_name; /**< name of application for interfacing ~/.inputrc */
5858
const char *prompt; /**< prompt string (will be post-fixed by "> " */
59+
const char *hist_file; /**< history file to load/store history. can be NULL for not saving history */
5960
icli_cmd_hook_t cmd_hook; /**< hook to be called before command is executed */
6061
icli_output_hook_t out_hook; /**< hook to be called when there is output */
6162
icli_output_hook_t err_hook; /**< hook to be called when there is error print */

0 commit comments

Comments
 (0)