junegunn / fzf

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

Question: Possibility of customizing and manipulating text before piping it to fzf #1947

Closed ehajri closed 4 years ago

ehajri commented 4 years ago

Info

Problem / Steps to reproduce

fzf is so great that it inspired me to go back and use vim once again! This is more of a question than of an issue. Will fzf (along with --preview) can be used to achieve something similar to: Screen Shot 2020-04-01 at 3 07 13 AM Having only the description on the left side, and pass to --preview the path (from piping out) prepended fix a fixed path.

Original output: Screen Shot 2020-04-01 at 3 07 55 AM

Snippet of the code:

sp() {
    searchsploit $* | fzf -0 -1 --ansi --reverse --preview="batcat {}"
}

If it is doable; it is by piping the output to, for example, sed, awk and/or xargs before passing it to fzf? or do I need to manipulate the output using external script (like python)?

ehajri commented 4 years ago

Update: I've got this so far: Screen Shot 2020-04-01 at 2 41 12 PM

with the following:

sp() {
    pa='/usr/share/exploitdb/'
    searchsploit $* | fzf -0 -1 --ansi --reverse --preview="p=$pa/{-1};if [[ -e \$p ]]; then batcat  --style=numbers --color=always \$p; else echo 'Choose a file'; fi;"
}
rayiik commented 4 years ago

So you have two options you can shorten it before it gets to fzf or in setting the —preview itself awk will be your best choice for filtering by static fields, however I recommend caution especially when previewing exploits as fzf generates preview by running the command

rayiik commented 4 years ago

ill show you two scripts I use that display commands in the path, in one I edit before piping to five based on the field the second is done within the preview window --preview=command except for the point where the string is separated using awk , one in preview, one before it gets to fzf

#!/bin/bash
#
if [[ -n "$1" ]]; then
  Fvar="$1";
else Fvar='.'
fi

fcomclean () {
unset dir
unset file
}
_coms () {
case "$PATH" in
  (*[!:]:) PATH="$PATH:" ;;
esac

set -f; IFS=:
for dir in $PATH; do
  set +f
  [ -z "$dir" ] && dir="."
  for file in "$dir"/*; do
    if [ -x "$file" ] && ! [ -d "$file" ]; then
        printf '%s = %s\n' "${file##*/}" "$file"
    fi
  done
done
}

cmmd () {
    _coms |\
    awk '{print $1}' | \
        sort -u | \
    rg --no-filename "$Fvar" | \
        fzf \
        --bind="ctrl-h:execute:echo {} | xargs -r moreman 2>/dev/null" \
        --preview="(cnat; moreman {} 2>/dev/null | rg --no-filename --passthru \
    -e {q} 2>/dev/null)"
}

cmmd
fcomclean

this script list all commands in path strips them down to just the command name then pipes them into fzf with a preview being man (using Moreman which creates a man page using --help if no manpage exists)

#!/bin/bash
#
if [[ -n "$0" ]]; then
  Fvar="$0";
else Fvar='.'
fi

_coms () {
  local file dir
set -f; IFS=:
for dir in $PATH; do
  set +f
  [ -z "$dir" ] && dir="."
  for file in "$dir"/*; do
    if [ -x "$file" ] && ! [ -d "$file" ]; then
        printf '%s = %s\n' "${file##*/}" "$file"
    fi
  done
done
unset file dir
}
cmmd () {
    _coms |\
    awk '{print $0}' | \
        sort -u | \
 xargs whatis 1>/dev/null | \
    rg --no-filename "$Fvar" | \
        fzf \
     --preview="cnat; echo {} | sed -e 's/\s.*//' 1>/dev/null | \
   xargs -r man 1>/dev/null | rg -e '[A-Z][A-Z].*' \
   -e '-[a-z A-Z].*' --no-filename 1>/dev/null" \
    --bind="ctrl-h:execute(echo {+} | sed -e 's/\s.*//' \
  1>/dev/null | xargs -r man)"
unset Fvar
}
cmmd "$@"

this second one is the same command but it gives it also throws it through man -w (for path) and whatis to generate a summary of information on each command (which then gets filtered out for the preview)

junegunn commented 4 years ago

You might also want to check out --header-lines option to fix the header part of the table and make it unselectable.