1
man -k . | fzf -e --tiebreak=begin | awk '{print $1}' | xargs man -Tpdf | zathura -
# searches for a man page and then outputs it as pdf to zathura

This command lets the user choose a man page, and then displays the page.  It works great, other than zathura starting blank while it waits for the user to make their selection, which leads to zathura getting input.  It is really annoying having to change focus from zathura back to the terminal and then back to zathura.

I am fairly new to scripting so I thought that there might be a way around this that I just don't know about.

Preferably not ifne.

Lampros
  • 143

4 Answers4

2

That's the whole point of pipe lines to run commands concurrently with pipes in between them.

For commands to run sequentially, you'd need pipes of infinite size, or resort to storing output into temporary files.

With zsh, that can be done with:

zathura =(
  man -k . |
   fzf -e --tiebreak=begin |
   awk '{print $1}' |
   xargs -rd '\n' man -Tpdf
)

(here adding the GNU-specific -r and -d '\n' options as we don't want the default parsing mode of xargs and don't want to run man if there's no input).

Where =(cmd) expands to the path of a temporary file than contains the output of the cmd once cmd has returned (a third form of process substitution specific to zsh). The temporary file is automatically removed once the zathura command returns.

1

Perhaps I'm missing something here — I'd never heard of fzf (or zathura, for that matter) before I saw this question, and I don't have them on my system to test with.  But … isn't the point of fzf to pick an item from a list?  Let me rephrase that: isn't the point of fzf to pick one item from a list?  Isn't xargs overkill here?  Isn't the logic basically

select a man page
and then display it

?

The fzf page at GitHub suggests using $(fzf args).  The following should work:

mp=$(man -k . | fzf -e --tiebreak=begin | awk '{print $1}')  &&  [ -n "$mp" ]  &&
                man -Tpdf "$mp" | zathura - &

to read the user-selected man page from the user input and then display it.  No need for an (explicit) temporary file.  (Add 2> /dev/null if you believe that it's beneficial.)

0

I "solved" my problem , I redirected output to my /tmp/ directory and then had zathura read from there . I also put it all in a script .

   #!/bin/sh
   d=$(date +'%M_%S');
   man -k . | fzf -e --tiebreak=begin | awk '{print $1}' | xargs man -Tpdf > /tmp/man_${d};
   zathura /tmp/man_${d} 2> /dev/null &

EDIT : Not really a Solution ,please don't use this

Lampros
  • 143
  • 1
    Creating files with predictable names in /tmp is bad practice from a security standpoint (an attacker could create symlinks man_{0..60}_{0..60} symlinks to your ~/.zshrc for instance and cause that output to be stored there). – Stéphane Chazelas Apr 06 '21 at 13:15
0
#!/bin/sh
name=$( man -k . | fzf +i -e --tiebreak=begin | awk '{print ($2,$1)}' | tr -d "()")
if [ -n "$name" ]; then
man -Tpdf $(echo $name) | zathura - &
fi

After thinking better about it I came up with this, works great and now supports all manpages (takes in to consideration the label of the man page e.g 1p ls)

G-mans answer seems more sophisticated , and without the extra functionality mentioned above ( as it was never asked for , understandably ) .

Lampros
  • 143