Busybox: emulate line editing for read shell's built-in - shell

I need to develop a simple text interface for an embedded system with more or less only the Busybox installed on it.
For my purposes the read shell built-in would have sufficed. But the Busybox ash (or any other shell, they use the same code for the built-in) does not support line editing or initial text in the read built-in.
Does anybody knows of a way in Busybox's ash to emulate bash's read -e -i <initial-text> in a shell script?

For readline emulation, there's rlwrap assuming it can be made to fit on the embedded system. Invoke like so: rlwrap ash, which provides command line history and editing.
For read -e -i "foo" bar emulation, try:
read bar ; bar="foo$bar"

Related

How to bind clear to ^L in Ksh

How can i replicate the following bash functionality in KornShell:
bind "\C-l":"clear-screen"
I needed that bind because i'm using set -o vi in bash, and
plan on using it in ksh too.
Trying to use it in ksh prints out an error:
ksh: bind: not found
Sorry to break the news, but as you've noticed this a different between ksh and bash: bind or the ability to define key mappings is not there. Nor is programmable command completion. Historically the Korn shell focused on language design and features and not on interactive terminal capabilities.
GNU bash provides key bindings via the GNU Readline library which was developed and maintained by the same person, Chet Ramey. ksh even in its most recent versions doesn't use this library nor does it provide an equivalant library, as far as I know.
A workaround is to see if you can program the terminal to provide such capabilities. In tmux if you put this in your .tmux.conf configuration file:
bind-key C-l send-keys clear
Then tmux will interpret the Control-l before ksh has a chance to see it and will expand with the string "clear". (Underneath I bet tmux is using the GNU Readline library)
The POSIX standard (which ksh and bash both follow) defines an "alias" command. However an alias name isn't defined to allow control characters. A particular implemenation may do that, but ksh doesn't.
See also https://unix.stackexchange.com/questions/82223/how-to-setup-keyboard-shortcut-that-enters-predefined-text-into-x11-xterminal-vi

echo command color not working

