Git Product home page Git Product logo

Comments (14)

raimue avatar raimue commented on July 24, 2024 2

I doubt PS0 can ever be used for an implementation of preexec(). PS0 is treated as a prompt string, not a list of commands. The only way to inject commands is by substitution with $().

However, command substitutions run in their own subshell, therefore no variables in the original shell can be modified from this context. This would be different behavior than running commands in the trap handler as it is now, from where the state of the shell can be modified. Within PS0, commands can only print data for stdout, or at most write to file descriptors.

from bash-preexec.

d630 avatar d630 commented on July 24, 2024 1

I would go with something like:

foo ()
{ 
        for i in "${!BPX_PROMPT[@]}"
        do 
            printf '%s -> %s\n\r' "$i" "${BPX_PROMPT[$i]}"
        done
}

PS0='$(
        builtin unset -v BPX_PROMPT;
        builtin unset -f typeset;
        builtin unalias typeset 2>/dev/null;
        typeset -A BPX_PROMPT=(
                [h]="\h"
                [H]="\H"
                [j]="\j"
                [l]="\l"
                [s]="\s"
                [u]="\u"
                [v]="\v"
                [V]="\V"
                [w]="\w"
                [W]="\W"
                [\\!]="\!"
                [#]="\#"
                [\$]="\$"
                [d]="\d"
                [t]="\t"
                [T]="\T"
                [\\@]="\@"
                [A]="\A"

                [unixtime]="\D{%s}"
        );
        foo
)'

What is then:

! -> 1445
# -> 14
$ -> $
unixtime -> 1475483154
@ -> 09:25 AM
A -> 09:25
H -> ICH3
T -> 09:25:54
V -> 4.4.0
W -> ~
d -> Mon Oct 03
h -> ICH3
j -> 0
l -> 0
s -> bash
t -> 09:25:54
u -> user1
v -> 4.4
w -> ~

edit:

In bash 4.4 we can use "parameter transformation". Most of these prompt strings can then be expanded within the command substitution in PS0.

v='\T \W \#'
echo "${v@P}"

> 08:09:59 ~ 70

from bash-preexec.

rcaloras avatar rcaloras commented on July 24, 2024

@d630 thanks for opening! Was thinking about this when I saw http://superuser.com/a/1052132 a little while back. Probably makes sense to add some version detection and then hook into the appropriate interface.

from bash-preexec.

d630 avatar d630 commented on July 24, 2024

Ok, I have updated my repo to use PS0 only.

Note:
PSO is meant to be expanded; there is no PROMPT_COMMAND like thing for it. So we have to write something like PSO='$(preexec)'. Then there are the following problems:

  • BASH_COMMAND is unusable;
  • you can not set any further strings in PSO via preexec (you can set PS1 in precmd);
  • the command substitution removes the trailing newline.

from bash-preexec.

rcaloras avatar rcaloras commented on July 24, 2024

@d630 awesome. Giving it a look.

Could you elaborate on your second bullet?

  • you can not set any further strings in PSO via preexec (you can set PS1 in precmd);

Do you mean you can't alter PS0 itself while it's invoked?

from bash-preexec.

d630 avatar d630 commented on July 24, 2024

That's possible:

foo () { printf '%s\n\r' FOO; }
PSO='\h\n\T$(foo)'

PS0='$(printf "%s\n%s\n%s\n\r" \h \T FOO)'

But not:

foo () { printf '%s\n%s\n%s\n\r' \\h \\T FOO; }
PS0='$(foo)'

PSO='$(PS0=FOO)'

from bash-preexec.

d630 avatar d630 commented on July 24, 2024

Also possible:

foo () { printf '%s\n\r' "${paa[u]}" "${paa[V]}" "${pa[0]}" "$PROMPT_w" "$1"; }
PS0='$(declare -A paa=([u]="\u" [V]="\V"); pa=("\w") ;PROMPT_w="\w" foo "\H")'

from bash-preexec.

d630 avatar d630 commented on July 24, 2024

Thanks for pointing it out again. I think, it's obviously a preprompt, not preexecution thing!

PS0 will be set before the hole command line is beeing executed, which may also be a command list; it's expanded after the list from the line has been read. That is, you have only got access to the hole line (when you have enabled the command history feature). The DEBUG trap applies to every command pipeline from the list, just before their executions.

Even though you might have a similar thing like PROMPT_COMMAND for it, it wouldn't be useful without having access to the commands from the list, which will be executing. So, you also need a second thing like BASH_COMMAND, that indicates, which command is beeing read, right?!

Unfortunately yes, PS0 cannot replace the DEBUG trap.

from bash-preexec.

rcaloras avatar rcaloras commented on July 24, 2024

Ahh bummer, was really hoping to move to something more reliable than the DEBUG trap due to #25 Hopes dashed for now :/

from bash-preexec.

d630 avatar d630 commented on July 24, 2024

I have been thinking about the preexec hook for quite a while (again). Maybe I am wrong, but in the end I found, that PS0 cannot replace the DEBUG trap as key to emulate the zsh prexec itself, (since you need command substitution for functions in it) but with the help of Readline key sequences you can! I have just now updated my bpx repo. Check it out and let me know, what do you think!

from bash-preexec.

tycho-kirchner avatar tycho-kirchner commented on July 24, 2024

Haven't checked further but one idea could be to send a signal from the PS0-subshell.

test.sh:

counter=0

trap_handler(){
    counter=$((counter+1))
    echo "hi from trap_handler: $counter: $(history 1)" >&2

}


trap trap_handler SIGRTMIN

PS0='$(echo "sending signal... "; kill -SIGRTMIN  $$; )'

Terminal session:

$ source test.sh
$ echo ok
sending signal... hi from trap_handler: 1:  4118  echo ok
ok
$ echo two
sending signal... hi from trap_handler: 2:  4119  echo two
two
$

In the bash manual I don't see a dealbreaker:

If Bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes. When Bash is waiting for an asynchronous command via the wait builtin, the reception of a signal for which a trap has been set will cause the wait builtin to return immediately with an exit status greater than 128, immediately after which the trap is executed.

from bash-preexec.

akinomyoga avatar akinomyoga commented on July 24, 2024

The next version of Bash, 5.3 (still under development), supports function substitutions (and value substitutions) of the form ${ command; } (and ${| command; }), which are variants of the command substitution but executed in the main shell.

I guess PS0 can be combined to the value substitutions ${| command; } to provide a more robust preexec in Bash >= 5.3.

from bash-preexec.

d630 avatar d630 commented on July 24, 2024

ah, interesting. similiar to funsubs and valsubs in mksh, right?

from bash-preexec.

akinomyoga avatar akinomyoga commented on July 24, 2024

Right. Chet indeed mentioned mksh:

https://lists.gnu.org/archive/html/bug-bash/2023-05/msg00078.html

By the way, I wrote above that a value substitution can be used, but I noticed that the shell variable REPLY is rewritten and there is no way to prevent it. I now think function substitution should be used. Something like this:

PS0+='${ __bp_preexec_invoke_from_ps0 >/dev/tty; }'

One possible caveat of this approach is that preexec is executed before the PS0 content is output to the terminal, though I'm not sure if that is really an issue.

from bash-preexec.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.