1

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 … &)

Community
  • 1
  • 1
tijagi
  • 1,124
  • 1
  • 13
  • 31

1 Answers1

1

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"'
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • I’ve not even tried eval because it’s evil and has potential caveats with backslashes, but since I can’t find any bugs right now, let it be. – tijagi Mar 23 '13 at 19:30
  • PROMPT_COMMAND is awesome, but rebound C-m appends ' & ' again and again, so it’s impossible to enter the command. – tijagi Mar 23 '13 at 20:00
  • It works for me as is (if I replace `\n` with `\C-m` it indeed starts looping). – n. m. could be an AI Mar 23 '13 at 20:03
  • It’s strange, what version of bash do you use and what does `shopt -p` say? – tijagi Mar 23 '13 at 20:06
  • 4.2.37(1)-release; `shopt -p` is too long for a comment so it's [here](http://pastebin.com/k4fWyRTA) – n. m. could be an AI Mar 23 '13 at 20:10
  • My version of bash is exactly same and I brought options in accordance with yours and no luck. However I managed that the line `"\C-j": copy-region-as-kill` in ~/.inputrc was causing \n to be misinterpreted, though, I still cannot understand what happened. This function does not remove the region, it just copies its contents to the kill-ring buffer. – tijagi Mar 23 '13 at 20:56