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.

3
  • 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, 2023 at 18:10
  • your first steps seem nonsense regarding your problem. Please explain how this could contribute to the solution May 28, 2023 at 18:23
  • I reworded the post and took out the irrelevant parts. I hope it's better now. May 28, 2023 at 18:47

1 Answer 1

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"
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .