Re: [RFC] edit: Add basic support for input line editing

Marcel Holtmann <[email protected]> Wed, 13 Dec 2023 23:26:00 +0100
Newsgroups dev.linux.lists.ell
Message-ID <[email protected]>
Hi Grant,

>>> This allows for simple line editing with history capabilities. On
>>> purpose this has no concept of terminal input or terminal output and
>>> just allows manipulation of an internal wide character string.
>>> 
>>> The history storing and loading is currently missing, but would be easy
>>> to add. The other two items are missing completion and hints handling.
>>> 
>>> This feature is not yet complete, but good enough for a first review and
>>> a sample application using it in a curses environment will follow.
>>> 
>>> The debug option is something that might need to be removed or at least
>>> changed a little bit, but right now it is nice to see the internal
>>> states.
>> 
>> Marcel,
>> 
>> Any reason not to build on / improve linenoise or to put a neutralizing wrapper around libedit / readline as ntp did / does?
>> 
>> Each have their deficiencies, of course. However, it seems like, at least linenoise and libedit are close enough where a delta would be smaller than a rewrite-from-scratch.
> 
> I should have added, the four most important features for the use cases I have are:
> 
>    1. Run loop integration / non-blocking on input (libcurl and libcares have reasonable APIs for this that make them well adaptable to just about any run loop infrastructure, including glib or CoreFoundation).
>    2. Initial input buffer population.
>    3. Dynamic prompt generation (basically, there’s a function call every time the prompt is refreshed or displayed—the implementer can decide whether to return a static string or on-the-fly-composed buffer).
>    4. Passphrase mode (generate asterisks, spaces, nulls, or bullets on input of confidential information).
> 
> TUI / CLI-based network setup motivates most of the above, for example:
> 
>    Running networking setup…
>        Setting up Ethernet...
>            Checking Ethernet availability...
>                Ethernet is available.
>                Enabling Ethernet networking by default...
>        Setting up Wi-Fi...
>            Checking Wi-Fi availability…
>                Wi-Fi is available.
>            Enable Wi-Fi networking (0|N-No, 1|Y-Yes) [Y]? Y
>            Already connected to Wi-Fi network “Northern Gaze”.
>                Add to, replace, or use the Wi-Fi network “Northern Gaze” (A-Add, R-Replace, U-Use) [U]? A
> 
>    [ … ]
> 
>                        Enter the passphrase for "Robust Ground": **********
>                            Associating with the "Robust Ground" Wi-Fi access point...done.
>                            Configuring IP addresses...done.
>                            Confirming Internet reachability...done.
>                        Successfully connected to Wi-Fi network "Robust Debt".
> 
> The custom, on-the-fly prompts are "Enable Wi-Fi networking (0|N-No, 1|Y-Yes) [Y]?”, "Add to, replace, or use the Wi-Fi network “Northern Gaze” (A-Add, R-Replace, U-Use) [U]?”, and “Enter the passphrase for "Robust Debt":". The pre-populated, editable input buffers are “Y” and “A”, respectively. The passphrase mode is “**********”.
> 
> libedit makes (2) and (3) very easy. linenoise makes (1) easy and (4) partially achievable. Neither can do all of those, at least easily.

I really need to clean up my Curses demo to show you how I envision this. I can easily add 2) actually. I left it out since I couldn’t find a use for it, but fair enough. And 3) and 4) really belong into the caller. Especially if you go fancy with colors or other attributes. It is so much easier for the the caller to get right than for the line editing.

What you missed is a 5) that restricts the input to a certain length. And I am still debating if a minimal length is useful as well, but then I really need to implement the hints support first.

Regards

Marcel