2

I'm trying to write a bash script to pipe strings into rofi. These strings are continuously generated by a function gen_x.

The function gen_x sometimes (only when a condition is met) outputs new strings. I currently implement the gen_x-function with an if statement within an infinite loop. I want to pipe this function into rofi. When an item is selected within rofi, rofi should output the selected item and gen_x and rofi should end.

When using an infinite loop which outputs a new element every loop (as seen in gen_b), the script does exactly what I described above. However, when I implement an if statement in my function and only print a new element when the condition is true, the program never ends. I am unsure if this is due to gen_x or rofi.

Simplified code

gen_a(){ while true; do if [[ "$v" == "" ]]; then echo "Test"; v=1; fi; sleep 1; done }
gen_b(){ while true; do                             echo "Test";            sleep 1; done }

gen_a | rofi -dmenu # -> this outputs Test and does not end
gen_b | rofi -dmenu # -> this outputs Test and ends properly

Is there a way to use conditionals within the while-loop, and the program ending properly.

  • Please explain what you are expecting to happen, what you really need to do, because it isn't clear from your script. What does `rofi -dmenu` expect as input? What exactly are you trying to pipe to it? Neither of the functions you show would ever exit unless you kill them since both are `while true` with no exit condition. – terdon May 28 '23 at 18:10
  • your first steps seem nonsense regarding your problem. Please explain how this could contribute to the solution – Thibault LE PAUL May 28 '23 at 18:23
  • I reworded the post and took out the irrelevant parts. I hope it's better now. – Friendly Penguin 123 May 28 '23 at 18:47

1 Answers1

1

rofi doesn't switch to async mode before it has read 25 lines of input by default. That can be changed with the:

-async-pre-read [number] Read several entries blocking before switching to async mode

option.

So:

cmd | rofi -async-pre-read 1 -dmenu

For it to display a menu as soon as one line has been read from cmd.

When an item is selected, rofi will print it and terminate. cmd will be killed by a SIGPIPE thereafter the next time it writes something to stdout (which is now a broken pipe) as usual.

To kill it straight away, the common approach is to do:

sh -c 'echo "$$"; exec cmd' | {
  IFS= read -r pid
  rofi -async-pre-read 1 -dmenu
  kill -s PIPE "$pid"
}
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501