WIP w/o TIOCSTIO: bash OK, zsh PROBLEM; 3.0.0 version file changes.

This commit is contained in:
Martin Dvorak 2023-04-02 22:44:10 +02:00
parent 07298947a7
commit 611eecbae8
16 changed files with 432 additions and 95 deletions

View file

@ -1,6 +1,6 @@
2023-03-19 Martin Dvorak <martin.dvorak@mindforger.com>
2023-04-02 Martin Dvorak <martin.dvorak@mindforger.com>
* Released v2.7.0 - important fix release ensuring that HSTR will work
* Released v3.0.0 - important fix release ensuring that HSTR will work
on operating systems and Linux kernels without TIOCSTI support.
2022-12-11 Martin Dvorak <martin.dvorak@mindforger.com>

View file

@ -4,7 +4,7 @@
# Contributor: Busindre <busilezas at busindre.com>
pkgname=hstr
pkgver=2.7
pkgver=3.0
pkgrel=1
pkgdesc="A command line utility that brings improved BASH command completion from the history. It aims to make completion easier and more efficient than Ctrl-r."
arch=('x86_64'

View file

@ -6,7 +6,7 @@ The following HSTR versions are currently being supported with security updates.
| Version | Supported |
| -------- | ------------------ |
| 2.7.0 | :white_check_mark: |
| 3.0.0 | :white_check_mark: |
| 2.6.0 | :white_check_mark: |
| 2.5.0 | :white_check_mark: |
| 2.4.0 | :white_check_mark: |

View file

@ -147,8 +147,8 @@ then
exit 1
fi
export ARG_BAZAAR_MSG="HSTR 2.7.0"
export ARG_VERSION="2.7.0"
export ARG_BAZAAR_MSG="HSTR 3.0.0"
export ARG_VERSION="3.0.0"
# Debian releases: https://www.debian.org/releases/
# 6/7/8/9/10: squeeze wheezy jessie stretch buster

View file

@ -20,7 +20,7 @@
# This script is available from http://www.mindforger.com/fedora/fedora-rpm-from-deb.sh
# to be easily available in VMs
export MFVERSION="2.7.0"
export MFVERSION="3.0.0"
export MFPRJNAME="hstr-${MFVERSION}"
export AMD64NAME="hstr_${MFVERSION}-1_amd64"
export I386NAME="hstr_${MFVERSION}-1_i386"

View file

@ -20,7 +20,7 @@
export SCRIPT_HOME=`pwd`
export HSTR_VERSION="2.7.0"
export HSTR_VERSION="3.0.0"
export NOW=`date +%Y-%m-%d--%H-%M-%S`
export GH_RELEASE_DIR=~/p/hstr/release

View file

@ -163,8 +163,8 @@ then
exit 1
fi
export ARG_BAZAAR_MSG="Release 2.7"
export ARG_MAJOR_VERSION=2.7.
export ARG_BAZAAR_MSG="Release 3.0"
export ARG_MAJOR_VERSION=3.0.
export ARG_MINOR_VERSION=1 # minor version is incremented for every Ubuntu version
# https://wiki.ubuntu.com/Releases

View file

View file

@ -20,7 +20,7 @@
AC_PREREQ([2.69])
AC_INIT(hstr, 2.7.0, martin.dvorak@mindforger.com)
AC_INIT(hstr, 3.0.0, martin.dvorak@mindforger.com)
AC_CONFIG_FILES([Makefile src/Makefile man/Makefile])
# Check src dir existence.

View file

@ -62,6 +62,6 @@ hstrdebug {
QMAKE_LINK = gcc
# TIOCSTI debugging:
#DEFINES += DEBUG_NO_TIOCSTI
DEFINES += DEBUG_NO_TIOCSTI
message(DEFINES of hstr.pro build: $$DEFINES)

View file

@ -51,9 +51,9 @@
</Company_Info>
<Program_Info>
<Program_Name>HSTR</Program_Name>
<Program_Version>2.7.0</Program_Version>
<Program_Release_Month>3</Program_Release_Month>
<Program_Release_Day>19</Program_Release_Day>
<Program_Version>3.0.0</Program_Version>
<Program_Release_Month>4</Program_Release_Month>
<Program_Release_Day>2</Program_Release_Day>
<Program_Release_Year>2023</Program_Release_Year>
<Program_Cost_Dollars />
<Program_Cost_Other_Code>USD</Program_Cost_Other_Code>

View file

@ -137,7 +137,7 @@
// major.minor.revision
static const char* VERSION_STRING=
"hstr version \"2.7.0\" (2023-03-19T18:15:00)"
"hstr version \"3.0.0\" (2023-04-02T18:50:00)"
"\n";
static const char* HSTR_VIEW_LABELS[]={
@ -180,52 +180,13 @@ static const char* INSTALL_BASH_CODE_PREFIX=
"\n# if this is interactive shell, then bind hstr to Ctrl-r (for Vi mode check doc)";
// zsh doc: http://zsh.sourceforge.net/Guide/zshguide.html
static const char* INSTALL_ZSH_STRING=
static const char* INSTALL_ZSH_CODE_PREFIX=
"\n# HSTR configuration - add this to ~/.zshrc"
"\nalias hh=hstr # hh to be alias for hstr"
"\nsetopt histignorespace # skip cmds w/ leading space from history"
// HISTFILE should not be needed - HSTR must work on blank environment as well
// "\nexport HISTFILE=~/.zsh_history # ensure history file visibility"
"\nexport HSTR_CONFIG=hicolor # get more colors"
#if defined(__MS_WSL__)
// TODO binding to be rewritten for zsh@WSL as it's done for bash - hstr_winwsl() like function to be implemented to make it work on WSL
"\n# Function and binding below is bash script that makes command completion work under WSL."
"\n# If you can rewrite the function and binding from bash to zsh please send it to martin.dvorak@mindforger.com"
"\n# so that I can share it with other users."
"\n#function hstr_winwsl {"
"\n# offset=${READLINE_POINT}"
"\n# READLINE_POINT=0"
"\n# { READLINE_LINE=$(</dev/tty hstr ${READLINE_LINE:0:offset} 2>&1 1>&$hstrout); } {hstrout}>&1"
"\n# READLINE_POINT=${#READLINE_LINE}"
"\n#}"
"\n#bindkey -s \"\\C-r\" \"\\eqhstr_winwsl\\n\""
"\n"
"\nbindkey -s \"\\C-r\" \"\\eqhstr\\n\" # bind hstr to Ctrl-r (for Vi mode check doc)"
#elif defined(__CYGWIN__)
// TODO binding to be rewritten for zsh@Cygwin as it's done for bash - hstr_cygwin() like function to be implemented to make it work under Cygwin
"\n# Function and binding below is bash script that makes command completion work under Cygwin."
"\n# If you can rewrite the function and binding from bash to zsh please send it to martin.dvorak@mindforger.com"
"\n# so that I can share it with other users."
"\n#function hstr_cygwin {"
"\n# offset=${READLINE_POINT}"
"\n# READLINE_POINT=0"
"\n# { READLINE_LINE=$(</dev/tty hstr ${READLINE_LINE:0:offset} 2>&1 1>&$hstrout); } {hstrout}>&1"
"\n# READLINE_POINT=${#READLINE_LINE}"
"\n#}"
"\n#bindkey -s \"\\C-r\" \"\\eqhstr_cygwin\\n\""
"\n"
"\nbindkey -s \"\\C-r\" \"\\eqhstr\\n\" # bind hstr to Ctrl-r (for Vi mode check doc)"
#else
"\nbindkey -s \"\\C-r\" \"\\C-a hstr -- \\C-j\" # bind hstr to Ctrl-r (for Vi mode check doc)"
#endif
// TODO try variant with args/pars separation
//"\nbindkey -s \"\\C-r\" \"\\eqhstr --\\n\" # bind hstr to Ctrl-r (for Vi mode check doc)"
// alternate binding options in zsh:
// bindkey -s '^R' '^Ahstr ^M'
// bindkey -s "\C-r" "\C-a hstr -- \C-j"
"\n\n";
"\nexport HSTR_CONFIG=hicolor # get more colors";
static const char* HELP_STRING=
"Usage: hstr [option] [arg1] [arg2]..."
@ -396,32 +357,21 @@ void print_bash_install_code(void)
} else {
printf(
#if defined(__MS_WSL__)
// IMPROVE commands are NOT executed on return under win10 > consider hstr_utils changes
// Script hints:
// {...} is inline group ~ lambda function whose vars are visible to the other commands
// V=$(c) executes commands and stores it to var V
"\nfunction hstrwsl {"
"\n offset=${READLINE_POINT}"
"\n READLINE_POINT=0"
"\n { READLINE_LINE=$(</dev/tty hstr ${READLINE_LINE:0:offset} 2>&1 1>&$hstrout); } {hstrout}>&1"
"\n READLINE_POINT=${#READLINE_LINE}"
"\n}"
"\nif [[ $- =~ .*i.* ]]; then bind -x '\"\\C-r\": \"hstrwsl\"'; fi"
#elif defined(__CYGWIN__)
"\nfunction hstrcygwin {"
"\n offset=${READLINE_POINT}"
"\n READLINE_POINT=0"
"\n { READLINE_LINE=$(</dev/tty hstr ${READLINE_LINE:0:offset} 2>&1 1>&$hstrout); } {hstrout}>&1"
"\n READLINE_POINT=${#READLINE_LINE}"
"\n}"
"\nif [[ $- =~ .*i.* ]]; then bind -x '\"\\C-r\": \"hstrcygwin\"'; fi"
#else
"\nfunction hstrnotiocsti {"
"\n offset=${READLINE_POINT}"
"\n READLINE_POINT=0"
"\n { READLINE_LINE=$(</dev/tty hstr ${READLINE_LINE:0:offset} 2>&1 1>&$hstrout); } {hstrout}>&1"
#endif
"\n READLINE_LINE=\"$(hstr ${READLINE_LINE})\""
"\n READLINE_POINT=${#READLINE_LINE}"
"\n}"
#if defined(__MS_WSL__)
"\nif [[ $- =~ .*i.* ]]; then bind -x '\"\\C-r\": \"hstrwsl\"'; fi"
#elif defined(__CYGWIN__)
"\nif [[ $- =~ .*i.* ]]; then bind -x '\"\\C-r\": \"hstrcygwin\"'; fi"
#else
"\nif [[ $- =~ .*i.* ]]; then bind -x '\"\\C-r\": \"hstrnotiocsti\"'; fi"
#endif
);
@ -433,11 +383,43 @@ void print_bash_install_code(void)
void print_zsh_install_code(void)
{
printf("%s", INSTALL_ZSH_CODE_PREFIX);
if(is_tiocsti) {
printf(
"\nbindkey -s \"\\C-r\" \"\\C-a hstr -- \\C-j\" # bind hstr to Ctrl-r (for Vi mode check doc)"
"\nexport HSTR_TIOCSTI=y"
);
} else {
printf(
#if defined(__MS_WSL__)
"\nhstr_wsl() {"
#elif defined(__CYGWIN__)
"\nhstr_cygwin() {"
#else
"\nhstr_notiocsti() {"
#endif
"\n BUFFER=\"$(hstr ${BUFFER})\""
"\n CURSOR=${#BUFFER}"
"\n zle redisplay"
"\n}"
#if defined(__MS_WSL__)
"\nzle -N hstr_wsl"
"\nbindkey '\\C-r' hstr_wsl"
#elif defined(__CYGWIN__)
"\nzle -N hstr_cygwin"
"\nbindkey '\\C-r' hstr_cygwin"
#else
"\nzle -N hstr_notiocsti"
"\nbindkey '\\C-r' hstr_notiocsti"
#endif
);
printf("\nexport HSTR_TIOCSTI=n");
}
printf("\n\n");
}
unsigned recalculate_max_history_items(void)
@ -1748,13 +1730,13 @@ void hstr_getopt(int argc, char **argv)
hstr_exit(EXIT_SUCCESS);
break;
case 'z':
printf("%s", INSTALL_ZSH_STRING);
print_zsh_install_code();
hstr_exit(EXIT_SUCCESS);
break;
case 's':
// ZSH_VERSION is not exported by zsh > detected by parent process name
if(is_zsh_parent_shell()) {
printf("%s", INSTALL_ZSH_STRING);
print_zsh_install_code();
} else {
print_bash_install_code();
}

View file

@ -39,9 +39,9 @@
#define MAX(a,b) (((a)>(b))?(a):(b))
// TIOCSTI is an acronym for "Terminal Input Output Control STack Input",
// and it is a system call used in Unix-like operating systems.
// The TIOCSTI system call allows to insert data into the input buffer
// of a terminal as if it had been typed by the user.
// and it is a system call used in Unix-like operating systems. The TIOCSTI
// system call allows to insert data into the input buffer of a terminal
// as if it had been typed by the user.
//
// TIOCSTI is NOT available on:
// - Linux kernel >=6.2.0
@ -49,22 +49,25 @@
// - WSL
//
// HSTR uses TIOCSTI to insert a command chosen by the user in HSTR
// to shell prompt.
// to shell prompt - if TIOCSTI is available. Otherwise shell features
// must be used.
//
// HSTR run:
// HSTR modus operandi:
//
// - user runs `hstr` command
// - `hstr` checks whther TIOCSTI is supported by the kernel or not
// - if SUPPORTED, then HSTR continues as it will be able to insert
// any chosen command into bash prompt
// - if NOT supported, then:
// - HSTR checks for HSTR_TIOCSTI environment variable:
// - if it is NOT defined, then it prints error and asks
// - `hstr` checks whether TIOCSTI is supported by the kernel or not
// - if TIOCSTI SUPPORTED, then HSTR continues as it is able to insert
// any chosen command into Bash/Zsh prompt
// - if TIOCSTI NOT supported, then:
// - HSTR checks for `HSTR_TIOCSTI` environment variable:
// - if `HSTR_TIOCSTI` is NOT defined, then it prints an error and asks
// user to configure HSTR (--show-configuration >> .*rc)
// - if it is DEFINED, then:
// - if `HSTR_TIOCSTI` is DEFINED, then:
// - if it is SET to `n`, then HSTR presumes that it has
// been configured (shell function is defined) and continues > DONE
// - OTHERWISE it prints error and ask user to configure HSTR
// been configured and that the shell function (which replaces TIOCSTI)
// is defined > HSTR uses the function to insert command > DONE
// - OTHERWISE HSTR prints and error and ask user to configure HSTR
// with --show-configuration >> .*rc
//
// HSTR features related to TIOCSTI
//

View file

@ -0,0 +1,191 @@
#!/usr/bin/env bash
# This script is used to experiment with Bash functions in order to set
# the content of the terminal prompt without TIOCSTI ioctl() call.
#
# IMPORTANT: to use the functions below @ Bash
#
# - check the bind command at the end of the file
# in order to control which function to use
# - source this file in the current shell
# . ./tiotcsi-functions.h
# - use ^R to test the function
# ORIGINAL FUNCTION VERSION
#
# - function contributed by a HSTR user for Cygwin
# - Bash only (does not work in Zsh)
# - I don't understand {hstrout} trick (actually I do, however, it seems to work in non-interactive mode only)
function hstrcygwin {
offset=${READLINE_POINT}
READLINE_POINT=0
{ READLINE_LINE=$(</dev/tty hstr ${READLINE_LINE:0:offset} 2>&1 1>&$hstrout); } {hstrout}>&1
READLINE_POINT=${#READLINE_LINE}
}
# MY FUNCTION VERSION
#
# - hstr gets current prompt string using READLINE_LINE
# - function sets what to show by changing the content of READLINE_LINE
# - ... which is much simpler than the original function, but is it good enough?
function foohstr {
echo "hstr-cmd-out ${1}"
}
function mysimple {
# prompt command content BEFORE
PROMPT_STR_BEFORE=${READLINE_LINE}
# cursor position at prompt BEFORE
PROMPT_LNG_BEFORE=${READLINE_POINT}
# HSTR gets PROMPT_STR_BEFORE
# HSTR prints out command which user selected after using ^
# ^ is set to READLINE_LINE
# prompt cursor is set to the end of line by setting READLINE_POINT to 1000 (blindly)
{ READLINE_LINE=$(foohstr ${PROMPT_STR_BEFORE}) 2>&1; }
# move cursor to the end of prompt
READLINE_POINT=${#READLINE_LINE}
}
# EXPERIMENTAL LAB
#
# - understanding bash-fu
function hstrdebug {
# content of the current terminal prompt
echo "Readline line : '${READLINE_LINE}'"
# how many characters is @ current terminal prompt
echo "Readline point: '${READLINE_POINT}'"
READLINE_POINT=0
# OBSERVATIONS:
# {hstrout}>&1 ... is VALID expression
# {hstrout} > &1 ... is INVALID expression
# command:
# - runs $() and redirects 2 and 1 to STDOUT
#{ READLINE_LINE=$(echo COMMAND) 2>&1 1>&$hstrout; } {hstrout}>&1
# - < /dev/tty
# ... read what is @ current prompt from /dev/tty (but I could use READLINE_LINE for it!)
# - offset=${READLINE_POINT}
# ... how long is the string @ prompt
# - ${READLINE_LINE:0:offset}
# ... substring of prompt from 0 to cursor position
# { READLINE_LINE=$(< /dev/tty echo ${READLINE_LINE:0:offset}) 2>&1; }
# store read line lenghth to read line POINT to set curser to the end of line
READLINE_POINT=${#READLINE_LINE}
# in principle I can do and it will have the same effect
# READLINE_POINT=1000
# after:
echo "Readline line : '${READLINE_LINE}'"
echo "Readline point: '${READLINE_POINT}'"
}
#
# BINDING
#
# bind '"\C-r": "\C-a hstr -- \C-j"'
# - bind
# ... Bash command which binds key sequence (Ctrl-r) to a command,
# bind INSERTS the command to the terminal
# - "\C-r"
# ... key sequence to bind
# - "\C-a hstr -- \C-j"
# ... command to execute ~ text to be inserted to the terminal:
# \C-a ... moves cursor to the beginning of line
# hstr -- ... inserts "hstr -- " to the terminal
# \C-j ... RUNs the command by INSERTing new line
# (without Ctrl-j, text would be just inserted, but not run)
# bind -x '"\C-r": "hstrfunction"'
# ... Bash command which binds key sequence (Ctrl-r) to a command,
# bind INSERTS the command to the terminal
# - -x
# ... enables READLINE_LINE and READLINE_POINT
# - hstrfunction
# ... function which uses READLINE_LINE and READLINE_POINT variables
#
#
# IMPORTANT bind -x
#
# - bind -x must be used in order to enable READLINE_LINE, READLINE_POINT
# - see also: https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#index-READLINE_005fLINE
#
# READLINE_LINE
# The contents of the Readline line buffer, for use with bind -x (see Bash Builtin Commands).
#
# READLINE_POINT
# The position of the insertion point in the Readline line buffer, for use with bind -x (see Bash Builtin Commands).
if [[ $- =~ .*i.* ]]; then bind -x '"\C-r": "mysimple"'; fi
#if [[ $- =~ .*i.* ]]; then bind -x '"\C-r": "hstrdebug"'; fi
#if [[ $- =~ .*i.* ]]; then bind -x '"\C-r": "hstrcygwin"'; fi
# ##################################################################
#
# EXAMPLE: WORKING insert into prompt
#
function mytest {
READLINE_LINE="XYZ"
READLINE_POINT=3
}
bind -x '"\C-r": "mytest"'
# ##################################################################
#
# EXAMPLE: WORKING foo HSTR w/ a lot of debugs
#
# get terminal input > send it to HSTR > get command from HSTR > insert it
function foohstr {
echo "CMD_BY_HSTR: >>>${1}<<<"
}
function hstrdebug {
# content of the current terminal prompt
echo "Readline line : '${READLINE_LINE}'"
# how many characters is @ current terminal prompt
echo "Readline point: '${READLINE_POINT}'"
TO_SET=$(foohstr ${READLINE_LINE})
READLINE_POINT=0
# insert text to terminal
echo "Setting: '${TO_SET}'"
READLINE_LINE="${TO_SET}"
# store read line length to read line POINT to set cursor to the end of line
READLINE_POINT=${#READLINE_LINE}
# after:
echo "Readline line : '${READLINE_LINE}'"
echo "Readline point: '${READLINE_POINT}'"
}
bind -x '"\C-r": "hstrdebug"'
# ##################################################################
#
# EXAMPLE: WORKING minimal production version w/ foo HSTR
function foohstr {
echo "CMD_BY_HSTR: >>>${@}<<<"
}
function hstrnotiocsti {
READLINE_LINE="$(foohstr ${READLINE_LINE})"
READLINE_POINT=${#READLINE_LINE}
}
bind -x '"\C-r": "hstrnotiocsti"'
# eof

View file

@ -0,0 +1,61 @@
#!/usr/bin/env bash
# ##################################################################
# EXAMPLE: NOT WORKING version
# Define a function to replace a word in the current line
replace-word() {
local oldword newword
zle -I # switch to insert mode
read -k "oldword?Enter word to replace: "
read -k "newword?Enter replacement word: "
BUFFER=${BUFFER//$oldword/$newword} # replace old word with new word
zle redisplay # update the display
}
# Bind the function to a key sequence
bindkey '^Xr' replace-word
# ##################################################################
#
# EXAMPLE: WORKING version w/ foo HSTR
foohstr() {
echo "command-by-hstr-${1}"
}
hstrnotiocsti() {
local word
# we need the WHOLE buffer, not just 0 to cursor: word=${BUFFER[0,CURSOR]}
BUFFER="$(foohstr ${BUFFER})"
CURSOR=${#BUFFER}
# update the display
zle redisplay
}
# create ZLE widget ~ readline function
zle -N hstrnotiocsti
# bind widget to keyboard shortcut
bindkey '\C-r' hstrnotiocsti
# ##################################################################
#
# EXAMPLE: WORKING minimal production version w/ foo HSTR
# PROBLEM!
# - active ZLE takes over the terminal, therefore HSTR cannot be run
# - w/o ZLE it is not possible to insert text into the terminal
foohstr() {
echo "command-by-hstr-${1}"
}
hstrnotiocsti() {
BUFFER="$(foohstr ${BUFFER})"
CURSOR=${#BUFFER}
zle redisplay
}
zle -N hstrnotiocsti
bindkey '\C-r' hstrnotiocsti
# eof

View file

@ -0,0 +1,100 @@
#!/bin/bash
# group commands in a sub-shell: ( )
# (list)
# group commands in the CURRENT shell: { }
# { list; }
# test - return the binary result of an expression: [[ ]]
# [[ expression ]]
# arithmetic expansion
# $(( expression ))
# (( expression ))
# { can be used to GROUP output of multiple commands into one BLOB
# - https://www.linux.com/topic/desktop/all-about-curly-braces-bash/
# - ; to separate commands
# - executed in the curren shell
{ echo a; echo B; echo c; }
echo "-------------------"
# string operations @ var
MY_VAR="abcde"
echo ${MY_VAR:0:1} # a
echo ${MY_VAR:0:2} # ab
echo ${MY_VAR:0:3} # abc
echo "-------------------"
# new and suggested execution
MY_VAR="$(pwd)"
echo $MY_VAR
# Bash bind:
#
# bash -x keyseq:shell-command
# Cause SHELL-COMMAND to be executed when KEYSEQ is entered
#
# Bash VARIABLES doc:
#
# READLINE_LINE
# The contents of the Readline line buffer, for use with bind -x
# READLINE_POINT
# The position of the insertion point in the Readline line buffer, for use with bind -x
#
echo "Readline line : '${READLINE_LINE}'"
echo "Readline point: '${READLINE_POINT}'"
# TODO
# TODO
# TODO
# TODO ^ must be tested @ .bashrc @ bind -x where these variable are set (not set elsewhere)
# TODO
# TODO
echo "- expression: ------------------"
# TODO
# execute COMMAND in the CURRENT shell and store it to variable READLINE_LINE
#{ READLINE_LINE=$(echo COMMAND) 2>&1 1>&$hstrout; } {hstrout} > &1
echo "^------------------"
#
# DECODING CRAZY EXPRESSION
#
# { READLINE_LINE=$(</dev/tty hstr ${READLINE_LINE:0:offset} 2>&1 1>&$hstrout); } {hstrout}>&1
echo "- expression 1: ------------------"
# execute COMMAND in the CURRENT shell and store it to variable READLINE_LINE
{ READLINE_LINE=$(echo COMMAND); }
echo $READLINE_LINE
echo "^------------------"
# read input for the command from file
grep abc < without-tiotcsh.sh
# EQUIVALENT way how to write it (reads input for command from file):
< without-tiotcsh.sh grep abc
echo "- expression 2: ------------------"
# execute COMMAND in the CURRENT shell and store it to variable READLINE_LINE
# {hstrout} >&1
# ... run command which is in the hstrout
function myfun {
# { READLINE_LINE=$(echo COMMAND) 2>&1 1>&$hstrout; } {hstrout} >&1
hstrout=ls
{ READLINE_LINE=$(echo COMMAND) 2>&1 1>&$hstrout; } {hstrout}
}
myfun
echo "^------------------"
# CMD > &${hstrout}
# ... redirect standard output of the command CMD to the FILE whose name is stored in hstrout variable
################################################################################
# zsh version by fzf
#
# https://github.com/junegunn/fzf/blob/c387689d1cd45f0d8eb122fe95ee72ccc61d3bff/shell/key-bindings.bash#L41
# eof