junegunn / fzf

:cherry_blossom: A command-line fuzzy finder
https://junegunn.github.io/fzf/
MIT License
64.3k stars 2.38k forks source link

--preview-window=auto to place the preview window based on terminal size #3817

Closed mmahmoudian closed 4 months ago

mmahmoudian commented 4 months ago

Checklist

Output of fzf --version

0.51.0 (260a65b0)

OS

Shell

Problem / Steps to reproduce

At the moment fzf allows position to be defined as:

POSITION: (default: right)
    up
    down
    left
    right

It would be super handy and useful to be able to have auto value too. This way if the terminal is vertical (row counts >> col counts) it defaults to down instead of right. This is extra valuable for people who use tiling for their terminals.

This issue is vaguely similar to #1558

LangLangBart commented 4 months ago

This way if the terminal is vertical (row counts >> col counts) it defaults to down instead of right.

Did you experiment with the alternative preview window layout ? [^1]

# If the width of the preview window is smaller than 50 columns,
# it will be displayed above the search window.
fzf --preview 'cat {}' --preview-window 'right,50%,border-left,<50(up,30%,border-bottom)'

[^1]: CHANGELOG.md 0.31.0

mmahmoudian commented 4 months ago

@LangLangBart Thanks for pointing it out. The issue with this is that it only accepts number of columns as an integer and not ratio, therefore, it doesn't behave smoothly when someone is tiling the terminal. For instance when you use Fibonacci layout, in many tiles you get less than 50 columns, but some of those have horizontal orientations and some some have vertical. My suggestion is more about ratio by comparing col count vs. row count to determine is the terminal is "wide" or "tall".

LangLangBart commented 4 months ago

Thanks for adding more context. There is one way it may already work with the current version of fzf using the resize[^1] event coupled with the transform[^2] action and some environment variables exported by fzf.

However, it can become quite lengthy, depending on the level of detail you wish to include.

look foo |
  fzf --preview 'echo {}' \
    --bind 'resize:transform:
    (((FZF_COLUMNS / FZF_LINES) <= 1)) && echo "change-preview-window:up,30%,border-bottom"
    (((FZF_COLUMNS / FZF_LINES) > 1)) && echo "change-preview-window:right,50%,border-left"
    '

The maintainer provided a useful example of how one can declare a variable called transformer in their .zshrc/.bashrc and assign it to the resize event in the changelog example 0.46.0.

So, you could try this until the maintainer joins this discussion.

[^1]: CHANGELOG.md 0.46.0 [^2]: CHANGELOG.md 0.45.0

junegunn commented 4 months ago

Thanks @LangLangBart.

resize:transform is the way to go. While it can be a bit verbose, it allows you to fine-tune the condition as you wish.

Aspect ratio alone is not going to be enough. You may want to determine the layout depending on the absolute values of lines and columns, and you may want to have more than one alternative layout, for example

  1. If the aspect ratio is >= 1.5 and the width of the screen is wider than 120 columns, show the preview window on the right
  2. If the aspect ratio is < 1.5 and the height of the screen is taller than 40 lines, show it on the top
  3. Otherwise, don't show the preview window

A fixed scheme provided by auto option won't have such flexibility.

TRANSFORMER='
  echo -n change-preview-window:
  if ((100 * FZF_COLUMNS / FZF_LINES >= 150)) && ((FZF_COLUMNS >= 120)); then
    echo "right,50%,border-left"
  elif ((FZF_LINES >= 40)); then
    echo "up,30%,border-bottom"
  else
    echo "hidden"
  fi
'

fzf --bind "start:transform($TRANSFORMER),resize:transform($TRANSFORMER)" --preview 'cat {}'