• fuzzy completion in bash
    • $ cat **<tab>
    • $ unset **<tab>
    • $ unalias **<tab>
    • $ export **<tab>
    • $ ssh **<tab>
    • $ kill -9 **<tab>
  • fzf

[!NOTE|label:references:]

fzf and vim
1.4.1.1.1 -- fzf and vim

install

[!NOTE|label:references:]

$ brew install fzf fd
$ type -P fzf >/dev/null && eval "$(command fzf --bash)"
# -- or --
$ ln -sf $(brew --prefix fd)/share/bash-completion/completions/fd "$(brew --prefix)"/etc/bash_completion.d/fd

# linux
$ DOWNLOAD_URL="$(curl -fsSL https://api.github.com/repos/junegunn/fzf/releases/latest | jq --arg pattern "linux_$(dpkg --print-architecture)" -r '.assets[] | select(.name | contains($pattern)) | .browser_download_url')"
$ curl -fsSL "${DOWNLOAD_URL}" | sudo tar xz -C /usr/local/bin/ fzf
$ sudo chmod +x /usr/local/bin/fzf
$ command fzf --bash > /usr/share/bash-completion/completions/fzf
$ sudo apt install fd
# -- cleanup --
$ rm -rf /tmp/fzf.tar.gz
# config
FZF_DEFAULT_OPTS="${FZF_DEFAULT_OPTS:+$FZF_DEFAULT_OPTS} "
FZF_DEFAULT_OPTS+="--height 35% --min-height 8+ "             # https://github.com/junegunn/fzf/issues/4226
FZF_DEFAULT_OPTS+="--layout=reverse --multi --cycle --ansi --gutter ' ' "
FZF_DEFAULT_OPTS+="--marker='󱍢 ' --pointer='▌' "
FZF_DEFAULT_OPTS+="--prompt='󰩀 ' --info='inline: 󰨿 ' "
FZF_DEFAULT_OPTS+="--info-command='printf \"\x1b[33;1m%s\x1b[m ~ %s\" \"\$FZF_POS\" \"\$FZF_INFO\"' "
FZF_DEFAULT_OPTS+="--bind 'ctrl-s:select-all,ctrl-d:deselect-all,ctrl-t:toggle-all' "
FZF_DEFAULT_OPTS+="--bind 'ctrl-y:execute-silent(/bin/echo -n {+} | ${COPY})' "
FZF_DEFAULT_OPTS+="--color=gutter:0,bg+:-1,query:italic,spinner:#e6db74,prompt:#404945,header:italic:#504945,info:#928374,pointer:#A66584,marker:#d79921,fg:#ebdbb2:dim,fg+:#A7A44E:regular,hl:#845069:italic,hl+:#A66584:bold:italic"

FZF_DEFAULT_COMMAND="fd --type f "
FZF_DEFAULT_COMMAND+="--strip-cwd-prefix "
FZF_DEFAULT_COMMAND+="--hidden "
FZF_DEFAULT_COMMAND+="--follow "
FZF_DEFAULT_COMMAND+="--exclude .git --exclude node_modules"

export FZF_DEFAULT_OPTS FZF_DEFAULT_COMMAND
fzf color themes
1.4.1.1.2 -- fzf color themes
fzf color theme: gruvbox-marslo
1.4.1.1.3 -- fzf color theme: gruvbox-marslo
NAME VALUE
pointer , , , , , , , ,
# -- or --
FZF_DEFAULT_OPTS+="--prompt='󰝗 ' --info='inline: 󰉾 ' "

# -- or --
FZF_DEFAULT_OPTS+="--prompt='ᑹ ∷ ' "
# or
FZF_DEFAULT_OPTS+="--prompt='󰊠 ' "

# -- or --
FZF_DEFAULT_OPTS+='--style full --layout reverse '
FZF_DEFAULT_OPTS+='--header-lines-border bottom --no-list-border '

# -- or --
FZF_DEFAULT_OPTS+="--no-bold "

# -- or --
FZF_DEFAULT_OPTS+="--color=fg+:#ebdbb2,pointer:#e6db74,hl+:#fb4934,prompt:#334D35"
older version of FZF environment variable
FZF_DEFAULT_OPTS="--height 35%"
FZF_DEFAULT_OPTS+=" --layout=reverse"
FZF_DEFAULT_OPTS+=" --pointer='→' --marker='» ' --prompt='$ '"
FZF_DEFAULT_OPTS+=" --multi"
FZF_DEFAULT_OPTS+=" --inline-info"
FZF_DEFAULT_OPTS+=" --color=spinner:#e6db74,hl:#928374,fg:#ebdbb2,header:#928374,info:#504945,pointer:#98971a,marker:#d79921,fg+:#ebdbb2,prompt:#404945,hl+:#fb4934"

