tijagi
tijagi

Reputation: 1244

URxvt as a shell-to-run-things or how to exit bash by <Enter>, but execute string entered so far?

What am I looking for is a replacement for all those things you’ve probably seen by hitting Mod+R in various tiling WM or Alt+F2 in Gnome DE — a small window to run things from there. I feel very sad without having my bash aliases and other stuff missing because those shells (at least those ones I can use now) are non-interactive and their interactiveness can’t be set as an option at run time.

This is why I decided to use URxvt window as a ‘shell for one command’. In my WM I have Mod+R shortcut bound to execute

/bin/bash -c 'export ONE_COMMAND_SHELL=t && urxvt -name one_command_shell' 

And put

[ -v ONE_COMMAND_SHELL ] && bind -x '"\C-m":"exit"'

in my ~/.bashrc

This way I can distinguish an URxvt instance which will become ‘shell for one command’, and set C-m combination (yes, it also works for Enter) to exit the shell, and, therefore, URxvt. The problem is how to execute string entered so far before exit?

I found two potential clues:

a) Making use of BASH_COMMAND

BASH_COMMAND
     The command currently being executed or about to be executed,  unless  the
     shell  is executing a command as the result of a trap, in which case it is
     the command executing at the time of the trap.

But I didn’t get it working because

[ -v ONE_COMMAND_SHELL ] && bind -x '"\C-m":"exec $BASH_COMMAND exit"'

will cause exec exec exec.

b) A trap on SIGCHLD!

It may work for you, if you place

[ -v ONE_COMMAND_SHELL ] && {
    PS1=
    eaoc() { exit; }
    trap eaoc SIGCHLD
}

At the end of your ~/.bashrc. PS1 may be non-empty, but it may not have subshell calls, or the trap will execute and shell will exit before the prompt is to be generated. This holds URxvt open till the forked process exit, so may be considered a half-way to solution.

c) A trap to DEBUG.

DEBUG trap executes before any simple command to be executed and before the first command in each function. If we provide a number via OC_SHELL and will count the number of executed commands, like…

/bin/bash -c 'export OC_SHELL=0 && urxvt -name one_command_shell' 
# note a zero ----------------^

And at the end of ~/.bashrc

[ -v OC_SHELL ] && {
    export PS1=
    eaoc() { echo $OC_SHELL && [ $(( OC_SHELL++ )) -ge 1 ] && wait $! && exit; }
    trap eaoc DEBUG
}

We get a fail again. Because our process, forked like

$ gimp &

Dies with its parent. How to deal with it?

Interesting thing is that DEBUG trap executes right after the command was entered, this trap does not wait for a process to return its status code or pid of background process in case of using &.

Ok, that’s how create process independent of bash Need to somehow wrap entered string into (nohup … &)

Upvotes: 1

Views: 1404

Answers (1)

n. m. could be an AI
n. m. could be an AI

Reputation: 120031

This works for me:

one_command_execute() {
    eval $(echo "$READLINE_LINE") &
    exit
}

[ -v ONE_COMMAND_SHELL ] && bind -x '"\C-m":"one_command_execute"'

Another version is without eval:

one_command_checkexit() {
    [ -v ONE_COMMAND_DONE ] && exit
    ONE_COMMAND_DONE=1
}

[ -v ONE_COMMAND_SHELL ] && PROMPT_COMMAND=one_command_checkexit

This doesn't close the window until the command exits. To execute everything in background automatically, add:

[ -v ONE_COMMAND_SHELL ] && bind '"\C-m":" & \n"'

Upvotes: 1

Related Questions