Skip to content

Commit bed2545

Browse files
committed
feat(esp_repl): Add esp_linenoise and esp_commands dependencies
1 parent 6553880 commit bed2545

File tree

7 files changed

+230
-79
lines changed

7 files changed

+230
-79
lines changed

esp_repl/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ set(srcs "esp_repl.c")
55
idf_component_register(
66
SRCS ${srcs}
77
INCLUDE_DIRS include
8-
PRIV_INCLUDE_DIRS private_include)
8+
REQUIRES test_esp_linenoise test_esp_commands)

esp_repl/esp_repl.c

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
/*
23
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
34
*
@@ -9,7 +10,8 @@
910
#include "freertos/semphr.h"
1011
#include "esp_repl.h"
1112
#include "esp_err.h"
12-
13+
#include "esp_commands.h"
14+
#include "esp_linenoise.h"
1315
typedef enum {
1416
ESP_REPL_STATE_RUNNING,
1517
ESP_REPL_STATE_STOPPED
@@ -32,10 +34,9 @@ typedef struct esp_repl_instance {
3234
} \
3335
} while(0)
3436

35-
esp_err_t esp_repl_create(esp_repl_instance_handle_t *handle, const esp_repl_config_t *config)
37+
esp_err_t esp_repl_create(esp_repl_instance_handle_t *handle, const esp_repl_config_t *config)
3638
{
37-
if ((config->executor.func == NULL) ||
38-
(config->reader.func == NULL) ||
39+
if ((config->linenoise_handle == NULL) ||
3940
(config->max_cmd_line_size == 0)) {
4041
return ESP_ERR_INVALID_ARG;
4142
}
@@ -106,7 +107,21 @@ esp_err_t esp_repl_stop(esp_repl_instance_handle_t handle)
106107
/* update the state to force the while loop in esp_repl to return */
107108
state->state = ESP_REPL_STATE_STOPPED;
108109

109-
/* Call the on_stop callback to let the user unblock reader.func, if provided */
110+
/* Call the abort function from esp_linenoise to force esp_linenoise_get_line to return.
111+
* This function is expected to return ESP_OK only if the user has registered a custom
112+
* read to the esp_linenoise instance and if the abort function succeeds.
113+
* ESP_ERR_INVALID_STATE is expected to be returned by esp_linenoise_abort if it is called
114+
* when the user has registered a custom read to the esp_linenoise instance. From the point
115+
* of view of esp_repl_stop, this return value if indicating that the user will have to take
116+
* care of returning from its own custom read by himself through the call of the on_stop callback,
117+
* therefore set the return value of esp_repl_stop to ESP_OK. */
118+
esp_err_t ret_val = esp_linenoise_abort(config->linenoise_handle);
119+
if (ret_val == ESP_ERR_INVALID_STATE) {
120+
ret_val = ESP_OK;
121+
}
122+
123+
/* Call the on_stop callback to let the user unblock esp_linenoise
124+
* if a custom read is provided */
110125
if (config->on_stop.func != NULL) {
111126
config->on_stop.func(config->on_stop.ctx, handle);
112127
}
@@ -117,7 +132,7 @@ esp_err_t esp_repl_stop(esp_repl_instance_handle_t handle)
117132
/* give it back so destroy can also take/give symmetrically */
118133
xSemaphoreGive(state->mux);
119134

120-
return ESP_OK;
135+
return ret_val;
121136
}
122137

123138
void esp_repl(esp_repl_instance_handle_t handle)
@@ -140,11 +155,22 @@ void esp_repl(esp_repl_instance_handle_t handle)
140155
* function is called. */
141156
xSemaphoreTake(state->mux, portMAX_DELAY);
142157

158+
esp_linenoise_handle_t l_hdl = config->linenoise_handle;
159+
esp_command_set_handle_t c_set = config->command_set_handle;
160+
143161
/* REPL loop */
144162
while (state->state == ESP_REPL_STATE_RUNNING) {
145163

146164
/* try to read a command line */
147-
const esp_err_t read_ret = config->reader.func(config->reader.ctx, cmd_line, cmd_line_size);
165+
const esp_err_t read_ret = esp_linenoise_get_line(l_hdl, cmd_line, cmd_line_size);
166+
167+
/* Add the command to the history */
168+
esp_linenoise_history_add(l_hdl, cmd_line);
169+
170+
/* Save command history to filesystem */
171+
if (config->history_save_path) {
172+
esp_linenoise_history_save(l_hdl, config->history_save_path);
173+
}
148174

149175
/* forward the raw command line to the pre executor callback (e.g., save in history).
150176
* this callback is not necessary for the user to register, continue if it isn't */
@@ -159,7 +185,7 @@ void esp_repl(esp_repl_instance_handle_t handle)
159185

160186
/* try to run the command */
161187
int cmd_func_ret;
162-
const esp_err_t exec_ret = config->executor.func(config->executor.ctx, cmd_line, &cmd_func_ret);
188+
const esp_err_t exec_ret = esp_commands_execute(c_set, cmd_line, &cmd_func_ret);
163189

164190
/* forward the raw command line to the post executor callback (e.g., save in history).
165191
* this callback is not necessary for the user to register, continue if it isn't */
@@ -181,4 +207,6 @@ void esp_repl(esp_repl_instance_handle_t handle)
181207
if (config->on_exit.func != NULL) {
182208
config->on_exit.func(config->on_exit.ctx, handle);
183209
}
210+
211+
printf("returned from get_line\n");
184212
}