FZF_DEFAULT_COMMAND="fd --type f"
FZF_DEFAULT_COMMAND+=" --strip-cwd-prefix"
FZF_DEFAULT_COMMAND+=" --hidden"
FZF_DEFAULT_COMMAND+=" --follow"
FZF_DEFAULT_COMMAND+=" --exclude .git --exclude node_modules"
  • install from source code for wsl

    [!NOTE|label:this solution for install latest fzf in wsl]

    $ git clone git@github.com:junegunn/fzf.git
    $ bash -x install --all
    $ sudo cp bin/fzf* /usr/local/bin/
    
  • offline install

    [!NOTE]

    • curl: (60) SSL certificate problem: self-signed certificate in certificate chain:

      $ curl -fL https://github.com/junegunn/fzf/releases/download/0.44.1/fzf-0.44.1-linux_amd64.tar.gz
      curl: (60) SSL certificate problem: self-signed certificate in certificate chain
      More details here: https://curl.se/docs/sslcerts.html
      
      curl failed to verify the legitimacy of the server and therefore could not
      establish a secure connection to it. To learn more about this situation and
      how to fix it, please visit the web page mentioned above.
      
    • How to fix curl: (60) SSL certificate: Invalid certificate chain
    • ~/.curlrc

      $ echo '--insecure' >> ~/.curlrc
      
    • offline installation

      ################ for offline installation only ################
      # check current version for offline installation
      $ uname -sm
      Linux x86_64
      
      # download correct package according https://github.com/junegunn/fzf/blob/master/install#L170
      # i.e.: Linux x86_64 -> fzf-$version-linux_amd64.tar.gz
      $ cp fzf-0.42.0-linux_amd64.tar.gz /tmp/fzf.tar.gz
      
      # modify install script `try_curl` function to not download but use local tar.gz directly
      $ cat << 'EOF' | git apply --inaccurate-eof --ignore-whitespace
      diff --git a/install b/install
      index 5ac191b..342bc49 100755
      --- a/install
      +++ b/install
      @@ -115,10 +115,8 @@ link_fzf_in_path() {
      try_curl() {
       command -v curl > /dev/null &&
       if [[ $1 =~ tar.gz$ ]]; then
      -    curl -fL $1 | tar -xzf -
      -  else
      -    local temp=${TMPDIR:-/tmp}/fzf.zip
      -    curl -fLo "$temp" $1 && unzip -o "$temp" && rm -f "$temp"
      +    local temp=${TMPDIR:-/tmp}/fzf.tar.gz
      +    tar -xzf "$temp" && rm -rf "$temp"
       fi
      }
      EOF
      
      ### or modify manually ###
      # try_curl() {
      #   command -v curl > /dev/null &&
      #   if [[ $1 =~ tar.gz$ ]]; then
      #     local temp=${TMPDIR:-/tmp}/fzf.tar.gz
      #     tar -xzf "$temp" && rm -rf "$temp"
      #   fi
      # }
      ################ for offline installation only ################
      

shortcuts

[!NOTE|label:references:]

KEYSTROKE BASH FUNCTION ZSH FUNCTION ENVIRONMENT VARIABLE
CTRL-t __fzf_select__ __fsel FZF_CTRL_T_COMMAND
CTRL-r __fzf_history__ fzf-history-widget FZF_CTRL_R_OPTS
ALT-c __fzf_cd__ fzf-cd-widget FZF_ALT_C_COMMAND

action and select

OPEN SELECT ALL DESELECT ALL TOGGLE ALL MULTIPLE SELECT
ctrl + s ctrl + d ctrl + t
shift +

movement

PREVIOUS NEXT MULTIPLE SELECT
ctrl + k ctrl + j
ctrl + p ctrl + n shift +
ctrl + k ctrl + j

ctrl-t

[!TIP]

  • file list:

    PREVIOUS NEXT CHANGE PREVIEW WINDOWS
    ctrl + /
    ctrl + k ctrl + j
    ctrl + p ctrl + n
  • preview content:

    PREVIOUS NEXT
    shift + shift +
    ctrl + ctrl +
    ctrl + p ctrl + n

usage

[!NOTE|label:references:]

magic vim

[!TIP]

  • vim()

    vim()
    # usage: eval "$( _load_fzf_context )"
    #        ... | fzf "${fzfopt[@]}"
    function _load_fzf_context() {
      local -a CAT=( "$(type -P cat)" )
      type -P bat >/dev/null && CAT=( "$(type -P bat)" --theme='Nord' --color=always --line-range :500 )
      local previewCmd="if file -bL --mime-encoding {} | grep -iq 'binary' && ! iconv -f utf-8 -t utf-8 {} >/dev/null 2>&1; then file -bL {}; else ${CAT[*]} {}; fi"
      local -a fzfopt=( --exit-0
                        --height 50%
                        --multi --cycle
                        --preview "${previewCmd}"
                        --preview-window 'right,60%,nowrap,rounded,+15'
                        --bind 'ctrl-/:toggle-preview'
                        --bind='ctrl-o:execute(bat {} > /dev/tty)'
                      )
      typeset -p fzfopt
    }
    
    # magic vim    : fzf list in recent modified order
    # @author      : marslo
    # @source      : https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh
    # @description :
    #   - if `nvim` installed using `nvim` instead of `vim`
    #     - using `-v` to force using `vim` instead of `nvim` even if nvim installed
    #   - if `vim` commands without parameters, then call fzf and using vim to open selected file
    #   - if `vim` commands with parameters
    #       - if single parameters and parameters is directory, then call fzf in target directory and using vim to open selected file
    #       - otherwise call regular vim to open file(s)
    #   - to respect fzf options by: `type -t _fzf_opts_completion >/dev/null 2>&1 && complete -F _fzf_opts_completion -o bashdefault -o default vim`
    # shellcheck disable=SC2155
    function vim() {                           # magic vim - fzf list in most recent modified order
      local -a voption=()
      local orgv=false                         # force using vim instead of nvim
    
      local -a fdopt=( --type f --hidden --follow --unrestricted --ignore-file "$HOME/.fdignore" )
      test -d "${1:-}" && [[ "$1" == "." || "$1" == ./* ]] && fdopt+=( --strip-cwd-prefix )
    
      local -a ignores=(
        '*.pem' '*.p12'
        '*.png' '*.jpg' '*.jpeg' '*.gif' '*.svg' '*.ico' '*.pdf' '*.mp4' '*.mp3'
        '*.zip' '*.tar' '*.gz' '*.bz2' '*.xz' '*.7z' '*.rar'
        '*.o' '*.a' '*.so' '*.ko' '*.bin' '*.exe' '*.dll' '*.dylib'
        '*.pyc' '*.pyd' '*.pyo' '*.node' '*.class' '*.jar' '*.db' '*.sqlite' '*.sqlite3'
        'Music' '.target_book' '_book' 'OneDrive*'
      )
      for pattern in "${ignores[@]}"; do fdopt+=( --exclude "${pattern}" ); done
    
      { test "$HOME" = "$(pwd)" || [[ "$HOME" = $(realpath ${1:-}) ]]; } && fdopt+=( --max-depth 3 )
      isWSL || fdopt+=( --exec-batch ls -t )
    
      eval "$( _load_fzf_context )"
    
      while [[ $# -gt 0 ]]; do
        case "$1" in
                     -v ) orgv=true              ; shift   ;;
            -h | --help ) voption+=( "$1" )      ; shift   ;;
              --version ) voption+=( "$1" )      ; shift   ;;
                     -c ) voption+=( "$1" "$2" ) ; shift   ;;
          --startuptime ) voption+=( "$1" "$2" ) ; shift 2 ;;
                    -Nu ) voption+=( "$1" "$2" ) ; shift 2 ;;
                  --cmd ) voption+=( "$1" "$2" ) ; shift 2 ;;
                     -* ) fzfopt+=(  "$1" "$2" ) ; shift 2 ;;
                      * ) break                            ;;
        esac
      done
    
      local VIM="$(type -P vim)"
      ! "${orgv}" && command -v nvim >/dev/null && VIM="$(type -P nvim)"
    
      if [[ 0 -eq "$#" ]] && [[ 0 -eq "${#voption}" ]]; then
        fd . "${fdopt[@]}" | fzf "${fzfopt[@]}" --bind="enter:become(${VIM} {+})"
      elif [[ 1 -eq "$#" ]] && [[ -d "${1}" ]]; then
        [[ '.' = "${1}" ]] && finalTarget=("${1}") || finalTarget=('.' "${1}")
        fd "${finalTarget[@]}" "${fdopt[@]}" | fzf "${fzfopt[@]}" --bind="enter:become(${VIM} {+})"
      else
        "${VIM}" "${voption[@]}" "$@"
      fi
    }
    
  • v()

    v()
    # v            : open files in ~/.vim_mru_files       # https://github.com/junegunn/fzf/wiki/Examples#v
    # @author      : marslo
    # @source      : https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh
    # @description : list 10 most recently used files via fzf, and open by regular vim
    function v() {                             # v - open files in ~/.vim_mru_files
      local files
      files=$( grep --color=none -v '^#' ~/.vim_mru_files |
               while read -r line; do [ -f "${line/\~/$HOME}" ] && echo "${line}"; done |
               fzf-tmux -d -m -q "$*" -1
             ) &&
      vim ${files//\~/$HOME}
    }
    
  • vimr()

    vimr()
    # vimr         : open files by [vim] in whole [r]epository
    #                same series: [`cdr`](https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh#L411-L419)
    #                similar with [`:Gfiles`](https://github.com/junegunn/fzf.vim?tab=readme-ov-file#commands)
    # @author      : marslo
    # @source      : https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh
    # @description :
    #   - if pwd inside the repo, then filter all files within current git repository via data modified and open by vim
    #   - if pwd not inside the repo, then call `vim`
    function vimr() {                          # vimr - open file(s) via [vim] in whole [r]epository
      local repodir
      # shellcheck disable=SC2155
      local VIM="$(type -P vim)"
      type -P nvim >/dev/null && VIM="$(type -P nvim)"
    
      local -a fdopt=( --type f --hidden --ignore-file "$HOME/.fdignore" )
      local -a ignores=(
        '*.pem' '*.p12'
        '*.png' '*.jpg' '*.jpeg' '*.gif' '*.svg'
        '*.zip' '*.tar' '*.gz' '*.bz2' '*.xz' '*.7z' '*.rar'
        'Music' '.target_book' '_book' 'OneDrive*'
      )
      while read -r pattern; do fdopt+=( --exclude "${pattern}" ); done <<< "$(printf '%s\n' "${ignores[@]}" | sort -u)"
      fdopt+=( --exec-batch ls -t )
    
      if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
        repodir="$( git rev-parse --show-toplevel )"
        local -a files=()
        mapfile -t files < <(
          fd . "${repodir}" "${fdopt[@]}" |
            sed "s|^${repodir}/||" |
            fzf --multi \
                 --bind "ctrl-r:reload(fd . ${repodir} ${fdopt[*]@Q} | sed 's|^${repodir}/||')" \
                 --preview "cd \"${repodir}\" && bat --color=always --line-range :500 {}" \
                 --preview-window '60%:nowrap,+15' \
                 --height 50% |
            awk -v prefix="${repodir}/" '{print prefix $0}'
        )
        [[ ${#files[@]} -gt 0 ]] && "${VIM}" "${files[@]}"
      else
        ${VIM}
      fi
    }
    
  • vimrc()

    vimrc()
    # vimrc        : open rc files list from "${rcPaths}" to quick update/modify rc files
    #                same series: runrc
    # @author      : marslo
    # @source      : https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh
    # @description :
    #   - default rcPaths: ~/.marslo ~/.config/nvim ~/.*rc ~/.*profile ~/.*ignore
    #   - using nvim if `command -v nvim` is true
    #   - using `-v` force using `command vim` instead of `command nvim`
    # shellcheck disable=SC2155
    function vimrc() {                         # vimrc - fzf list all rc files in data modified order
      local orgv=false                         # force using vim instead of nvim
      local VIM="$(type -P vim)"
      local -a foption=( --multi --cycle )
    
      while [[ $# -gt 0 ]]; do
        case "$1" in
          -v ) orgv=true               ; shift   ;;
          -q ) foption+=(--query "$2") ; shift 2 ;;
           * ) break                             ;;
        esac
      done
    
      eval "$( _load_fzf_context  )"
    
      "${orgv}" || command -v nvim >/dev/null && VIM="$(type -P nvim)"
      fdInRC -x | sed -rn 's/^[^|]* \| (.+)$/\1/p' \
                | fzf "${foption[@]}" "${fzfopt[@]}" \
                      --bind="enter:become(${VIM} {+})" \
                      --preview-window 'right,55%,nowrap,rounded,+15' \
                      --bind "ctrl-y:execute-silent(printf '%s' {+} | ${COPY})" \
                      --header 'Press CTRL-Y to copy name into clipboard'
    }
    
fzf magic vim
1.4.1.1.4 -- fzf magic vim
fzf vimrc
1.4.1.1.5 -- fzf vimrc

smart vimdiff

  • vimdiff()

    vimdiff()
    # vimdiff      : magic vimdiff, using fzf list in recent modified order
    # @author      : marslo
    # @source      : https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh
    # @description :
    #   - if any of parameters is directory, then get file path via fzf in target path first
    #   - if `vimdiff` commands without parameter , then compare files in `.` and `~/.marslo`
    #   - if `vimdiff` commands with 1  parameter , then compare files in current path and `$1`
    #   - if `vimdiff` commands with 2  parameters, then compare files in `$1` and `$2`
    #   - otherwise ( if more than 2 parameters )  , then compare files in `${*: -2:1}` and `${*: -1}` with parameters of `${*: 1:$#-2}`
    #   - to respect fzf options by: `type -t _fzf_opts_completion >/dev/null 2>&1 && complete -F _fzf_opts_completion -o bashdefault -o default vimdiff`
    function vimdiff() {                       # smart vimdiff
      local lFile
      local rFile
      local -a var=()
      local -a options=()
      local -a fzfopt=( --cycle --multi --header 'filter in rc paths:' )
    
      while [[ $# -gt 0 ]]; do
        case "$1" in
          --help ) options+=( "$1" )      ; shift   ;;
              -* ) options+=( "$1" "$2" ) ; shift 2 ;;
               * ) break                            ;;
        esac
      done
      fzfopt+=( "${options[@]}" )
    
      if [[ 0 -eq $# ]]; then
        lFile=$(fzfInPath '.' "${options[@]}" true)
        [[ -z "${lFile}" ]] && return 1
        rFile=$(fdInRC -x | sed -rn 's/^[^|]* \| (.+)$/\1/p' | fzf "${fzfopt[@]}" )
      elif [[ 1 -eq $# ]]; then
        lFile=$(fzfInPath '.' "${options[@]}" true)
        [[ -z "${lFile}" ]] && return 1
        [[ -d "$1"       ]] && rFile=$(fzfInPath "$1" "${options[@]}") || rFile="$1"
      elif [[ 2 -eq $# ]]; then
        [[ -d "$1"       ]] && lFile=$(fzfInPath "$1" "${options[@]}") || lFile="$1"
        [[ -z "${lFile}" ]] && return 1
        [[ -d "$2"       ]] && rFile=$(fzfInPath "$2" "${options[@]}") || rFile="$2"
      else
        var=( "${@:1:$#-2}" )
        [[ -d "${*: -2:1}" ]] && lFile=$(fzfInPath "${*: -2:1}") || lFile="${*: -2:1}"
        [[ -z "${lFile}"   ]] && return 1
        [[ -d "${*: -1}"   ]] && rFile=$(fzfInPath "${*: -1}")   || rFile="${*: -1}"
      fi
    
      [[ -f "${lFile}" ]] && [[ -f "${rFile}" ]] && $(type -P vim) -d "${var[@]}" "${lFile}" "${rFile}"
    }
    
  • vd()

    vd()
    # vd           : open vimdiff loaded files from ~/.vim_mru_files
    # @author      : marslo
    # @source      : https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh
    # @description : list 10 most recently used files via fzf, and open by vimdiff
    #   - if `vd` commands without parameter, list 10 most recently used files via fzf, and open selected files by vimdiff
    #   - if `vd` commands with `-a` ( [q]uiet ) parameter, list 10 most recently used files via fzf and automatic select top 2, and open selected files by vimdiff
    function vd() {                            # vd - open [v]im[d]iff loaded files from ~/.vim_mru_files
      [[ 1 -eq $# ]] && [[ '-q' = "$1" ]] && opt='--bind start:select+down+select+accept' || opt=''
    
      local -a files=()
      mapfile -t files < <(
        grep --color=none -v '^#' ~/.vim_mru_files |
         xargs -r -d'\n' -I_ bash -c "sed 's:\~:$HOME:' <<< _" |
         fzf --multi 3 --sync --cycle --reverse ${opt}
      )
      [[ ${#files[@]} -lt 2 ]] || vimdiff "${files[@]}"
    }
    
vimdiff
1.4.1.1.6 -- vimdiff

smart cat

[!NOTE|label:references:]

smart cat
1.4.1.1.7 -- smart cat
cat()
# smart cat    : using bat by default for cat content, respect bat options
# @author      : marslo
# @source      : https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh
# @description :
#   - using `bat` by default if `command -v bat`
#     - using `-c` ( `c`at ) as 1st parameter, to force using `type -P cat` instead of `type -P bat`
#   - if `bat` without  parameter, then search file via `fzf` and shows via `bat`
#   - if `bat` with 1   parameter, and `$1` is directory, then search file via `fzf` from `$1` and shows via `bat`
#   - otherwise respect `bat` options, and shows via `bat`
# shellcheck disable=SC2046,SC2155
function cat() {                           # smart cat
  local -a CAT=( "$(type -P cat)" )
  command -v bat >/dev/null && CAT=( "$(type -P bat)" --theme='gruvbox-dark' --color=always )

  # reading from pipe == [[ -p /dev/stdin ]]
  [[ ! -t 0      ]] && { "${CAT[@]}" "$@"; return; }
  # force use cat
  [[ '-c' = "$1" ]] && { $(type -P cat) "${@:2}"; return; }

  eval "$( _load_fd_context  )"
  eval "$( _load_fzf_context )"

  # reading from fd + fzf
  if [[ 0 -eq $# ]]; then
    local selected=$( fd . "${fdopt[@]}" | fzf --exit-0 "${fzfopt[@]}" )
    # using IFS to handle file name with space
    [[ -n "${selected}" ]] && echo "${selected}" | xargs -d '\n' "${CAT[@]}"
  elif [[ 1 -eq $# ]] && [[ -d $1 ]]; then
    local target=$1;
    fd . "${target}" "${fdopt[@]}" | fzf --bind="enter:become(${CAT[*]} {+})" "${fzfopt[@]}";
  else
    "${CAT[@]}" "${@:1:$#-1}" "${@: -1}"
  fi
}

smart copy

[!NOTE|label:references:]

smart copy
1.4.1.1.8 -- smart copy
copy()
# smart copy   : using `fzf` to list files and copy the selected file
# @author      : marslo
# @source      : https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh
# @description :
#   - if `copy` without parameter, then list file via `fzf` and copy the content
#     - "${COPY}"
#       - `pbcopy` in osx
#       - `/mnt/c/Windows/System32/clip.exe` in wsl
#   - otherwise copy the content of parameter `$1` via `pbcopy` or `clip.exe`
# shellcheck disable=SC2317
function copy() {                          # smart copy
  [[ -z "${COPY}" ]] && echo -e "$(c Rs)ERROR: 'copy' function NOT support :$(c) $(c Ri)$(uanme -v)$(c)$(c Rs). EXIT..$(c)" && return;

  eval "$( _load_fd_context  )"
  eval "$( _load_fzf_context )"

  if [[ 0 -eq $# ]]; then
    file=$( fd . "${fdopt[@]}" | fzf "${fzfopt[@]}" ) &&
         "${COPY}" < "${file}" &&
         printf "$(c Wd)>>$(c) $(c Gis)%s$(c) $(c Wdi)has been copied ..$(c)" "${file}"
  elif [[ 1 -eq $# ]] && [[ -d "$1" ]]; then
    local target=$1;
    file=$( fd . "${target}" "${fdopt[@]}" | fzf "${fzfopt[@]}" ) &&
         "${COPY}" < "${file}" &&
         printf "$(c Wd)>>$(c) $(c Gis)%s$(c) $(c Wdi)has been copied ..$(c)" "${file}"
  else
    "${COPY}" < "$1" &&
       printf "$(c Wd)>>$(c) $(c Gis)%s$(c) $(c Wdi)has been copied ..$(c)" "${1}"
  fi
}

smart open

smart open
1.4.1.1.9 -- smart open
open()
# smart open   : using `fzf` to list files and open the selected file with default application
# @author      : marslo
# @source      : https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh
# shellcheck disable=SC2317
function open() {                          # smart open
  [[ "Darwin" != "$(uname -s)" ]] && echo -e "$(c Rs)ERROR: 'open' function currently only support macOS :$(c) $(c Ri)$(uanme -v)$(c)$(c Rs). EXIT..$(c)" && return;

  local ORG_OPEN=false
  local USAGE='USAGE'
  USAGE+="\n  $(c Cs)\$ open $(c 0G)[options] $(c 0Mi)[file|dir ...]$(c)"
  USAGE+="\n\nOPTIONS"
  USAGE+="\n  $(c G)-d$(c), $(c G)--no-fzf$(c)    open directory directly without fzf selection"
  USAGE+="\n  $(c C)-- $(c 0G)-h$(c), $(c 0G)--help$(c)   show this help message"
  USAGE+="\n\nEXAMPLES"
  USAGE+="\n  $(c Y)\$ open$(c)                       $(c 0Wdi)# list files via fzf and open the selected file$(c)"
  USAGE+="\n  $(c Y)\$ open $(c 0Mi)/path/to/dir$(c)          $(c 0Wdi)# list files in directory via fzf and open the selected file$(c)"
  USAGE+="\n  $(c Y)\$ open $(c 0Gi)--no-fzf $(c 0Mi)/path/to/dir$(c) $(c 0Wdi)# open the directory directly without fzf selection$(c)"

  eval "$( _load_fd_context  )"
  eval "$( _load_fzf_context )"

  while [[ $# -gt 0 ]]; do
    case "$1" in
      -d | --no-fzf ) ORG_OPEN=true     ; shift  ;;
      --            ) shift;
                      for arg in "$@"; do
                        case "${arg}" in
                          -h | --help ) echo -e "${USAGE}"; return ;;
                        esac
                      done; break   ;;
      -*            ) command open "$1" ; return ;;
      *             ) break                      ;;
    esac
  done

  if [[ 0 -eq $# ]]; then
    local selected=$( fd . "${fdopt[@]}" | fzf --exit-0 "${fzfopt[@]}" )
    [[ -n "${selected}" ]] && echo "${selected}" | tr '\n' '\0' | xargs -0 command open
  elif [[ -d "${1:-}" ]]; then
    local target=$1;
    "${ORG_OPEN}" && command open "${target}" && return;
    fd . "${target}" "${fdopt[@]}" | fzf --bind="enter:become(command open {+})" "${fzfopt[@]}";
  else
    command open "${@}"
  fi
}

others

  • image view

    [!NOTE]

  • imgview()

    imgview()
    # imgview      : fzf list and preview images
    # @author      : marslo
    # @source      : https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh
    # @description :
    #   - to respect fzf options by: `type -t _fzf_opts_completion >/dev/null 2>&1 && complete -F _fzf_opts_completion -o bashdefault -o default imgview`
    #   - disable `gif` due to imgcat performance issue
    # shellcheck disable=SC2215
    function imgview() {                       # [view] [im]a[g]e via [imgcat](https://github.com/eddieantonio/imgcat)
      fd --unrestricted --type f --exclude .git --exclude node_modules '^*\.(png|jpeg|jpg|xpm|bmp)$' |
      fzf "$@" --height 100% \
               --preview "imgcat -W \$FZF_PREVIEW_COLUMNS -H \$FZF_PREVIEW_LINES {}" \
               --bind "ctrl-y:execute-silent(printf '%s' {+} | pbcopy)+abort" \
               --bind 'ctrl-/:toggle-preview' \
               --header 'Press CTRL-Y to copy name into clipboard' \
               --preview-window 'up:80%:nowrap' \
               --exit-0 \
      >/dev/null || true
    }
    
  • open files

    • fs

      $ function fs() { fzf --multi --bind 'enter:become(vim {+})' }
      
    • fe

      # fe [FUZZY PATTERN] - Open the selected file with the default editor
      #   - Bypass fuzzy finder if there's only one match (--select-1)
      #   - Exit if there's no match (--exit-0)
      fe() {
        IFS=$'\n' files=($(fzf-tmux --query="$1" --multi --select-1 --exit-0))
        [[ -n "$files" ]] && ${EDITOR:-vim} "${files[@]}"
      }
      
    • fo

      # Modified version where you can press
      #   - CTRL-O to open with `open` command,
      #   - CTRL-E or Enter key to open with the $EDITOR
      fo() {
        IFS=$'\n' out=("$(fzf-tmux --query="$1" --exit-0 --expect=ctrl-o,ctrl-e)")
        key=$(head -1 <<< "$out")
        file=$(head -2 <<< "$out" | tail -1)
        if [ -n "$file" ]; then
          [ "$key" = ctrl-o ] && open "$file" || ${EDITOR:-vim} "$file"
        fi
      }
      
  • search in files

    [!NOTE]

    fif()
    # references:
    # - https://github.com/junegunn/fzf/blob/master/ADVANCED.md#using-fzf-as-the-secondary-filter
    # - https://github.com/junegunn/fzf/issues/3572#issuecomment-1887735150
    # shellcheck disable=SC2154
    function fif() {                           # [f]ind-[i]n-[f]ile
      if [ ! "$#" -gt 0 ]; then
        bash "${iRCHOME}"/bin/rfv
      else
        $(type -P rg) --files-with-matches --no-messages --hidden --follow --smart-case "$1" |
        fzf --height 80% \
            --bind 'ctrl-p:preview-up,ctrl-n:preview-down' \
            --bind "enter:become($(type -P vim) {+})" \
            --header 'CTRL-N/CTRL-P or CTRL-↑/CTRL-↓ to view contents' \
            --preview "bat --color=always --style=plain {} |
                       rg --no-line-number --colors 'match:bg:yellow' --ignore-case --pretty --context 10 \"$1\" ||
                       rg --no-line-number --ignore-case --pretty --context 10 \"$1\" {} \
                      "
      fi
    }
    
    # or highlight as preview tool
    function fif() {                           # [f]ind-[i]n-[f]ile
      if [ ! "$#" -gt 0 ]; then echo "Need a string to search for!"; return 1; fi
      rg --color never --files-with-matches --no-messages "$1" |
      fzf --bind 'ctrl-p:preview-up,ctrl-n:preview-down' \
          --preview "highlight -O ansi {} 2> /dev/null |
                     rg --colors 'match:bg:yellow' --ignore-case --pretty --context 10 '$1' ||
                     rg --no-line-number --ignore-case --pretty --context 10 '$1' {} \
                    "
    }
    
    rg+fzf
    1.4.1.1.10 -- rg+fzf
  • changing directory

    [!NOTE|label:references:]

  • Interactive cd

    function cd() {
      if [[ "$#" != 0 ]]; then
        # shellcheck disable=SC2164
        builtin cd "$@";
        return
      fi
      while true; do
        # shellcheck disable=SC2155,SC2010
        local lsd=$(echo ".." && ls -A --color=none -p | grep --color=none '/$' | sed 's;/$;;')
        # shellcheck disable=SC2155,SC2016
        local dir="$(printf '%s\n' "${lsd[@]}" |
            fzf --reverse --preview '
                __cd_nxt="$(echo {})";
                __cd_path="$(echo $(pwd)/${__cd_nxt} | sed "s;//;/;")";
                echo $__cd_path;
                echo;
                ls -p --color=always "${__cd_path}";
        ')"
        [[ ${#dir} != 0 ]] || return 0
        # shellcheck disable=SC2164
        builtin cd "$dir" &> /dev/null
      done
    }
    
    deprecated `fd`
    • fd

      [!DANGER] conflict with fd-find

      # fd - cd to selected directory
      fd() {
        local dir
        dir=$(find ${1:-.} -path '*/\.*' -prune \
                           -o -type d -print 2> /dev/null | fzf +m) &&
        cd "$dir"
      }
      
      # Another fd - cd into the selected directory
      # This one differs from the above, by only showing the sub directories and not
      #  showing the directories within those.
      fd() {
        DIR=$(find * -maxdepth 0 -type d -print 2> /dev/null | fzf-tmux) && cd "$DIR"
      }
      
    • fda

      # fda - including hidden directories
      fda() {
        local dir
        dir=$(find ${1:-.} -type d 2> /dev/null | fzf +m) && cd "$dir"
      }
      

advanced usage

venv selector

# activate venv - using `fzf` to list and activate python venv
# @author      : marslo
# @inspired    : https://seb.jambor.dev/posts/improving-shell-workflows-with-fzf/#virtual-env
# @source      : https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh
function avenv() {
  # shellcheck disable=SC2155
  local _venv=$(command ls --color=never "$HOME/.venv" | fzf)
  [[ -n "${_venv}" ]] &&
    source "$HOME/.venv/${_venv}/bin/activate" &&
    echo -e "$(c Wd)>>$(c) $(c Gis)${_venv}$(c) $(c Wdi)has been activated ..$(c)"
}

chrome

  • Bookmarks

    # https://github.com/junegunn/fzf/wiki/Examples#bookmarks
    # shellcheck disable=SC2016
    function b() {                             # chrome [b]ookmarks browser with jq
      if [ "$(uname)" = "Darwin" ]; then
        if [[ -e "$HOME/Library/Application Support/Google/Chrome Canary/Default/Bookmarks" ]]; then
          bookmarks_path="$HOME/Library/Application Support/Google/Chrome Canary/Default/Bookmarks"
        else
          bookmarks_path="$HOME/Library/Application Support/Google/Chrome/Default/Bookmarks"
        fi
        open=open
      else
        bookmarks_path="$HOME/.config/google-chrome/Default/Bookmarks"
        open=xdg-open
      fi
    
      jq_script='
         def ancestors: while(. | length >= 2; del(.[-1,-2]));
         . as $in | paths(.url?) as $key | $in | getpath($key) | {name,url, path: [$key[0:-2] | ancestors as $a | $in | getpath($a) | .name?] | reverse | join("/") } | .path + "/" + .name + "\t" + .url'
    
      urls=$( jq -r "${jq_script}" < "${bookmarks_path}" \
                 | sed -E $'s/(.*)\t(.*)/\\1\t\x1b[36m\\2\x1b[m/g' \
                 | fzf --ansi \
                 | cut -d$'\t' -f2
            )
      # shellcheck disable=SC2046
      [[ -z "${urls}" ]] || "${open}" $(echo "${urls}" | xargs)
    }
    

man page

[!NOTE]

# fman - fzf list and preview for manpage:
# @source      : https://github.com/junegunn/fzf/wiki/examples#fzf-man-pages-widget-for-zsh
# @description :
#   - CTRL-N/CTRL-P or SHIFT-↑/↓ for view preview content
#   - ENTER/Q for toggle maximize/normal preview window
#   - CTRL+O  for toggle tldr in preview window
#   - CTRL+I  for toggle man in preview window
#   - to respect fzf options by: `type -t _fzf_opts_completion >/dev/null 2>&1 && complete -F _fzf_opts_completion -o bashdefault -o default fman`
# shellcheck disable=SC2046
function fman() {
  unset MANPATH
  local option
  local batman="man {1} | col -bx | bat --language=man --plain --color always --theme='gruvbox-dark'"

  while [[ $# -gt 0 ]]; do
    case "$1" in
          -* ) option+="$1 $2 "; shift 2 ;;
           * ) break                     ;;
    esac
  done

  man -k . |
  sort -u |
  sed -r 's/(\(.+\))//g' |
  grep -v -E '::' |
  awk -v cyan=$(tput setaf 6) -v blue=$(tput setaf 4) -v res=$(tput sgr0) -v bld=$(tput bold) '{ $1=cyan bld $1; $2=res blue $2;} 1' |
  fzf ${option:-} \
      -d ' ' \
      --nth 1 \
      --height 100% \
      --ansi \
      --no-multi \
      --tiebreak=begin \
      --prompt='ᓆ > ' \
      --color='prompt:#0099BD' \
      --preview-window 'up,70%,wrap,rounded,<50(up,85%,border-bottom)' \
      --preview "${batman}" \
      --bind 'ctrl-p:preview-up,ctrl-n:preview-down' \
      --bind "ctrl-o:+change-preview(tldr --color {1})+change-prompt(ﳁ tldr > )" \
      --bind "ctrl-i:+change-preview(${batman})+change-prompt(ᓆ  man > )" \
      --bind "enter:execute(${batman})+change-preview(${batman})+change-prompt(ᓆ > )" \
      --header 'CTRL-N/P or SHIFT-↑/↓ to view preview contents; ENTER/Q to maximize/normal preview window' \
      --exit-0
}
  • simple version
    $ apropos . |
      fzf -d ') ' --nth 1 \
                  --height 100% \
                  --bind 'ctrl-p:preview-up,ctrl-n:preview-down' \
                  --header 'CTRL-N/CTRL-P or CTRL-↑/CTRL-↓ to view contents' \
                  --preview-window=up:88%:wrap \
                  --preview 'echo {} | sed -r "s/([^\(]+).*$/\1/" | xargs man' \
                  --exit-0 |
      sed -r "s/([^\(]+).*$/\1/" |
      xargs man
    
fzf man
1.4.1.1.11 -- fzf man

git alias

[!TIP]

[alias]
  ### checkout sorted [b]ranch
  bb    = "! bash -c 'branch=$(git for-each-ref refs/remotes refs/heads --sort=-committerdate --format=\"%(refname:short)\" | \n\
                      grep --color=never -v \"origin$\" | \n\
                      fzf +m --prompt=\"branch> \" | \n\
                      sed -rn \"s:\\s*(origin/)?(.*)$:\\2:p\") && \n\
                      [[ -n \"${branch}\" ]] && \n\
                      echo -e \"\\033[1;33m~~> ${branch}\\033[0m\" && \n\
                      git checkout \"${branch}\"; \n\
                     '"

  ### [b]ranch [copy]
  bcopy = "! bash -c 'branch=$(git for-each-ref refs/remotes refs/heads --sort=-committerdate --format=\"%(refname:short)\" | \n\
                      grep --color=never -v \"origin$\" | \n\
                      fzf +m --prompt=\"branch> \" | \n\
                      sed -rn \"s:\\s*(origin/)?(.*)$:\\2:p\") && \n\
                      [[ -n \"${branch}\" ]] && \n\
                      echo -e \"\\033[0;33;1m~~> branch \\033[0m\\033[0;32;3m${branch}\\033[0m \\033[0;33;1mcopied\\033[0m\" && \n\
                      pbcopy <<< \"${branch}\" \n\
                     '"

environment

  • export

    # mkexp - compilation environment variable export, support multiple select
    # @author      : marslo
    # @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.marslo/bin/ffunc.sh
    # @description : list compilation environment variable via `fzf`, and export selected items
    #   - if parameter is [ -f | --full ], then load full tool paths
    # shellcheck disable=SC1090
    function mkexp() {                         # [m]a[k]e environment variable [e][x][p]ort
      if [[ 1 -eq $# ]] && [[ '-f' = "$1" || '--full' = "$1" ]]; then
        source ~/.marslo/.imac
      fi
    
      LDFLAGS="${LDFLAGS:-}"
      test -d "${HOMEBREW_PREFIX}"      && LDFLAGS+=" -L${HOMEBREW_PREFIX}/lib"
      test -d '/usr/local/opt/readline' && LDFLAGS+=' -L/usr/local/opt/readline/lib'
      test -d "${OPENLDAP_HOME}"        && LDFLAGS+=" -L${OPENLDAP_HOME}/lib"
      test -d "${CURL_OPENSSL_HOME}"    && LDFLAGS+=" -L${CURL_OPENSSL_HOME}/lib"
      test -d "${BINUTILS}"             && LDFLAGS+=" -L${BINUTILS}/lib"
      test -d "${PYTHON_HOME}"          && LDFLAGS+=" -L${PYTHON_HOME}/lib"
      test -d "${RUBY_HOME}"            && LDFLAGS+=" -L${RUBY_HOME}/lib"
      test -d "${TCLTK_HOME}"           && LDFLAGS+=" -L${TCLTK_HOME}/lib"
      test -d "${SQLITE_HOME}"          && LDFLAGS+=" -L${SQLITE_HOME}/lib"
      test -d "${OPENSSL_HOME}"         && LDFLAGS+=" -L${OPENSSL_HOME}/lib"
      test -d "${NODE_HOME}"            && LDFLAGS+=" -L${NODE_HOME}/lib"                       # ${NODE_HOME}/libexec/lib for node@12
      test -d "${LIBRESSL_HOME}"        && LDFLAGS+=" -L${LIBRESSL_HOME}/lib"
      test -d "${ICU4C_711}"            && LDFLAGS+=" -L${ICU4C_711}/lib"
      test -d "${EXPAT_HOME}"           && LDFLAGS+=" -L${EXPAT_HOME}/lib"
      test -d "${NCURSES_HOME}"         && LDFLAGS+=" -L${NCURSES_HOME}/lib"
      test -d "${LIBICONV_HOME}"        && LDFLAGS+=" -L${LIBICONV_HOME}/lib"
      test -d "${ZLIB_HOME}"            && LDFLAGS+=" -L${ZLIB_HOME}/lib"
      test -d "${LLVM_HOME}"            && LDFLAGS+=" -L${LLVM_HOME}/lib"
      test -d "${LLVM_HOME}"            && LDFLAGS+=" -L${LLVM_HOME}/lib/c++ -Wl,-rpath,${LLVM_HOME}/lib/c++"  # for c++
      LDFLAGS=$( echo "$LDFLAGS" | tr ' ' '\n' | uniq | sed '/^$/d' | paste -s -d' ' )
    
      CFLAGS="${CFLAGS:-}"
      CFLAGS+=" -I/usr/local/include"
      test -d "${TCLTK_HOME}" && CFLAGS+=" -I${TCLTK_HOME}/include"
      CFLAGS=$( echo "$CFLAGS" | tr ' ' '\n' | uniq | sed '/^$/d' | paste -s -d' ' )
    
      CPPFLAGS="${CPPFLAGS:-}"
      test -d "${HOMEBREW_PREFIX}"      && CPPFLAGS+=" -I${HOMEBREW_PREFIX}/include"
      test -d "${JAVA_HOME}"            && CPPFLAGS+=" -I${JAVA_HOME}/include"
      test -d "${OPENLDAP_HOME}"        && CPPFLAGS+=" -I${OPENLDAP_HOME}/include"
      test -d "${CURL_OPENSSL_HOME}"    && CPPFLAGS+=" -I${CURL_OPENSSL_HOME}/include"
      test -d "${BINUTILS}"             && CPPFLAGS+=" -I${BINUTILS}/include"
      test -d "${SQLITE_HOME}"          && CPPFLAGS+=" -I${SQLITE_HOME}/include"
      test -d '/usr/local/opt/readline' && CPPFLAGS+=' -I/usr/local/opt/readline/include'
      test -d "${OPENSSL_HOME}"         && CPPFLAGS+=" -I${OPENSSL_HOME}/include"
      test -d "${NODE_HOME}"            && CPPFLAGS+=" -I${NODE_HOME}/include"
      test -d "${LIBRESSL_HOME}"        && CPPFLAGS+=" -I${LIBRESSL_HOME}/include"
      test -d "${TCLTK_HOME}"           && CPPFLAGS+=" -I${TCLTK_HOME}/include"
      test -d "${RUBY_HOME}"            && CPPFLAGS+=" -I${RUBY_HOME}/include"
      test -d "${ICU4C_711}"            && CPPFLAGS+=" -I${ICU4C_711}/include"
      test -d "${LLVM_HOME}"            && CPPFLAGS+=" -I${LLVM_HOME}/include"
      test -d "${LIBICONV_HOME}"        && CPPFLAGS+=" -I${LIBICONV_HOME}/include"
      test -d "${EXPAT_HOME}"           && CPPFLAGS+=" -I${EXPAT_HOME}/include"
      test -d "${NCURSES_HOME}"         && CPPFLAGS+=" -I${NCURSES_HOME}/include"
      test -d "${ZLIB_HOME}"            && CPPFLAGS+=" -I${ZLIB_HOME}/include"
      CPPFLAGS=$( echo "$CPPFLAGS" | tr ' ' '\n' | uniq | sed '/^$/d' | paste -s -d' ' )
    
      PKG_CONFIG_PATH=${PKG_CONFIG_PATH:-}
      PKG_CONFIG_PATH+=":${HOMEBREW_PREFIX}/lib/pkgconfig"
      test -d "${CURL_OPENSSL_HOME}"  && PKG_CONFIG_PATH+=":${CURL_OPENSSL_HOME}/lib/pkgconfig"
      test -d "${TCLTK_HOME}"         && PKG_CONFIG_PATH+=":${TCLTK_HOME}/lib/pkgconfig"
      command -v brew >/dev/null 2>&1 && PKG_CONFIG_PATH+=':/usr/local/Homebrew/Library/Homebrew/os/mac/pkgconfig/14'
      test -d "${SQLITE_HOME}"        && PKG_CONFIG_PATH+=":${SQLITE_HOME}/lib/pkgconfig"
      test -d "${OPENSSL_HOME}"       && PKG_CONFIG_PATH+=":${OPENSSL_HOME}/lib/pkgconfig"
      test -d "${PYTHON_HOME}"        && PKG_CONFIG_PATH+=":${PYTHON_HOME}/lib/pkgconfig"
      test -d "${RUBY_HOME}"          && PKG_CONFIG_PATH+=":${RUBY_HOME}/lib/pkgconfig"
      test -d "${LIBRESSL_HOME}"      && PKG_CONFIG_PATH+=":${LIBRESSL_HOME}/lib/pkgconfig"
      test -d "${ICU4C_711}"          && PKG_CONFIG_PATH+=":${ICU4C_711}/lib/pkgconfig"
      test -d "${EXPAT_HOME}"         && PKG_CONFIG_PATH+=":${EXPAT_HOME}/lib/pkgconfig"
      test -d "${NCURSES_HOME}"       && PKG_CONFIG_PATH+=":${NCURSES_HOME}/lib/pkgconfig"
      test -d "${ZLIB_HOME}"          && PKG_CONFIG_PATH+=":${ZLIB_HOME}/lib/pkgconfig"
      PKG_CONFIG_PATH=$( echo "$PKG_CONFIG_PATH" | tr ':' '\n' | uniq | sed '/^$/d' | paste -s -d: )
    
      LIBRARY_PATH="${HOMEBREW_PREFIX}/lib"
      test -d "${LIBICONV_HOME}" && LIBRARY_PATH+=":${LIBICONV_HOME}/lib"
      LIBRARY_PATH=$( echo "$LIBRARY_PATH" | tr ':' '\n' | uniq | sed '/^$/d' | paste -s -d: )
    
      LD_LIBRARY_PATH=/usr/local/lib
      LD_LIBRARY_PATH=$( echo "$LD_LIBRARY_PATH" | tr ':' '\n' | uniq | sed '/^$/d' | paste -s -d: )
    
      while read -r _env; do
        export "${_env?}"
        echo -e "$(c Ys)>> ${_env}$(c)\n$(c Wi).. $(eval echo \$${_env})$(c)"
      done < <( echo 'LDFLAGS CFLAGS CPPFLAGS PKG_CONFIG_PATH LIBRARY_PATH LD_LIBRARY_PATH' |
                      fmt -1 |
                      fzf -1 --exit-0 \
                             --no-sort \
                             --multi \
                             --cycle \
                             --prompt 'env> ' \
                             --header 'TAB/SHIFT-TAB to select multiple items, CTRL-D to deselect-all, CTRL-S to select-all'
              )
    }
    
  • unset

      • alternative:
        $ unset ,,<TAB>
        # by default
        $ unset **<TAB>
        
    # eclr - environment variable clear, support multiple select
    # @author      : marslo
    # @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.marslo/bin/ffunc.sh
    # @description : list all environment variable via `fzf`, and unset for selected items
    function eclr() {                          # [e]nvironment variable [c][l]ea[r]
      while read -r _env; do
        echo -e "$(c Ys)>> unset ${_env}$(c)\n$(c Wdi).. $(eval echo \$${_env})$(c)"
        unset "${_env}"
      done < <( env |
                sed -rn 's/^([a-zA-Z0-9]+)=.*$/\1/p' |
                fzf -1 --exit-0 --no-sort --multi --prompt='env> ' --header 'TAB to select multiple items'
              )
    }
    
  • or unset limited to environment list

    # mkclr - compilation environment variable clear, support multiple select
    # @author      : marslo
    # @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.marslo/bin/ffunc.sh
    # @description : list compilation environment variable via `fzf`, and unset for selected items
    function mkclr() {                         # [m]a[k]e environment variable [c][l]ea[r]
      while read -r _env; do
        echo -e "$(c Ys)>> unset ${_env}$(c)\n$(c Wdi).. $(eval echo \$${_env})$(c)"
        unset "${_env}"
      done < <( echo 'LDFLAGS CFLAGS CPPFLAGS PKG_CONFIG_PATH LIBRARY_PATH LD_LIBRARY_PATH' |
                      fmt -1 |
                      fzf -1 --exit-0 \
                             --no-sort \
                             --multi \
                             --cycle \
                             --prompt 'env> ' \
                             --header 'TAB/SHIFT-TAB to select multiple items, CTRL-D to deselect-all, CTRL-S to select-all'
              )
      # echo -e "\n$(c Wdi)[TIP]>> to list all env via $(c)$(c Wdiu)\$ env | sed -rn 's/^([a-zA-Z0-9]+)=.*$/\1/p'$(c)"
    }
    
    fzf for unset environment
    1.4.1.1.12 -- fzf for unset environment
  • print and copy

    [!NOTE|label:references:]

    • environ – user environment : ( man environ )
    • printenv
    # penv - print environment variable, support multiple select
    # @author      : marslo
    # @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.marslo/bin/ffunc.sh
    # @description : list all environment variable via `fzf`, and print values for selected items
    #   - to copy via `-c`
    #     - "${COPY}"
    #       - `pbcopy` in osx
    #       - `/mnt/c/Windows/System32/clip.exe` in wsl
    #   - to respect fzf options via `type -t _fzf_opts_completion >/dev/null 2>&1 && complete -F _fzf_opts_completion -o bashdefault -o default penv`
    #   - more options: https://github.com/junegunn/fzf/issues/3599#issuecomment-1907233847
    # shellcheck disable=SC2215,SC2016
    function penv() {                          # [p]rint [env]ironment variable
      local option
      local -a array
    
      while [[ $# -gt 0 ]]; do
        case "$1" in
          -c ) option+="$1 "   ; shift   ;;
          -* ) option+="$1 $2 "; shift 2 ;;
           * ) break                     ;;
        esac
      done
    
      option+='-1 --exit-0 --sort --multi --cycle'
      _echo_values() { echo -e "$(c Ys)>> $1$(c)\n$(c Wi).. $(eval echo \$$1)$(c)"; }
    
      while read -r _env; do
        _echo_values $_env
        array+=( "${_env}=$(eval echo \$${_env})" )
      done < <( env |
                sed -r 's/^([a-zA-Z0-9_-]+)=.*$/\1/' |
                fzf ${option//-c\ /} \
                    --prompt 'env> ' \
                    --height '50%' \
                    --preview-window 'top,30%,wrap,rounded' \
                    --preview='source ~/.marslo/bin/bash-color.sh; _env={}; echo -e "$(c Gs)${_env}=${!_env}$(c)"' \
                    --header 'TAB/SHIFT-TAB to select multiple items, CTRL-D to deselect-all, CTRL-S to select-all'
              )
      [[ "${option}" == *-c\ * ]] && [[ -n "${COPY}" ]] && "${COPY}" < <( printf '%s\n' "${array[@]}" | head -c-1 )
    }
    
    penv
    1.4.1.1.13 -- penv

process

[!NOTE]

$ (date; ps -ef) |
  fzf --bind='ctrl-r:reload(date; ps -ef)' \
      --header=$'Press CTRL-R to reload\n\n' --header-lines=2 \
      --preview='echo {}' --preview-window=down,3,wrap \
      --layout=reverse --height=80% |
  awk '{print $2}'

# or kill
$ (date; ps -ef) |
  fzf --bind='ctrl-r:reload(date; ps -ef)' \
      --header=$'Press CTRL-R to reload\n\n' --header-lines=2 \
      --preview='echo {}' --preview-window=down,3,wrap \
      --layout=reverse --height=80% |
  awk '{print $2}' |
  xargs kill -9
  • functions

    function lsps() {                          # [l]i[s]t [p]roces[s]
      (date; ps -ef) |
      fzf --bind='ctrl-r:reload(date; ps -ef)' \
          --header=$'Press CTRL-R to reload\n\n' --header-lines=2 \
          --preview='echo {}' --preview-window=down,3,wrap \
          --layout=reverse --height=80% |
      awk '{print $2}'
    }
    
    function killps() {                        # [kill] [p]roces[s]
      (date; ps -ef) |
      fzf --bind='ctrl-r:reload(date; ps -ef)' \
          --header=$'Press CTRL-R to reload\n\n' --header-lines=2 \
          --preview='echo {}' --preview-window=down,3,wrap \
          --layout=reverse --height=80% |
      awk '{print $2}' |
      xargs kill -9
    }
    
    ps fzf
    1.4.1.1.14 -- ps fzf
    kill ps fzf
    1.4.1.1.15 -- kill ps fzf

kubectl

  • kns

    # kns - kubectl set default namespace
    # @author      : marslo
    # @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.marslo/bin/ffunc.sh
    # @description : using `fzf` to list all available namespaces and use the selected namespace as default
    # [k]ubectl [n]ame[s]pace
    function kns() {                           # [k]ubectl [n]ame[s]pace
      local krn=$(kubecolor config get-contexts --no-headers $(kubectl config current-context) | awk "{print \$5}" | sed "s/^$/default/")
      kubectl get -o name namespace |
              sed "s|^.*/|  |;\|^  $(krn)$|s/ /*/" |
              fzf -e |
              sed "s/^..//" |
              xargs -i bash -c "echo -e \"\033[1;33m~~> {}\\033[0m\";
                                kubecolor config set-context --current --namespace {};
                                kubecolor config get-contexts;
                               "
    }
    
    # or limited with `kubectl get namespace`
    function kns() {
      echo 'namespace-1 namespace-2 namespace-3 ...' |
            fmt -1 |
            fzf -1 -0 --no-sort +m --prompt='namespace> ' |
            xargs -i bash -c "echo -e \"\033[1;33m~~> {}\\033[0m\";
                              kubectl config set-context --current --namespace {};
                              kubecolor config get-contexts;
                             "
    }
    
  • kcani

    # kcani - kubectl check permission (auth can-i)
    # @author      : marslo
    # @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.marslo/bin/ffunc.sh
    # @description : check whether an action is allowed in given namespaces. support multiple selection
    # [k]ubectl [can]-[i]
    function kcani() {                         # [k]ubectl [can]-[i]
      local namespaces=''
      local actions='list get watch create update delete'
      local components='sts deploy secrets configmap ingressroute ingressroutetcp'
    
      namespaces=$( echo 'namespace-1 namespace-2 namespace-3 ...' |
                        fmt -1 |
                        fzf -1 -0 --no-sort --prompt='namespace> ' \
                            --bind 'ctrl-y:execute-silent(echo -n {+} | pbcopy)+abort' \
                            --header 'Press CTRL-Y to copy name into clipboard'
                 )
      [[ -z "${namespaces}" ]] && echo "$(c Rs)ERROR: select at least one namespace !$(c)" && return
    
      while read -r namespace; do
        echo -e "\n>> $(c Ys)${namespace}$(c)"
        k-p-cani ${namespace}                  # for pods component
    
        for _c in ${components}; do
          local res=''
          echo -e ".. $(c Ms)${_c}$(c) :"
          for _a in ${actions}; do
            r=$(_can_i -n "${namespace}" "${_a}" "${_c}")
            res+="${r} ";
          done;                                # in actions
          echo -e "${actions}\n${res}" | "${COLUMN}" -t | sed 's/^/\t/g'
        done;                                  # in components
    
      done< <(echo "${namespaces}" | fmt -1)
    }
    
    # _can_i - kubectl check permission (auth can-i) for pods component
    # @author      : marslo
    # @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.marslo/bin/ifunc.sh
    # @description : check whether given action is allowed in given namespaces; if namespace not provide, using default namespace
    function _can_i() {
      local namespace
      namespace=$(command kubectl config view --minify -o jsonpath='{..namespace}')
    
      while [[ $# -gt 0 ]]; do
        case "$1" in
          -n | --namespace ) namespace="$2" ; shift 2 ;;
                         * ) break                    ;;
        esac
      done
    
      [[ 0 = "$#" ]] && echo -e "$(c Rs)>> ERROR: must provide action to check with$(c)\n\nUSAGE$(c Gis)\n\t\$ $0 list pod\n\t\$ $0 -n <namespace> create deploy$(c)" && return
      checker=$*
      r="$(kubectl auth can-i ${checker} -n ${namespace})";
      [[ 'yes' = "${r}" ]] && r="$(c Gs)${r}$(c)" || r="$(c Rs)${r}$(c)";
      echo -e "${r}";
    }
    
    # k-p-cani - kubectl check permission (auth can-i) for pods component
    # @author      : marslo
    # @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.marslo/bin/ifunc.sh
    # @description : check whether certain action is allowed in given namespaces
    # [k]ubectl [can]-[i]
    function k-p-cani() {
      local components='pods'
      declare -A pactions
      pactions=(
                 ['0_get']="get ${components}"
                 ['1_get/exec']="get ${components}/exec"
                 ['2_get/sub/exec']="get ${components} --subresource=exec"
                 ['2_get/sub/log']="get ${components} --subresource=log"
                 ['3_list']="list ${components}"
                 ['4_create']="create ${components}"
                 ['5_create/exec']="create ${components}/exec"
                 ['6_get/sub/exec']="get ${components} --subresource=exec"
               )
    
      while read -r pnamespace; do
        local headers=''
        local pres=''
        while read -r _a; do
          headers+="$(sed -rn 's/^[0-9]+_(.+)$/\1/p' <<< ${_a}) "
          r=$(_can_i -n "${pnamespace}" "${pactions[${_a}]}")
          pres+="${r} "
        done < <( for _act in "${!pactions[@]}"; do echo "${_act}"; done | sort -h )
        echo -e ".. $(c Ms)pods$(c) :"
        echo -e "${headers}\n${pres}" | "${COLUMN}" -t | sed 's/^/\t/g'
      done< <(echo "$*" | fmt -1)
    }
    
    kcani
    1.4.1.1.16 -- kcani
  • Log tailing : pods

    pods() {
      : | command='kubectl get pods --all-namespaces' fzf \
        --info=inline --layout=reverse --header-lines=1 \
        --prompt "$(kubectl config current-context | sed 's/-context$//')> " \
        --header $'╱ Enter (kubectl exec) ╱ CTRL-O (open log in editor) ╱ CTRL-R (reload) ╱\n\n' \
        --bind 'start:reload:$command' \
        --bind 'ctrl-r:reload:$command' \
        --bind 'ctrl-/:change-preview-window(80%,border-bottom|hidden|)' \
        --bind 'enter:execute:kubectl exec -it --namespace {1} {2} -- bash > /dev/tty' \
        --bind 'ctrl-o:execute:${EDITOR:-vim} <(kubectl logs --all-containers --namespace {1} {2}) > /dev/tty' \
        --preview-window up:follow \
        --preview 'kubectl logs --follow --all-containers --tail=10000 --namespace {1} {2}' "$@"
    }
    

homebrew

  • bip

    # Install (one or multiple) selected application(s)
    # using "brew search" as source input
    # mnemonic [B]rew [I]nstall [P]ackage
    bip() {
      local inst=$(brew search "$@" | fzf -m)
    
      if [[ $inst ]]; then
        for prog in $(echo $inst);
        do; brew install $prog; done;
      fi
    }
    
  • bup

    # Update (one or multiple) selected application(s)
    # mnemonic [B]rew [U]pdate [P]ackage
    bup() {
      local upd=$(brew leaves | fzf -m)
    
      if [[ $upd ]]; then
        for prog in $(echo $upd);
        do; brew upgrade $prog; done;
      fi
    }
    

config

ctrl-r

FZF_CTRL_R_OPTS="--preview 'echo {}'"
FZF_CTRL_R_OPTS+=" --preview-window up:3:hidden:wrap"
FZF_CTRL_R_OPTS+=" --bind 'ctrl-/:toggle-preview'"
FZF_CTRL_R_OPTS+=" --bind 'ctrl-y:execute-silent(echo -n {2..} | pbcopy)+abort'"
FZF_CTRL_R_OPTS+=" --color header:italic"
FZF_CTRL_R_OPTS+=" --header 'Press CTRL-Y to copy command into clipboard'"
export FZF_CTRL_R_OPTS

# or
export FZF_CTRL_R_OPTS="
  --preview 'echo {}' --preview-window up:3:hidden:wrap
  --bind 'ctrl-/:toggle-preview'
  --bind 'ctrl-y:execute-silent(echo -n {2..} | pbcopy)+abort'
  --color header:italic
  --header 'Press CTRL-Y to copy command into clipboard'"
  • __fzf_history__

    $ type __fzf_history__
    __fzf_history__ is a function
    __fzf_history__ ()
    {
       local output opts script;
       opts="--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} -n2..,.. --scheme=history --bind=ctrl-r:toggle-sort ${FZF_CTRL_R_OPTS-} +m --read0";
       script='BEGIN { getc; $/ = "\n\t"; $HISTCOUNT = $ENV{last_hist} + 1 } s/^[ *]//; print $HISTCOUNT - $. . "\t$_" if !$seen{$_}++';
       output=$(set +o pipefail
    builtin fc -lnr -2147483648 | last_hist=$(HISTTIMEFORMAT='' builtin history 1) command perl -n -l0 -e "$script" | FZF_DEFAULT_OPTS="$opts" $(__fzfcmd) --query "$READLINE_LINE") || return;
       READLINE_LINE=${output#*' '};
       if [[ -z "$READLINE_POINT" ]]; then
           echo "$READLINE_LINE";
       else
           READLINE_POINT=0x7fffffff;
       fi
    }
    
    $ fcf __fzf_history__
    /usr/local/Cellar/fzf/0.42.0/shell/key-bindings.bash
    
    fzf ctrl-r
    1.4.1.1.17 -- fzf ctrl-r

ctrl-t

[!NOTE|label:references:]

  • to disable/reset osx default + and +

    • System SettingsKeyboardKeyboard Shutcuts...Mission Control keyboards ⇢ shortcuts

    • System SettingsDesktop & DockShortcuts... desktop & dock ⇢ Shortcuts

# preview file content using bat (https://github.com/sharkdp/bat)
FZF_CTRL_T_OPTS="--preview 'bat -n --color=always {}'"
FZF_CTRL_T_OPTS+=" --bind 'ctrl-/:change-preview-window(down|hidden|)'"
FZF_CTRL_T_OPTS+=" --bind 'ctrl-p:preview-up,ctrl-n:preview-down'"
FZF_CTRL_T_OPTS+=" --header 'CTRL-N/CTRL-P or CTRL-↑/CTRL-↓ to view contents'"
export FZF_CTRL_T_OPTS

# or
export FZF_CTRL_T_OPTS="
  --preview 'bat -n --color=always {}'
  --bind 'ctrl-p:preview-up,ctrl-n:preview-down'
  --bind 'ctrl-/:change-preview-window(down|hidden|)'"
fzf ctrl-t
1.4.1.1.18 -- fzf ctrl-t
  • __fzf_select__

    $ type __fzf_select__
    __fzf_select__ is a function
    __fzf_select__ ()
    {
        local cmd opts;
        cmd="${FZF_CTRL_T_COMMAND:-"command find -L . -mindepth 1 \\( -path '*/.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune     -o -type f -print     -o -type d -print     -o -type l -print 2> /dev/null | command cut -b3-"}";
        opts="--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore --reverse --scheme=path ${FZF_DEFAULT_OPTS-} ${FZF_CTRL_T_OPTS-} -m";
        eval "$cmd" | FZF_DEFAULT_OPTS="$opts" $(__fzfcmd) "$@" | while read -r item; do
            printf '%q ' "$item";
        done
    }
    
    $ fcf __fzf_select__
    __fzf_select__ 19 /Users/marslo/.marslo/utils/fzf/shell/key-bindings.bas
    
    $ mdfind key-bindings.bas
    /Users/marslo/iMarslo/tools/git/marslo/mbook/docs/devops/adminTools.md
    /usr/local/Cellar/fzf/0.42.0/shell/key-bindings.bash
    
  • __fzf_select_dir()

    # another ctrl-t script to select a directory and paste it into line
    __fzf_select_dir () {
      builtin typeset READLINE_LINE_NEW="$(
        command find -L . \( -path '*/\.*' -o -fstype dev -o -fstype proc \) \
                -prune \
                -o -type f -print \
                -o -type d -print \
                -o -type l -print 2>/dev/null \
        | command sed 1d \
        | command cut -b3- \
        | env fzf -m
      )"
    
      if [[ -n $READLINE_LINE_NEW ]]; then
        builtin bind '"\er": redraw-current-line'
        builtin bind '"\e^": magic-space'
        READLINE_LINE=${READLINE_LINE:+${READLINE_LINE:0:READLINE_POINT}}${READLINE_LINE_NEW}${READLINE_LINE:+${READLINE_LINE:READLINE_POINT}}
        READLINE_POINT=$(( READLINE_POINT + ${#READLINE_LINE_NEW} ))
      else
        builtin bind '"\er":'
        builtin bind '"\e^":'
      fi
    }
    
    builtin bind -x '"\C-x1": __fzf_select_dir'
    builtin bind '"\C-t": "\C-x1\e^\er"'
    

theme

# junegunn/seoul256.vim (dark)
export FZF_DEFAULT_OPTS='--color=bg+:#3F3F3F,bg:#4B4B4B,border:#6B6B6B,spinner:#98BC99,hl:#719872,fg:#D9D9D9,header:#719872,info:#BDBB72,pointer:#E12672,marker:#E17899,fg+:#D9D9D9,preview-bg:#3F3F3F,prompt:#98BEDE,hl+:#98BC99'

# junegunn/seoul256.vim (light)
export FZF_DEFAULT_OPTS='--color=bg+:#D9D9D9,bg:#E1E1E1,border:#C8C8C8,spinner:#719899,hl:#719872,fg:#616161,header:#719872,info:#727100,pointer:#E12672,marker:#E17899,fg+:#616161,preview-bg:#D9D9D9,prompt:#0099BD,hl+:#719899'

# morhetz/gruvbox
export FZF_DEFAULT_OPTS='--color=bg+:#3c3836,bg:#32302f,spinner:#fb4934,hl:#928374,fg:#ebdbb2,header:#928374,info:#8ec07c,pointer:#fb4934,marker:#fb4934,fg+:#ebdbb2,prompt:#fb4934,hl+:#fb4934'

# arcticicestudio/nord-vim
export FZF_DEFAULT_OPTS='--color=bg+:#3B4252,bg:#2E3440,spinner:#81A1C1,hl:#616E88,fg:#D8DEE9,header:#616E88,info:#81A1C1,pointer:#81A1C1,marker:#81A1C1,fg+:#D8DEE9,prompt:#81A1C1,hl+:#81A1C1'

# tomasr/molokai
export FZF_DEFAULT_OPTS='--color=bg+:#293739,bg:#1B1D1E,border:#808080,spinner:#E6DB74,hl:#7E8E91,fg:#F8F8F2,header:#7E8E91,info:#A6E22E,pointer:#A6E22E,marker:#F92672,fg+:#F8F8F2,prompt:#F92672,hl+:#F92672'
  • generating fzf color theme from vim color schemes

    let g:fzf_colors =
    \ { 'fg':         ['fg', 'Normal'],
      \ 'bg':         ['bg', 'Normal'],
      \ 'preview-bg': ['bg', 'NormalFloat'],
      \ 'hl':         ['fg', 'Comment'],
      \ 'fg+':        ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
      \ 'bg+':        ['bg', 'CursorLine', 'CursorColumn'],
      \ 'hl+':        ['fg', 'Statement'],
      \ 'info':       ['fg', 'PreProc'],
      \ 'border':     ['fg', 'Ignore'],
      \ 'prompt':     ['fg', 'Conditional'],
      \ 'pointer':    ['fg', 'Exception'],
      \ 'marker':     ['fg', 'Keyword'],
      \ 'spinner':    ['fg', 'Label'],
      \ 'header':     ['fg', 'Comment'] }
    
    :echo fzf#wrap()
    :call append('$', printf('export FZF_DEFAULT_OPTS="%s"', matchstr(fzf#wrap().options, "--color[^']*")))
    

tips

  • select by column

    [!NOTE]

    $ seq 20 | pr -ts' ' --column 4
    1 6 11 16
    2 7 12 17
    3 8 13 18
    4 9 14 19
    5 10 15 20
    
    $ seq 20 | pr -ts' ' --column 4 | fzf --sync --bind 'start:select-all+become:cat {+f2}'
    6
    7
    8
    9
    10
    
    $ seq 20 | pr -ts' ' --column 4 | fzf --sync --bind 'start:select-all+become:echo {+2}'
    6 7 8 9 10
    
  • --with-nth

    [!NOTE]

    $ echo {a..z} | fzf --with-nth='1..3'
    
    fzf --with-nth
    1.4.1.1.21 -- fzf --with-nth
    # https://github.com/junegunn/fzf/issues/1323#issuecomment-499615418
    # for git comment show
    $ git log --pretty=oneline |
      fzf --ansi --delimiter=' ' --no-multi --preview='git show --color=always {1}' --with-nth=2.. |
      cut --delimiter=' ' --field=1
    
    git with-nth for git comments
    1.4.1.1.22 -- git with-nth for git comments
    $ echo -e 'first line\tfirst preview\nsecond line\tsecond preview' |
      fzf --delimiter='\t' --with-nth=1 --preview='echo {2}'
    
    fzf --with-nth for preview
    1.4.1.1.23 -- fzf --with-nth for preview
  • --track

    $ git log --oneline --graph --color=always |
      nl |
      fzf --ansi --track --no-sort --layout=reverse-list
    
    fzf --track for git
    1.4.1.1.24 -- fzf --track for git
  • select-all

    $ seq 3 | fzf --multi --sync --bind start:last+select-all
    
    fzf select-all
    1.4.1.1.25 -- fzf select-all
  • select-n

    [!TIP]

    # select top 2 and move down
    $ seq 10 | fzf --multi --sync --reverse --bind start:select+down+select+down
    
    # select top 2
    $ seq 10 | fzf --multi --sync --reverse --bind start:select+down+select
    
    select and move down
    1.4.1.1.26 -- select and move down
    select
    1.4.1.1.27 -- select
  • for git

    [!NOTE]

    # cannot be used to grab a sha as an argument.
    fshow() {
      git log --color=always \
          --format="%C(auto)%h%d %s %C(black)%C(bold)%cr" "$@" |
      fzf --ansi --no-sort --reverse --tiebreak=index --bind=ctrl-s:toggle-sort \
          --bind "ctrl-o:execute(git show --color=always {1})"
    }
    
    • view history by fzf, show revision number finally

      $ git log --pretty=oneline \
            | fzf --ansi --delimiter=' ' --no-multi --preview='git show --color=always {1}' --with-nth=2.. \
            | cut --delimiter=' ' --field=1
      # or
      $ git log --pretty=oneline --all \
            | fzf --ansi --no-multi --preview='git show --color=always {1}' --with-nth=2.. \
            | awk '{print $1}'
      
    • pr checkout

      [!NOTE]

      function pr-checkout() {
        local jq_template pr_number
      
        jq_template='"'\
          '#\(.number) - \(.title)'\
          '\t'\
          'Author: \(.user.login)\n'\
          'Created: \(.created_at)\n'\
          'Updated: \(.updated_at)\n\n'\
          '\(.body)'\
          '"'
      
        pr_number=$(
          gh api 'repos/:owner/:repo/pulls' |
          jq ".[] | $jq_template" |
          sed -e 's/"\(.*\)"/\1/' -e 's/\\t/\t/' |
          fzf \
            --with-nth=1 \
            --delimiter='\t' \
            --preview='echo -e {2}' \
            --preview-window=top:wrap |
          sed 's/^#\([0-9]\+\).*/\1/'
        )
      
        if [ -n "$pr_number" ]; then
          gh pr checkout "$pr_number"
        fi
      }
      
  • creating feature branches from JIRA issues

    function create-branch() {
      # The function expects that username and password are stored using secret-tool.
      # To store these, use
      # secret-tool store --label="JIRA username" jira username
      # secret-tool store --label="JIRA password" jira password
    
      local jq_template query username password branch_name
    
      jq_template='"'\
        '\(.key). \(.fields.summary)'\
        '\t'\
        'Reporter: \(.fields.reporter.displayName)\n'\
        'Created: \(.fields.created)\n'\
        'Updated: \(.fields.updated)\n\n'\
        '\(.fields.description)'\
        '"'
      query='project=BLOG AND status="In Progress" AND assignee=currentUser()'
      username=$(secret-tool lookup jira username)
      password=$(secret-tool lookup jira password)
    
      branch_name=$(
        curl \
          --data-urlencode "jql=$query" \
          --get \
          --user "$username:$password" \
          --silent \
          --compressed \
          'https://jira.example.com/rest/api/2/search' |
        jq ".issues[] | $jq_template" |
        sed -e 's/"\(.*\)"/\1/' -e 's/\\t/\t/' |
        fzf \
          --with-nth=1 \
          --delimiter='\t' \
          --preview='echo -e {2}' \
          --preview-window=top:wrap |
        cut -f1 |
        sed -e 's/\. /\t/' -e 's/[^a-zA-Z0-9\t]/-/g' |
        awk '{printf "%s/%s", $1, tolower($2)}'
      )
    
      if [ -n "$branch_name" ]; then
        git checkout -b "$branch_name"
      fi
    }
    
  • localhost:$FZF_PORT

    $ fzf --listen --sync --bind 'focus:transform-header:curl -s localhost:$FZF_PORT?limit=0 | jq .' --height 100%
    
  • --style

    [!NOTE|label:references:]

    fzf style
    1.4.1.1.28 -- fzf style

fzf with git

[!NOTE|label:references:]

Copyright © marslo 2020-2025 all right reserved,powered by GitbookLast Modified: 2026-03-03 00:44:31

results matching ""

    No results matching ""