-
Notifications
You must be signed in to change notification settings - Fork 7.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ESP Linenoise] new esp linenoise with multiconsole support (IDFGH-9126) #10526
base: master
Are you sure you want to change the base?
[ESP Linenoise] new esp linenoise with multiconsole support (IDFGH-9126) #10526
Conversation
bb74e1e
to
57742bc
Compare
57742bc
to
785d059
Compare
3128014
to
2e24c0c
Compare
2e24c0c
to
cb3a3ef
Compare
Completely unrelated question: why do you often create new PRs instead of updating the ones you already opened? Isn't tracking progress one of the features of PRs? |
Thanks for the question. Its only if the old PR needs a huge rewrite. There's a few reasons:
Of course you can still look at all the old comments - I always link to it. So, this gives me the best of both approaches IMO. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the massive PR @chipweinberger!
I've taken the first look, the structure looks fine to me. To be honest, I have trouble reviewing esp_linenoise.c since I can't tell which code is the original one and which you have modified. I'll try to open both files side by side and do a more detailed review later.
A few other things:
-
Should we replace the usage of the old linenoise APIs in components/console/esp_console_repl.c with the new ones? Same for the examples?
-
Should the old APIs be marked as
__attribute__((deprecated, "please use esp_linenoise_xxxx instead"))
? If yes, this should also be mentioned under docs/en/migration-guides/release-5.x/5.1. -
Do the new APIs even need to be called "linenoise"? The name is cool, but frankly is not self-explanatory. Perhaps
esp_readline
oresp_lineedit
? Not sure about this, just an idea. Once we add a new public API, we can't change its name easily. -
Now that the functions don't use a global context, seems like we can unit test them quite easily? You definitely aren't expected to do this, but we would still need this before the PR can be merged internally.
-
Probably need to update the docs:
- add the new esp_linenoise.h header file to docs/doxygen/Doxyfile
- remove the mention of the old linenoise functions from docs/en/api-reference/system/console.rst
- add
.. include-build-file:: inc/esp_linenoise.inc
in the same file to add the generated API reference
Same as with the unit tests, you can leave the documentation changes to us, if you prefer.
Edit: I see I've missed this comment:
Trying to push this PR along. It is tested working. It would be great for an Espressif employee to do any necessary "finishing touches", any extra docs, desired code cleanup, small api changes, etc. It's difficult to merge large features as a 3rd party developer.
In that case, please ignore the "few other things" and the review nitpicks I've posted, we'll take over the PR. Thank you for the contribution!
@@ -184,27 +169,32 @@ static const cmd_item_t *find_command_by_name(const char *name) | |||
|
|||
esp_err_t esp_console_run(const char *cmdline, int *cmd_ret) | |||
{ | |||
if (s_tmp_line_buf == NULL) { | |||
return ESP_ERR_INVALID_STATE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably still need to return ESP_ERR_INVALID_STATE if esp_console_init wasn't called?
@@ -12,9 +12,7 @@ extern "C" { | |||
#include <stddef.h> | |||
#include "sdkconfig.h" | |||
#include "esp_err.h" | |||
|
|||
// Forward declaration. Definition in linenoise/linenoise.h. | |||
typedef struct linenoiseCompletions linenoiseCompletions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we keep this as a forward declaration instead of pulling in the dependency on esp_linenoise.h header?
*/ | ||
void esp_console_get_completion(const char *buf, linenoiseCompletions *lc); | ||
void esp_console_get_completion(const char *buf, esp_linenoise_completions_t *lc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to check: with this change, does the examples/system/console/advanced
example from IDF v5.0 compile okay with this brach?
(I assume the answer is "yes" since you didn't have to modify the example. Is that due to that `#include "esp_linenoise.h" above which you have added?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done my testing with the "basic" example. But I think you are correct.
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To reflect the copyrights and the actual license below, suggest:
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD | |
* | |
* SPDX-License-Identifier: Apache-2.0 | |
* SPDX-FileCopyrightText: 2010-2016 Salvatore Sanfilippo <antirez at gmail dot com> | |
* SPDX-FileCopyrightText: 2010-2013 Pieter Noordhuis <pcnoordhuis at gmail dot com> | |
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD | |
* | |
* SPDX-License-Identifier: BSD-2-Clause |
.state = {0} \ | ||
} | ||
|
||
struct esp_linenoise_t stdio = LINENOISE_DEFAULT; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it possible to avoid overriding the standard stdio
name?
(also, can this variable be static
, and prefixed with s_
?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes good point. I should have noticed this.
struct esp_linenoise_t def = LINENOISE_DEFAULT; | ||
esp_linenoise_handle_t handle = (esp_linenoise_handle_t) malloc(sizeof(struct esp_linenoise_t)); | ||
memcpy(handle, &def, sizeof(struct esp_linenoise_t)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
struct esp_linenoise_t def = LINENOISE_DEFAULT; | |
esp_linenoise_handle_t handle = (esp_linenoise_handle_t) malloc(sizeof(struct esp_linenoise_t)); | |
memcpy(handle, &def, sizeof(struct esp_linenoise_t)); | |
esp_linenoise_handle_t handle = (esp_linenoise_handle_t) malloc(sizeof(struct esp_linenoise_t)); | |
if (handle == NULL) { | |
return NULL; | |
} | |
*handle = (esp_linenoise_t) LINENOISE_DEFAULT; |
return handle; | ||
} | ||
|
||
char *esp_linenoise(esp_linenoise_handle_t handle, const char *prompt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
char *esp_linenoise(esp_linenoise_handle_t handle, const char *prompt) | |
char *esp_linenoise_get_line(esp_linenoise_handle_t handle, const char *prompt) |
or something like this — we don't have to keep the names 1:1 with the original version, and can make them more self-explanatory.
* | ||
* @returns the console command the user entered, or NULL if failure. | ||
*/ | ||
char* esp_linenoise(esp_linenoise_handle_t handle, const char *prompt); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All other functions return esp_err_t, perhaps we could apply the same treatment to this one?
char* esp_linenoise(esp_linenoise_handle_t handle, const char *prompt); | |
esp_err_t esp_linenoise_get_line(esp_linenoise_handle_t handle, const char *prompt, char** out_line); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I considered that strongly as well. I would be in favor of that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Preferably have the user pass the buffer. We would need to handle the linenoise wrapper differently - but that shouldn't be too hard tho. Just have the wrapper do the malloc.
esp_err_t esp_linenoise_get_line(esp_linenoise_handle_t handle, const char *prompt, char* out_line, size_t len);
* | ||
* @returns A new linenoise handle. | ||
*/ | ||
esp_linenoise_handle_t esp_linenoise_create(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
esp_linenoise_handle_t esp_linenoise_create(); | |
esp_linenoise_handle_t esp_linenoise_create(void); |
|
||
|
||
/** | ||
* @brief Linenoise does not necessarily allocate with malloc. Any memory returned by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This maybe was true for the original library, is this still necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had the same thought. Ideally we should eliminate returning memory that we allocate ourself, IMO.
esp_err_t esp_linenoise_get_line(esp_linenoise_handle_t handle, const char *prompt, char* out_line, size_t len);
Yes, let me push a new change that splits this into 2 commits, so that there is a diff. edit: nvm, seems you are okay taking this over!
Eventually! That's a lot for single PR!
My vote would be to deprecate it in 5.2. More specifically, I don't have time to do the above ^^ in the 5.1 release window, but perhaps Espressif has the time!
Hmm! My vote is keep the
Could they use the '0' handle? I have this written so that handle '0' uses a global context. That might be controversial, but it makes the linenoise wrappers very easy to write. |
bump |
This looks great, I'd really like this to land in preparation of better console support. Good work, @chipweinberger! |
Also asking for a bump on this PR. I'd like to implement a second console on my system, with separate commands (as its used for a separate kind of user), and this is a first step towards making that easier. |
Related PR: #9998
Adds new
esp_linenoise_x
functions.Side Comment: Trying to push this PR along. It is tested working. It would be great for an Espressif employee to do any necessary "finishing touches", any extra docs, desired code cleanup, small api changes, etc. It's difficult to merge large features as a 3rd party developer. That said, I've gotten the PR as close to mergable as I can.
Motivation:
Features:
stdin
&stdout
redirection supporterrno == EWOULDBLOCK
, to (eventually) support console deinitialization. see: [Console] fix console deinit: add ability to unblock linenoise, to fix deinit deadlock (IDFGH-8529) #9983Code Changes:
esp_linenoise.c
/esp_linenoise.h
- now contains the majority of the linenoise codelinenoise/linenoise.c
/linenoise/linenoise.h
- for compatibility, just wrapsesp_linenoise.c
commands.c
- support callingesp_console_run()
on multiple independent threads.Tested:
Future:
fputc