esp_repl/idf_component.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ version: "1.0.0"
22
description: "esp_repl - Read Eval Print Loop component"
33
url: https://github.com/espressif/idf-extra-components/tree/master/esp_repl
44
dependencies:
5-
idf: ">=6.0"
5+
SoucheSouche/test_esp_linenoise:
6+
version: "*"
7+
registry_url: https://components-staging.espressif.com
8+
SoucheSouche/test_esp_commands:
9+
version: "*"
10+
registry_url: https://components-staging.espressif.com
611
sbom:
712
manifests:
813
- path: sbom_esp_repl.yml

esp_repl/include/esp_repl.h

Lines changed: 10 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,14 @@ extern "C" {
1111

1212
#include <stdbool.h>
1313
#include "esp_err.h"
14+
#include "esp_linenoise.h"
15+
#include "esp_commands.h"
1416

1517
/**
1618
* @brief Handle to a REPL instance.
1719
*/
1820
typedef struct esp_repl_instance *esp_repl_instance_handle_t;
1921

20-
/**
21-
* @brief Function prototype for reading input for the REPL.
22-
*
23-
* @param ctx User-defined context pointer.
24-
* @param buf Buffer to store the read data.
25-
* @param buf_size Size of the buffer in bytes.
26-
*
27-
* @return ESP_OK on success, error code otherwise.
28-
*/
29-
typedef esp_err_t (*esp_repl_reader_fn)(void *ctx, char *buf, size_t buf_size);
30-
31-
/**
32-
* @brief Reader configuration structure for the REPL.
33-
*/
34-
typedef struct esp_repl_reader {
35-
esp_repl_reader_fn func; /**!< Function to read input */
36-
void *ctx; /**!< Context passed to the reader function */
37-
} esp_repl_reader_t;
38-
3922
/**
4023
* @brief Function prototype called before executing a command.
4124
*
@@ -55,25 +38,6 @@ typedef struct esp_repl_pre_executor {
5538
void *ctx; /**!< Context passed to the pre-executor function */
5639
} esp_repl_pre_executor_t;
5740

58-
/**
59-
* @brief Function prototype to execute a REPL command.
60-
*
61-
* @param ctx User-defined context pointer.
62-
* @param buf Null-terminated command string.
63-
* @param ret_val Pointer to store the command return value.
64-
*
65-
* @return ESP_OK on success, error code otherwise.
66-
*/
67-
typedef esp_err_t (*esp_repl_executor_fn)(void *ctx, const char *buf, int *ret_val);
68-
69-
/**
70-
* @brief Executor configuration structure for the REPL.
71-
*/
72-
typedef struct esp_repl_executor {
73-
esp_repl_executor_fn func; /**!< Function to execute commands */
74-
void *ctx; /**!< Context passed to the executor function */
75-
} esp_repl_executor_t;
76-
7741
/**
7842
* @brief Function prototype called after executing a command.
7943
*
@@ -133,13 +97,14 @@ typedef struct esp_repl_on_exit {
13397
* @brief Configuration structure to initialize a REPL instance.
13498
*/
13599
typedef struct esp_repl_config {
136-
size_t max_cmd_line_size; /**!< Maximum allowed command line size */
137-
esp_repl_reader_t reader; /**!< Reader callback and context */
138-
esp_repl_pre_executor_t pre_executor; /**!< Pre-executor callback and context */
139-
esp_repl_executor_t executor; /**!< Executor callback and context */
140-
esp_repl_post_executor_t post_executor; /**!< Post-executor callback and context */
141-
esp_repl_on_stop_t on_stop; /**!< Stop callback and context */
142-
esp_repl_on_exit_t on_exit; /**!< Exit callback and context */
100+
esp_linenoise_handle_t linenoise_handle; /**!< Handle to the esp_linenoise instance */
101+
esp_command_set_handle_t command_set_handle; /**!< Handle to a set of commands */
102+
size_t max_cmd_line_size; /**!< Maximum allowed command line size */
103+
const char *history_save_path; /**!< Path to file to save the history */
104+
esp_repl_pre_executor_t pre_executor; /**!< Pre-executor callback and context */
105+
esp_repl_post_executor_t post_executor; /**!< Post-executor callback and context */
106+
esp_repl_on_stop_t on_stop; /**!< Stop callback and context */
107+
esp_repl_on_exit_t on_exit; /**!< Exit callback and context */
143108
} esp_repl_config_t;
144109

145110
/**

esp_repl/test_apps/main/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
idf_component_register(SRCS "test_esp_repl.c" "test_main.c"
23
PRIV_INCLUDE_DIRS "." "include"
34
PRIV_REQUIRES unity

0 commit comments

Comments
 (0)