I have a code like this:
#!/bin/bash
COLOR_REST='\e[0m'
COLOR_GREEN='\e[0;32m'
echo -e "${COLOR_GREEN}OK${COLOR_REST}"
When I copy and paste the code into my iTerm, it displays OK in the color of green.
However, when I store the code in a file named testColor.sh, and execute ./testColor.sh. It displays \e[0;32mOK\e[0m on my screen.
Why doesn't it display OK with green?
I've also tried bash testColor.sh, and sh testColor.sh. Both fail to display the text in green.
Another thing I feel strange is that I don't see the -e option in the BSD General Commands Manual in man echo.
I'm using macOS High Sierra as my operating system.
Use
#!/bin/bash
COLOR_REST="$(tput sgr0)"
COLOR_GREEN="$(tput setaf 2)"
printf '%s%s%s\n' $COLOR_GREEN 'OK' $COLOR_REST
which uses printf to avoid echo options and tput to be portable across different terminals.
Using printf instead of echo should work in any POSIX compliant shell. I tried this in High Sierra with the default terminal and it didn't work (there weren't any extended options, just -n).
As for an explanation, I haven't used iTerm so I'm not completely sure, but could be a different echo implementation by iTerm, which would cause the flag to work only when using iTerm itself, not /bin/bash. Notice that in the man page for echo, it says
NOTE: your shell may have its own version of echo, which usually supersedes the version described here. Please refer to your shell's documentation for details about the options it supports.
I am a fan of this syntax:
echo $'\e[31mRED\e[0m'
The $'...' notation causes the shell to honor escape codes e.g. \t, \n, \e.
This seems to work in bash, ksh, zsh, and sh -- yes, on MacOS.
The problem seems to be that Darwin's BSD-era /bin/echo does not actually accept -e argument at all. The zsh in recent versions of MacOS has a builtin echo that does take -e, but that's obviously not portable to other shells unless you want to run every shell script with zsh.

bash: vim mode instead of vi mode?

I noticed when in vi mode in bash (i.e. the mode enabled with "set -o vi"), that some commands, such as "diw", that work in vim but not in vi, don't work on the bash command line. Is there an easy way to configure bash so that its keybindings will support vim commands? I would like to be able to enter vim commands on the command line without having to actually start the vim program, as described in this question.
The best way of doing this that I know of would be to use athame.
It can be a surprisingly powerful experience in some cases. I particularly like it for interacting with a repl.
Athame patches your shell to add full Vim support by routing your keystrokes through an actual Vim process. Athame can currently be used to patch readline (used by bash, gdb, python, etc) and/or zsh (which doesn't use readline).
Alternatively I find spacemacs with the eshell to be a reasonably functional if strange solution.
Teach vi-command-mode diw to any software that uses readline (such as bash) by adding this to your ~/.inputrc:
set keymap vi-command
"diw": "bde"
First, the "vi mode" you get with set -o vi is not vi itself. It's an incomplete approximation of vi's behavior built into readline, the command-line editing library used by bash under the hood.
Second, because it is incomplete there's no reason whatsoever to expect every vi command to work.
Third, no, there's no "vim mode" so even less reason to expect any vim commands to work.
Fourth, if you absolutely want to edit the current command-line with Vim-like commands, why don't you go all the way and… actually use Vim:
<C-x><C-e>
That said, $ man readline tells you everything you need to customize its behavior and add bindings.
You can use ble.sh. Which is a command line editor written in pure Bash which replaces the default GNU Readline. I like to call it "zsh for bash".
Appart from vim-style navigation it gives you:
Enhanced completion
Syntax highlighting
Other interesting features
After installation don't forget to add (recommended) to your .bashrc:
# at the start of your .bashrc file
[[ $- == *i* ]] && source /usr/share/blesh/ble.sh --noattach
...
#for vim-style mode
set -o vi
...
#at the end of your .bashrc file
[[ ${BLE_VERSION-} ]] && ble-attach
or you can just:
# at the start of your .bashrc file
source /usr/share/blesh/ble.sh
but this may not work as expected - read this.

ZSH completion from script prompt (like BASH's read -e)

In a bash shell script you can prompt the user for input and enable readline completion for the user with the -e flag. (e.g. read -e -p 'GET YOUR FILE: ' file would allow a the user to use tab-completion to find the file.)
ZSH's completion is more advanced and extendable, so I hoped that I might be able to find a zsh builtin that allowed similar behavior.
I'm sure there's a better answer (I just recently started experimenting with zsh), but you can use vared.
$ vared -c line

Bash usage of vi or emacs

From a programming standpoint, when you set the bash shell to use vi or emacs via
set -o vi
or
set -o emacs
What is actually going on here? I've been reading a book where it claims the bash shell uses either of these editors for the input to the shell itself, but I thought it may have used readline.
Bash is still using readline. Readline uses either emacs or vi mode and setting the mode switches between the various editor modes. You can check the lib/readline folder in the base source code to see the various key bindings.
According to the man page BASH_BUILTINS(1) (on Fedora 8):
set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
... (skipping all the single letter options)
-o option-name
The option-name can be one of the following:
...
emacs Use an emacs-style command line editing interface. This is
enabled by default when the shell is interactive, unless the
shell is started with the --noediting option.
...
vi Use a vi-style command line editing interface.
I interpret that to mean that bash is directly interpreting the commands for line editing. This option simply sets which command set to use. See the man page for readline(3).
It uses the keystrokes that are familiar to users of one of those editors to edit the command line.
Readline is the facility that provides that feature to Bash and other programs.
From man bash:
READLINE
This is the library that handles reading input when using an interac‐
tive shell, unless the --noediting option is given at shell invocation.
Line editing is also used when using the -e option to the read builtin.
By default, the line editing commands are similar to those of emacs. A
vi-style line editing interface is also available. Line editing can be
enabled at any time using the -o emacs or -o vi options to the set
builtin (see SHELL BUILTIN COMMANDS below). To turn off line editing
after the shell is running, use the +o emacs or +o vi options to the
set builtin.
From what I know, readline is what provides the line-editing functionality for bash.
One proviso: when you press v in vi command mode, you get the full blown vi editor to edit your command line.
From man bash:
READLINE
This is the library that handles reading input when using an interactive shell, unless the --noediting option is given at shell invocation. By default, the line editing commands are similar to those of emacs. A vi-style line editing interface is also available. To turn off line editing after the shell is running, use the +o emacs or +o vi options to the set builtin.
When the shell presents you with a prompt (unless you're in non-editing mode), you're already using readline. You'll either be in emacs mode or vi insert mode (which is why you can just use ESC to get back to vi command mode).

Resources