# devops

* [`fzf`](#fzf)
  * [install](#install)
  * [shortcuts](#shortcuts)
    * [action and select](#action-and-select)
    * [movement](#movement)
    * [ctrl-t](#ctrl-t)
  * [usage](#usage)
    * [magic vim](#magic-vim)
    * [smart vimdiff](#smart-vimdiff)
    * [smart cat](#smart-cat)
    * [smart copy](#smart-copy)
    * [others](#others)
  * [advanced usage](#advanced-usage)
    * [venv selector](#venv-selector)
    * [chrome](#chrome)
    * [man page](#man-page)
    * [git alias](#git-alias)
    * [environment](#environment)
    * [process](#process)
    * [kubectl](#kubectl)
    * [homebrew](#homebrew)
  * [config](#config)
    * [`ctrl-r`](#ctrl-r)
    * [`ctrl-t`](#ctrl-t)
    * [theme](#theme)
  * [tips](#tips)
  * [fzf with git](#fzf-with-git)
* [`fd`](#fd)
  * [advanced usage](#advanced-usage-1)
* [`rg` the faster `mg`](#rg-the-faster-mg)
  * [usage](#usage-1)
  * [tips](#tips-1)
  * [using inside in vim](#using-inside-in-vim)
* [`ag` the faster `mg`](#ag-the-faster-mg)
* [`fzy`](#fzy)
* [`bat`](#bat)
  * [usage](#usage-2)
  * [tips](#tips-2)
  * [config](#config-1)
  * [theme](#theme-1)
* [`tldr`](#tldr)
  * [install](#install-1)
  * [config](#config-2)
* [`cht.sh`](#chtsh)
  * [links](#links)
  * [.cht.sh.conf](#chtshconf)
    * [CHTSH environment](#chtsh-environment)
    * [theme](#theme-2)
    * [mode](#mode)
  * [`--shell`](#--shell)
* [`cheat`](#cheat)
  * [configure](#configure)
    * [theme](#theme-3)
* [`ncdu` : NCurses Disk Usage](#ncdu--ncurses-disk-usage)
* [theme and colors](#theme-and-colors)
  * [`c`: bash-color](#c-bash-color)
  * [`ansi`](#ansi)
  * [`diff-so-fancy`](#diff-so-fancy)
* [utility](#utility)
  * [`elinks`](#elinks)
  * [`duf`](#duf)
  * [`enhancd`](#enhancd)
  * [watchman](#watchman)

{% hint style="info" %}

> references:
>
> * [Best UNIX shell-based tools](https://gist.github.com/mbbx6spp/1429161)
> * [\* alebcay/awesome-shell](https://github.com/alebcay/awesome-shell/tree/master) | [\* zh-cn](https://github.com/alebcay/awesome-shell/blob/master/README_ZH-CN.md)
>   * [nosarthur/awesome-shell](https://github.com/nosarthur/awesome-shell)
> * [\* rockerBOO/awesome-neovim](https://github.com/rockerBOO/awesome-neovim)
> * [sindresorhus/awesome](https://github.com/sindresorhus/awesome)
> * [Sainnhe's Dashboard: os in web browser](https://dashboard.sainnhe.dev/)
>   * [osx](https://macos.sainnhe.dev/) | [windows](https://windows.sainnhe.dev/)
> * others
>   * [bayandin/awesome-awesomeness](https://github.com/bayandin/awesome-awesomeness)
>   * [emijrp/awesome-awesome](https://github.com/emijrp/awesome-awesome)
>   * [kahun/awesome-sysadmin](https://github.com/kahun/awesome-sysadmin)
>   * [stup - Daily notes in the terminal](https://iridakos.com/programming/2020/04/20/stup-cli-notes)
>   * [Awesome Command-Line Tools](https://www.vimfromscratch.com/articles/awesome-command-line-tools)
> * [My Minimalist Over-powered Linux Setup Guide](https://medium.com/@jonyeezs/my-minimal-over-powered-linux-setup-guide-710931efb75b)
> * [\* devynspencer/cute\_commands.sh](https://gist.github.com/devynspencer/cfdce35b3230e72214ef)
> * [Use Bash Strict Mode (Unless You Love Debugging)](http://redsymbol.net/articles/unofficial-bash-strict-mode/)
> * [Learn Enough Command Line to Be Dangerous](https://www.learnenough.com/command-line-tutorial/basics)
> * [jlevy/the-art-of-command-line](https://github.com/jlevy/the-art-of-command-line)
> * [pv - Pipe Viewer](https://www.ivarch.com/programs/pv.shtml)
>   {% endhint %}

## [`fzf`](https://github.com/junegunn/fzf)

{% hint style="info" %}

> * fuzzy completion in bash
>   * `$ cat **<tab>`
>   * `$ unset **<tab>`
>   * `$ unalias **<tab>`
>   * `$ export **<tab>`
>   * `$ ssh **<tab>`
>   * `$ kill -9 **<tab>`
>     {% endhint %}

> \[!NOTE|label:references:]
>
> * [\* fzf - FuZzy Finder Tutorial](https://www.youtube.com/watch?v=tB-AgxzBmH8)
>   * [Examples (completion)](https://github.com/junegunn/fzf/wiki/Examples-\(completion\))
>   * [Examples (vim)](https://github.com/junegunn/fzf/wiki/Examples-\(vim\))
>   * [On MacVim with iTerm2](https://github.com/junegunn/fzf/wiki/On-MacVim-with-iTerm2)
> * [\* junegunn/fzf](https://github.com/junegunn/fzf)
>   * [fzf wiki](https://github.com/junegunn/fzf/wiki)
>   * [fzf screencasts by gotbletu](https://www.youtube.com/playlist?list=PLqv94xWU9zZ2fMsMMDF4PjtNHCeBFbggD)
>   * [junegunn/fzf-git.sh](https://github.com/junegunn/fzf-git.sh)
>   * fzf basics:
>     * [layout](https://qmacro.org/blog/posts/2021/02/02/fzf-the-basics-part-1-layout/)
>     * [search results](https://qmacro.org/blog/posts/2021/02/07/fzf-the-basics-part-2-search-results/)
>   * [examples](https://github.com/junegunn/fzf/wiki/examples)
>     * [Man pages](https://github.com/junegunn/fzf/wiki/Examples#man-pages)
>     * [Git](https://github.com/junegunn/fzf/wiki/Examples#git)
>   * [Advanced fzf examples](https://github.com/junegunn/fzf/blob/master/ADVANCED.md) | [Advanced fzf examples](https://fossies.org/linux/fzf/ADVANCED.md)
> * usage
>   * [\*\* A Practical Guide to fzf: Building a File Explorer](https://thevaluable.dev/practical-guide-fzf-example/)
>   * [\* Find anything you need with fzf, the Linux fuzzy finder tool](https://www.redhat.com/sysadmin/fzf-linux-fuzzy-finder)
>   * [\* Improving shell workflows with fzf](https://seb.jambor.dev/posts/improving-shell-workflows-with-fzf/)
>   * [Introduction to fzf command](https://www.baeldung.com/linux/fzf-command)
>   * [Why you should be using fzf, the command line fuzzy finder](https://www.freecodecamp.org/news/fzf-a-command-line-fuzzy-finder-missing-demo-a7de312403ff/)
>   * [Linux下搜索神器fzf的配置和使用](https://blog.csdn.net/qq_39852676/article/details/126820806)
>   * [serenevoid/fzf\_config.md](https://gist.github.com/serenevoid/13239752cfa41a75a69446b7beb26d7a)
>   * [4 Useful fzf Tricks for Your Terminal](https://pragmaticpineapple.com/four-useful-fzf-tricks-for-your-terminal/)
>   * [Day 18 - Awesome command-line fuzzy finding with fzf](https://sysadvent.blogspot.com/2017/12/day-18-awesome-command-line-fuzzy.html)
> * more tools
>   * [ggVGc/fzf\_browser](https://github.com/ggVGc/fzf_browser/tree/master)
>   * [garybernhardt/selecta](https://github.com/garybernhardt/selecta)
>   * [scripts/rgfzf](https://github.com/naggie/dotfiles/blob/master/include/scripts/rgfzf)
> * vim
>   * [Improving Vim Workflow With fzf](https://pragmaticpineapple.com/improving-vim-workflow-with-fzf/)
>   * [\* How to search faster in Vim with FZF.vim](https://dev.to/iggredible/how-to-search-faster-in-vim-with-fzf-vim-36ko)
>   * [\* How FZF and ripgrep improved my workflow](https://sidneyliebrand.medium.com/how-fzf-and-ripgrep-improved-my-workflow-61c7ca212861) | [SidOfc/vim-rg-outdated-command.vim](https://gist.github.com/SidOfc/ba43acade7f4a1bf9faf57d16b33616a#file-vim-rg-outdated-command-vim)
>
>     ```vim
>     " fzf.vim now supports this command out of the box
>     " so this code is no longer needed.
>     command! -bang -nargs=* Rg
>       \ call fzf#vim#grep(
>       \   'rg --column --line-number --hidden --ignore-case --no-heading --color=always '.shellescape(<q-args>), 1,
>       \   <bang>0 ? fzf#vim#with_preview({'options': '--delimiter : --nth 4..'}, 'up:60%')
>       \           : fzf#vim#with_preview({'options': '--delimiter : --nth 4..'}, 'right:50%:hidden', '?'),
>       \   <bang>0)
>     ```
> * customize
>   * [\* fzf wiki: color themes](https://github.com/junegunn/fzf/wiki/Color-schemes)
>   * [\* fzf-color-theme.css](https://github.com/marslo/ibook/blob/marslo/docs/devops/fzf-color-theme.css)
>   * [#692 Custom selected character](https://github.com/junegunn/fzf/issues/692)

![fzf and vim](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-a793ac54325b2505ac88e453a0ba8fdb97fdb4c3%2Ffzf-vim.gif?alt=media)

### install

> \[!NOTE|label:references:]
>
> * [FZF\_DEFAULT\_OPTS](https://github.com/junegunn/fzf/issues/3053#issuecomment-1330285106)

```bash
$ 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
# debine
$ sudo apt install fd

$ 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 "
$ FZF_DEFAULT_OPTS+="--marker='󱍢 ' --pointer='▌' "
$ FZF_DEFAULT_OPTS+="--prompt='󰩀 ' --info='inline: 󰨿 ' "
$ FZF_DEFAULT_OPTS+="--info-command='echo \"\x1b[33;1m\$FZF_POS\x1b[m ~ \$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:-1,bg+:-1,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](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-ad876a219a6ee9594f0f3ac9b8ad3aa373860c4f%2Ffzf-color-themes.png?alt=media)

![fzf color theme: gruvbox-marslo](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-08a01608070fb1c48148c3023b87d1d89ddf7b2d%2Ffzf-color-theme-gruvbox-marslo.png?alt=media)

| NAME    | VALUE                                       |
| ------- | ------------------------------------------- |
| pointer | `▏`, `▕`, `┃`, `▎`, `▌`, `▊`, `▉`, `▒`, `ⵗ` |

```bash
# -- 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"
```

```bash
$ 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]
  >
  > * in wsl Ubuntu, the fzf version is `0.29`
  >
  >   ```bash
  >   $ sudo apt search fzf
  >   Sorting... Done
  >   Full Text Search... Done
  >   fzf/jammy 0.29.0-1 amd64
  >     general-purpose command-line fuzzy finder
  >   ```
  > * [\* Fzf – A Quick Fuzzy File Search from Linux Terminal](https://www.tecmint.com/fzf-fuzzy-file-search-from-linux-terminal/)

  ```bash
  $ 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`:
  >
  >   ```bash
  >   $ 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](https://stackoverflow.com/a/46843526/2940319)

  * `~/.curlrc`

    ```bash
    $ echo '--insecure' >> ~/.curlrc
    ```
  * offline installation

    ```bash
    ################ 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:]
>
> * [Using the finder](https://github.com/junegunn/fzf#using-the-finder)
> * [multiple select](https://github.com/junegunn/fzf.vim/issues/40#issuecomment-156037468)
>   * enable via : `--multi` or `-m`
>   * disable via : `--no-multi` or `+m`
> * [Customizing fzf Keybindings](https://thevaluable.dev/fzf-shell-integration/)

| KEYSTROKE                    |   BASH FUNCTION   |     ZSH FUNCTION     | ENVIRONMENT VARIABLE |
| ---------------------------- | :---------------: | :------------------: | -------------------- |
| <kbd>CTRL</kbd>-<kbd>t</kbd> |  `__fzf_select__` |       `__fsel`       | `FZF_CTRL_T_COMMAND` |
| <kbd>CTRL</kbd>-<kbd>r</kbd> | `__fzf_history__` | `fzf-history-widget` | `FZF_CTRL_R_OPTS`    |
| <kbd>ALT</kbd>-<kbd>c</kbd>  |    `__fzf_cd__`   |    `fzf-cd-widget`   | `FZF_ALT_C_COMMAND`  |

#### action and select

| OPEN                            | SELECT ALL                     | DESELECT ALL                   | TOGGLE ALL                     | MULTIPLE SELECT |
| ------------------------------- | ------------------------------ | ------------------------------ | ------------------------------ | --------------- |
| <kbd>⏎</kbd>                    | <kbd>ctrl</kbd> + <kbd>s</kbd> | <kbd>ctrl</kbd> + <kbd>d</kbd> | <kbd>ctrl</kbd> + <kbd>t</kbd> | <kbd>⇥</kbd>    |
| <kbd>shift</kbd> + <kbd>⇥</kbd> |                                |                                |                                |                 |

#### movement

| PREVIOUS                       | NEXT                           | MULTIPLE SELECT                 |
| ------------------------------ | ------------------------------ | ------------------------------- |
| <kbd>↑</kbd>                   | <kbd>↓</kbd>                   | <kbd>⇥</kbd>                    |
| <kbd>ctrl</kbd> + <kbd>k</kbd> | <kbd>ctrl</kbd> + <kbd>j</kbd> |                                 |
| <kbd>ctrl</kbd> + <kbd>p</kbd> | <kbd>ctrl</kbd> + <kbd>n</kbd> | <kbd>shift</kbd> + <kbd>⇥</kbd> |
| <kbd>ctrl</kbd> + <kbd>k</kbd> | <kbd>ctrl</kbd> + <kbd>j</kbd> |                                 |

#### ctrl-t

> \[!TIP]
>
> * customized shortcut key via:
>
>   ```bash
>   export FZF_CTRL_T_OPTS="${FZF_CTRL_T_OPTS} --bind 'ctrl-p:preview-up,ctrl-n:preview-down'"
>   export FZF_CTRL_T_OPTS="${FZF_CTRL_T_OPTS} --bind 'ctrl-/:change-preview-window(down|hidden|)'"
>   ```
> * [#358: Keyboard bindings for scrolling preview window?](https://github.com/junegunn/fzf.vim/issues/358#issuecomment-769589975)
> * [#211: Scroll inside preview?](https://github.com/junegunn/fzf.vim/issues/211)

* file list:

  | PREVIOUS                       | NEXT                           | CHANGE PREVIEW WINDOWS         |
  | ------------------------------ | ------------------------------ | ------------------------------ |
  | <kbd>↑</kbd>                   | <kbd>↓</kbd>                   | <kbd>ctrl</kbd> + <kbd>/</kbd> |
  | <kbd>ctrl</kbd> + <kbd>k</kbd> | <kbd>ctrl</kbd> + <kbd>j</kbd> |                                |
  | <kbd>ctrl</kbd> + <kbd>p</kbd> | <kbd>ctrl</kbd> + <kbd>n</kbd> |                                |
* preview content:

  | PREVIOUS                        | NEXT                            |
  | ------------------------------- | ------------------------------- |
  | <kbd>shift</kbd> + <kbd>↑</kbd> | <kbd>shift</kbd> + <kbd>↓</kbd> |
  | <kbd>ctrl</kbd> + <kbd>↑</kbd>  | <kbd>ctrl</kbd> + <kbd>↓</kbd>  |
  | <kbd>ctrl</kbd> + <kbd>p</kbd>  | <kbd>ctrl</kbd> + <kbd>n</kbd>  |

### usage

> \[!NOTE|label:references:]
>
> * [Advanced fzf examples](https://github.com/junegunn/fzf/blob/master/ADVANCED.md)
> * [Examples](https://github.com/junegunn/fzf/wiki/examples)

#### magic vim

> \[!TIP]
>
> * [v](https://github.com/junegunn/fzf/wiki/Examples#v)
> * [Opening files](https://github.com/junegunn/fzf/wiki/Examples#opening-files)

```bash
# magic vim - fzf list in recent modified order
# @author      : marslo
# @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.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 paramters, then call fzf and using vim to open selected file
#   - if `vim` commands with paramters
#       - if single paramters and parameters is directlry, 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 voption
  local target
  local orgv                               # force using vim instead of nvim
  local VIM="$(type -P vim)"
  local foption='--multi --cycle '
  local fdOpt="--type f --hidden --follow --unrestricted --ignore-file $HOME/.fdignore --exclude Music"
  [[ "$(pwd)" = "$HOME" ]] && fdOpt+=' --max-depth 3'
  if ! uname -r | grep -q "Microsoft"; then fdOpt+=' --exec-batch ls -t'; fi

  while [[ $# -gt 0 ]]; do
    case "$1" in
                 -v ) orgv=1            ; 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 ;;
                 -* ) foption+="$1 $2 " ; shift 2 ;;
                  * ) break                       ;;
    esac
  done

  [[ 1 -ne "${orgv}" ]] && command -v nvim >/dev/null && VIM="$(type -P nvim)"

  if [[ 0 -eq $# ]] && [[ -z "${voption}" ]]; then
    fd . ${fdOpt} | fzf ${foption} --bind="enter:become(${VIM} {+})"
  elif [[ 1 -eq $# ]] && [[ -d $1 ]]; then
    [[ '.' = "${1}" ]] && target="${1}" || target=". ${1}"
    fd ${target} ${fdOpt} | fzf ${foption} --bind="enter:become(${VIM} {+})"
  else
    # shellcheck disable=SC2068
    "${VIM}" ${voption} $@
  fi
}

# v - open files in ~/.vim_mru_files       # https://github.com/junegunn/fzf/wiki/Examples#v
# @author      : marslo
# @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.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 - open files by [vim] in whole [r]epository
#        same series: [`cdr`](https://github.com/marslo/dotfiles/blob/main/.marslo/bin/ffunc.sh#L310-L318)
#        similar with [`:Gfiles`](https://github.com/junegunn/fzf.vim?tab=readme-ov-file#commands)
# @author      : marslo
# @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.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
  isrepo=$(git rev-parse --is-inside-work-tree >/dev/null 2>&1; echo $?)
  if [[ 0 = "${isrepo}" ]]; then
    repodir="$(git rev-parse --show-toplevel)"
    # shellcheck disable=SC2164
    files=$( fd . "${repodir}" --type f --hidden --ignore-file ~/.fdignore --exec-batch ls -t |
                  xargs -I{} bash -c "echo {} | sed \"s|${repodir}/||g\"" |
                  fzf --multi -0 |
                  xargs -I{} bash -c "echo ${repodir}/{}"
           )
    # shellcheck disable=SC2046
    [[ -z "${files}" ]] || vim $(xargs <<< "${files}")
  else
    vim
  fi
}

# vimrc - open rc files list from "${rcPaths}" to quick update/modify rc files
# @author      : marslo
# @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.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                               # force using vim instead of nvim
  local rcPaths="$HOME/.config/nvim $HOME/.marslo"
  local VIM="$(type -P vim)"
  local foption='--multi --cycle '
  local fdOpt="--type f --hidden --follow --unrestricted --ignore-file $HOME/.fdignore"
  if ! uname -r | grep -q "Microsoft"; then fdOpt+=' --exec-batch ls -t'; fi

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

  [[ 1 -ne "${orgv}" ]] && command -v nvim >/dev/null && VIM="$(type -P nvim)"
  fdInRC | sed -rn 's/^[^|]* \| (.+)$/\1/p' \
         | fzf ${foption} --bind="enter:become(${VIM} {+})" \
                          --bind "ctrl-y:execute-silent(echo -n {+} | ${COPY})+abort" \
                          --header 'Press CTRL-Y to copy name into clipboard'
}

```

* `fdInRC`

  ```bash
  # shellcheck disable=SC2089,SC2090
  function fdInRC() {
    local rcPaths="$HOME/.config/nvim $HOME/.marslo $HOME/.idlerc $HOME/.ssh"
    local fdOpt="--type f --hidden --follow --unrestricted --ignore-file $HOME/.fdignore"
    fdOpt+=' --exec stat --printf="%y | %n\n"'
    (
      eval "fd --max-depth 1 --hidden '.*rc|.*profile|.*ignore' $HOME ${fdOpt}";
      echo "${rcPaths}" | fmt -1 | xargs -I{} bash -c "fd . {} --exclude ss/ --exclude log/ --exclude .completion/ --exclude bin/bash-completion/ ${fdOpt}" ;
    ) |  sort -r
  }
  ```

![fzf magic vim](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-bef7695e8dedf867d8e50bb36bc1682606f21d12%2Ffzf-magic-vim.gif?alt=media)

![fzf vimrc](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-3d804384841edc49c3bc8e7fcc7037ca2711c0ad%2Ffzf-vimrc.gif?alt=media)

#### smart vimdiff

```bash
function fzfInPath() {                   # return file name via fzf in particular folder
  local fdOpt="--type f --hidden --follow --unrestricted --ignore-file $HOME/.fdignore"
  if ! uname -r | grep -q 'Microsoft'; then fdOpt+=' --exec-batch ls -t'; fi
  [[ '.' = "${1}" ]] && path="${1}" || path=". ${1}"
  eval "fd ${path} ${fdOpt} | fzf --multi --cycle ${*:2} --header 'filter in ${1} :'"
}

# magic vimdiff - using fzf list in recent modified order
# @author      : marslo
# @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.marslo/bin/ffunc.sh
# @description :
#   - if any of paramters 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 paramters 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 option
  local var

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

  if [[ 0 -eq $# ]]; then
    lFile=$(fzfInPath '.' "${option}")
    # shellcheck disable=SC2154
    rFile=$(fzfInPath "${iRCHOME}" "${option}")
  elif [[ 1 -eq $# ]]; then
    lFile=$(fzfInPath '.' "${option}")
    [[ -d "$1" ]] && rFile=$(fzfInPath "$1" "${option}") || rFile="$1"
  elif [[ 2 -eq $# ]]; then
    [[ -d "$1" ]] && lFile=$(fzfInPath "$1" "${option}") || lFile="$1"
    [[ -d "$2" ]] && rFile=$(fzfInPath "$2" "${option}") || rFile="$2"
  else
    var="${*: 1:$#-2}"
    [[ -d "${*: -2:1}" ]] && lFile=$(fzfInPath "${*: -2:1}") || lFile="${*: -2:1}"
    [[ -d "${*: -1}"   ]] && rFile=$(fzfInPath "${*: -1}")   || rFile="${*: -1}"
  fi

  [[ -f "${lFile}" ]] && [[ -f "${rFile}" ]] && $(type -P vim) -d ${var} "${lFile}" "${rFile}"
}

# vd - open vimdiff loaded files from ~/.vim_mru_files
# @author      : marslo
# @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.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 `-q` ( [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 vimdiff loaded files from ~/.vim_mru_files
  [[ 1 -eq $# ]] && [[ '-q' = "$1" ]] && opt='--bind start:select+down+select+accept' || opt=''
  # shellcheck disable=SC2046
  files=$( grep --color=none -v '^#' ~/.vim_mru_files |
           xargs -d'\n' -I_ bash -c "sed 's:\~:$HOME:' <<< _" |
           fzf --multi 3 --sync --cycle --reverse ${opt}
         ) &&
  vimdiff $(xargs <<< "${files}")
}
```

![vimdiff](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-5829f1dde463d1452d7604c09f5cbc8b407341e1%2Ffzf-vimdiff-vd.gif?alt=media)

#### smart cat

```bash
# smart cat - using bat by default for cat content, respect bat options
# @author      : marslo
# @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.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  paramter, then search file via `fzf` and shows via `bat`
#   - if `bat` with 1   paramter, 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 fdOpt='--type f --hidden --follow --exclude .git --exclude node_modules'
  local CAT="$(type -P cat)"
  if ! uname -r | grep -q "Microsoft"; then fdOpt+=' --exec-batch ls -t'; fi
  command -v nvim >/dev/null && CAT="$(type -P bat)"

  if [[ 0 -eq $# ]]; then
    "${CAT}" --theme='gruvbox-dark' $(fd . ${fdOpt} | fzf --multi --cycle --exit-1)
  elif [[ '-c' = "$1" ]]; then
    $(type -P cat) "${@:2}"
  elif [[ 1 -eq $# ]] && [[ -d $1 ]]; then
    local target=$1;
    fd . "${target}" ${fdOpt} |
      fzf --multi --cycle --exit-1 --bind="enter:become(${CAT} --theme='gruvbox-dark' {+})" ;
  else
    "${CAT}" --theme='gruvbox-dark' "${@:1:$#-1}" "${@: -1}"
  fi
}
```

![smart cat](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-9db2f7ca896309a83d2c5e527dd2cf9e69871e5e%2Ffzf-smart-cat.gif?alt=media)

#### smart copy

```bash
# smart copy - using `fzf` to list files and copy the selected file
# @author      : marslo
# @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.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
  local fdOpt='--type f --hidden --follow --exclude .git --exclude node_modules'
  [[ -z "${COPY}" ]] && echo -e "$(c Rs)ERROR: 'copy' function NOT support :$(c) $(c Ri)$(uanme -v)$(c)$(c Rs). EXIT..$(c)" && return;

  if [[ 0 -eq $# ]]; then
    file=$(fzf --cycle --exit-0) &&
      "${COPY}" < "${file}" &&
      echo -e "$(c Wd)>>$(c) $(c Gis)${file}$(c) $(c Wdi)has been copied ..$(c)"
  elif [[ 1 -eq $# ]] && [[ -d $1 ]]; then
    local target=$1;
    file=$( fd . "${target}" ${fdOpt} | fzf --cycle --exit-0 ) &&
      "${COPY}" < "${file}" &&
      echo -e "$(c Wd)>>$(c) $(c Gis)${file}$(c) $(c Wdi)has been copied ..$(c)"
  else
    "${COPY}" < "$1"
  fi
}
```

![smart copy](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-4067757ee20e923e7a8e2c5516dffb96d2bace0a%2Ffzf-smart-copy.gif?alt=media)

#### others

* image view

  > \[!NOTE]
  >
  > * [eddieantonio/imgcat](https://github.com/eddieantonio/imgcat)

  ```bash
  # imgview - fzf list and preview images
  # @author      : marslo
  # @source      : https://github.com/marslo/mylinux/blob/master/confs/home/.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 image 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(echo -n {+} | pbcopy)+abort' \
             --header 'Press CTRL-Y to copy name into clipboard' \
             --preview-window 'down,80%,wrap' \
             --exit-0 \
    >/dev/null || true
  }
  ```
* [open files](https://github.com/junegunn/fzf/wiki/examples#opening-files)
  * `fs`

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

    ```bash
    # 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`

    ```bash
    # 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](https://github.com/junegunn/fzf/wiki/Examples#general)

  > \[!NOTE]
  >
  > * [#1057 Feature request: new option preview-window-scroll](https://github.com/junegunn/fzf/issues/1057#issuecomment-339347148)
  > * [gnanderson/fif.sh](https://gist.github.com/gnanderson/d74079d16714bb8b2822a7a07cc883d4)
  > * [Switching to fzf-only search mode](https://github.com/junegunn/fzf/blob/master/ADVANCED.md#switching-to-fzf-only-search-mode)
  > * [Switching between Ripgrep mode and fzf mode](https://github.com/junegunn/fzf/blob/master/ADVANCED.md#switching-to-fzf-only-search-mode)

  ```bash
  function fif() {                           # [f]ind-[i]n-[f]ile
    if [ ! "$#" -gt 0 ]; then echo "Need a string to search for!"; return 1; fi
    $(type -P rg) --files-with-matches --no-messages --hidden --follow --smart-case "$1" |
    fzf --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\" {} \
                  "
  }

  # 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](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-79b46eab47babe65965149694da8c51f5fb6b084%2Ffzf-fif-rg.gif?alt=media)
* changing directory

  > \[!NOTE|label:references:]
  >
  > * [changing directory](https://github.com/junegunn/fzf/wiki/examples#changing-directory)
  > * fuzzy-cd : [rumpelsepp/fcd.fish](https://gist.github.com/rumpelsepp/b1b416f52d6790de1aee) | [chrisnorris/fcd.fish](https://gist.github.com/chrisnorris/fe57c7855fd87a2636999edf1d4d735b)
  > * [l4u/autojump\_fzf.fish](https://gist.github.com/l4u/06502cf680b9a3817efddfb0a9a6ede8)

  * `cdp`

    ```bash
    # shellcheck disable=SC2034,SC2316
    function cdp() {                           # cdp - [c][d] to selected [p]arent directory
      local declare dirs=()
      get_parent_dirs() {
        if [[ -d "${1}" ]]; then dirs+=("$1"); else return; fi
        if [[ "${1}" == '/' ]]; then
          for _dir in "${dirs[@]}"; do echo $_dir; done
        else
          # shellcheck disable=SC2046
          get_parent_dirs $(dirname "$1")
        fi
      }
      # shellcheck disable=SC2155,SC2046
      local DIR=$(get_parent_dirs $(realpath "${1:-$PWD}") | fzf-tmux --tac)
      cd "$DIR" || return
    }
    ```
  * `cdf`

    ```bash
    function cdf() {                           # [c][d] into the directory of the selected [f]ile
      local file
      local dir
      # shellcheck disable=SC2164
      file=$(fzf +m -q "$1") && dir=$(dirname "$file") && cd "$dir"
    }
    ```
  * `cdd`

    ```bash
    function cdd() {                           # cdd - [c][d] to selected sub [d]irectory
      local dir
      # shellcheck disable=SC2164
      dir=$(fd --type d --hidden --ignore-file ~/.fdignore | fzf --no-multi -0) && cd "${dir}"
    }
    ```
  * `cdr`

    ```bash
    function cdr() {                           # cdd - [c][d] to selected [r]epo directory
      local repodir
      repodir="$(git rev-parse --show-toplevel)"
      # shellcheck disable=SC2164
      dir=$( ( echo './'; fd . "${repodir}" --type d --hidden --ignore-file ~/.fdignore |
                         xargs -I{} bash -c "echo {} | sed \"s|${repodir}/||g\""
             ) | fzf --no-multi -0
           ) && cd "${repodir}/${dir}"
    }
    ```
* [Interactive cd](https://github.com/junegunn/fzf/wiki/Examples#interactive-cd)

  ```bash
  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
  }
  ```

  * `fd`

    > \[!DANGER]**conflict with fd-find**

    ```bash
    # 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`

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

### advanced usage

#### venv selector

```bash
# 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)

  ```bash
  # 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]
>
> * [fzf example: man page](https://github.com/junegunn/fzf/wiki/examples#man-pages)
> * [`fzf-man-widget()`](https://github.com/junegunn/fzf/wiki/examples#fzf-man-pages-widget-for-zsh)
> * [apropos(1) — Linux manual page](https://man7.org/linux/man-pages/man1/apropos.1.html)
> * [`fzf_apropos()`](https://gist.github.com/igemnace/9b6fb8c2885c3e35299b3a122e1009e5)

```bash
# 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

  ```bash
  $ 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](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-60ed85ffd79fff9f70d73c3f02ec37d9a99f0872%2Ffzf-fman.gif?alt=media)

#### git alias

> \[!TIP]
>
> * [\* iMarslo : git-del](https://github.com/marslo/mylinux/raw/master/confs/home/.marslo/bin/git-del) to delete both local and remote branches automatically
> * [junegunn/fzf-git.sh](https://github.com/junegunn/fzf-git.sh)

```
[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

  ```bash
  # 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 paramter 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:
  > ```
  >
  > ````
  > ```bash
  > $ unset ,,<TAB>
  > # by deafult
  > $ unset **<TAB>
  > ```
  > ````

  ```bash
  # 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 varialbe 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

  ```bash
  # 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](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-3bc00792747707ab5027424c6ff75db1ed794e24%2Ffzf-eclr.gif?alt=media)
* print and copy

  > \[!NOTE|label:references:]
  >
  > * `environ – user environment` : ( `man environ` )
  > * [`printenv`](https://www.gnu.org/software/coreutils/manual/html_node/printenv-invocation.html)

  ```bash
  # 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](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-297b8abff3e9d06a405d88f9037e2a2443152956%2Ffzf-penv.gif?alt=media)

#### process

> \[!NOTE]
>
> * [Processes](https://github.com/junegunn/fzf/wiki/examples#processes)
> * [ctrl-r](https://github.com/junegunn/fzf/blob/master/ADVANCED.md#updating-the-list-of-processes-by-pressing-ctrl-r)

```bash
$ (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

  ```bash
  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](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-6835afff71f31c069287002a170393fc0f8afa72%2Ffzf-ps.png?alt=media)

  ![kill ps fzf](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-1a8d0398b0b53d2d22d44571148cdf5a10e68154%2Ffzf-kill-process.gif?alt=media)

#### kubectl

* `kns`

  ```bash
  # kns - kubectl set default namesapce
  # @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 'namepsace-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`

  ```bash
  # 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 'namepsace-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](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-9a51798293c4c437af4af4fd57f75522373c8a27%2Ffzf-kcani.png?alt=media)
* [Log tailing : pods](https://github.com/junegunn/fzf/blob/master/ADVANCED.md#log-tailing)

  ```bash
  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](https://github.com/junegunn/fzf/wiki/examples#homebrew)

* `bip`

  ```bash
  # 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`

  ```bash
  # 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`](https://github.com/junegunn/fzf#key-bindings-for-command-line)

```bash
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__`

```bash
$ 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](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-d855324b31112e4735a9177bb242423561d15c42%2Ffzf-ctrl-r.gif?alt=media)

#### [`ctrl-t`](https://github.com/junegunn/fzf#key-bindings-for-command-line)

> \[!NOTE|label:references:]
>
> * to disable/reset osx default <kbd>⌃</kbd>+<kbd>↑</kbd> and <kbd>⌃</kbd>+<kbd>↓</kbd>
>   * **System Settings** ⇢ **Keyboard** ⇢ **Keyboard Shutcuts...** ⇢ **Mission Control**![keyboards ⇢ shortcuts](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-57d2f27991e2485af6380333f3cfa6a9f9378942%2Fosx-settings-keyboards-mission-control.png?alt=media)
>   * **System Settings** ⇢ **Desktop & Dock** ⇢ **Shortcuts...**![desktop & dock ⇢ Shortcuts](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-4727335869b35b45a02929e37ae36990c10a6ffc%2Fosx-settings-desktop_dock-shortcuts.png?alt=media)

```bash
# 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](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-8259c2d5f559fc536ea92737abe6ce4308046d14%2Ffzf-ctrl-t.gif?alt=media)

* `__fzf_select__`

  ```bash
  $ 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()`](https://github.com/junegunn/fzf/wiki/Examples#changing-directory)

  ```bash
  # 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](https://github.com/junegunn/fzf/blob/master/ADVANCED.md#color-themes)

```bash
# 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](https://github.com/junegunn/fzf/blob/master/ADVANCED.md#generating-fzf-color-theme-from-vim-color-schemes)

  ```vim
  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

* move cursor to position

  > \[!TIP]
  >
  > * [12af069 Add pos(...) action to move the cursor to the numeric position](https://github.com/junegunn/fzf/commit/12af069dcad672b1563388c61ec33ba8a86c013e)
  > * [#395 Feature: Set selected entries](https://github.com/junegunn/fzf/issues/395)

  ```bash
  $ seq 100 | fzf --sync --bind 'start:pos(N)'
  ```

  ![fzf start pos](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-eadda46dd9c5138f42d4a754287524ea23fb15c0%2Ffzf-start-pos-1.png?alt=media)

  ![fzf start pos](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-7d11e3e2460abe31335e81813d9183c465711aac%2Ffzf-start-pos-2.png?alt=media)
* select by column

  > \[!NOTE]
  >
  > * [#3514 : Manual output on enter, no linebreak.](https://github.com/junegunn/fzf/discussions/3514#discussioncomment-7667338)

  ```bash
  $ 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]
  >
  > * [#102: Feature Request: Option to hide some fields](https://github.com/junegunn/fzf/issues/102)

  ```bash
  $ echo {a..z} | fzf --with-nth='1..3'
  ```

  ![fzf --with-nth](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-c84237a0838fbebd51e54f1fc9a3862ffe6aa848%2Ffzf-with-nth.png?alt=media)

  ```bash
  # 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](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-5cec285e2564fd903a05a5a06bb5f49b8db07e50%2Ffzf-with-nth-git.gif?alt=media)

  ```bash
  $ echo -e 'first line\tfirst preview\nsecond line\tsecond preview' |
    fzf --delimiter='\t' --with-nth=1 --preview='echo {2}'
  ```

  ![fzf --with-nth for preview](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-fc19110cfa7fc826daf3662b0ba3b095a9353942%2Ffzf-with-nth-preview.png?alt=media)
* `--track`

  ```bash
  $ git log --oneline --graph --color=always |
    nl |
    fzf --ansi --track --no-sort --layout=reverse-list
  ```

  ![fzf --track for git](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-ea10bdbe1a65b8205360addf6862222762e343a4%2Ffzf---track.gif?alt=media)
* select-all

  ```bash
  $ seq 3 | fzf --multi --sync --bind start:last+select-all
  ```

  ![fzf select-all](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-8ba124fb556fe11c258e7b11edd7175886d70de7%2Ffzf-select-all.png?alt=media)
* select-n

  > \[!TIP]
  >
  > * [#3548 - \[new feature\] ask for select-n feature](https://github.com/junegunn/fzf/issues/3548#issuecomment-1868433219)

  ```bash
  # 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](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-36ee8e78a1a173a6382f92e35926a044bf454928%2Ffzf-bind-select.png?alt=media)

  ![select](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-54ad179bcd8ecbb750f6cffff85819d0a84c374b%2Ffzf-bind-select-2.png?alt=media)
* for git

  > \[!NOTE]
  >
  > * [fshow](https://github.com/junegunn/fzf/issues/1323#issuecomment-780326885)

  ```bash
  # 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](https://github.com/junegunn/fzf/issues/1323#issuecomment-781244399)

    ```bash
    $ 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](https://seb.jambor.dev/posts/improving-shell-workflows-with-fzf/)

    > \[!NOTE]
    >
    > * [github cli: `gh`](https://cli.github.com/)

    ```bash
    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](https://seb.jambor.dev/posts/improving-shell-workflows-with-fzf/)

  ```bash
  function create-branch() {
    # The function expectes 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`](https://github.com/junegunn/fzf/releases/tag/v0.54.0)

  ```bash
  $ fzf --listen --sync --bind 'focus:transform-header:curl -s localhost:$FZF_PORT?limit=0 | jq .' --height 100%
  ```
* \[`--style`]

  > \[!NOTE|label:references:]
  >
  > * [#4160 Add style presets](https://github.com/junegunn/fzf/issues/4160)

  ![fzf style](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-1fe6ad868ffbca1268c68b16e46332b6a70da966%2Ffzf-style-full-1.png?alt=media)

### fzf with git

> \[!NOTE|label:references:]
>
> * [Make Git better with FZF](https://fortes.com/2022/make-git-better-with-fzf/)
> * [A Practical Guide to fzf: Building a Git Explorer](https://thevaluable.dev/fzf-git-integration/)
> * [jesseduffield/lazygit](https://github.com/jesseduffield/lazygit)
> * [Examples - Git](https://github.com/junegunn/fzf/wiki/examples#git)

## [`fd`](https://github.com/sharkdp/fd)

> \[!NOTE|label:references:]
>
> * [Find Files With the fd Command](https://www.linode.com/docs/guides/finding-files-with-fd-command/)
> * [How to Use the fd Command on Linux](https://www.howtogeek.com/682244/how-to-use-the-fd-command-on-linux/)
> * [How to Find Files with fd Command in Linux](https://www.atlantic.net/vps-hosting/how-to-find-files-with-fd-command-in-linux/)
> * [Fd – The Best Alternative to ‘Find’ Command for Quick File Searching](https://www.tecmint.com/fd-alternative-to-find-command/)
> * [File list of package fd-find in noble of architecture amd64](https://packages.ubuntu.com/noble/amd64/fd-find/filelist)
> * [Download Page for fd-find\_9.0.0-1\_amd64.deb on AMD64 machines](https://packages.ubuntu.com/noble/amd64/fd-find/download)

* install

```bash
# osx
$ brew install fd
$ type -P fd >/dev/null && eval "$(fd --gen-completions bash)"
# -- or --
$ fd --gen-completions bash | sudo tee $(brew --prefix)/etc/bash_completion.d/fd
# -- or --
$ ln -sf $(brew --prefix fd)/share/bash-completion/completions/fd $(brew --prefix)/etc/bash_completion.d/fd
# or - v9.0.0
$ ln -sf $(brew --prefix fd)/share/bash-completion/completions/fd "$(brew --prefix)"/etc/bash_completion.d/fd

# debine
$ sudo apt install fd-find                  # ubuntu 22.04 : fd 8.3.1
$ curl -fsSL -O http://ftp.osuosl.org/pub/ubuntu/pool/universe/r/rust-fd-find/fd-find_9.0.0-1_amd64.deb
$ sudo dpkg -i fd-find_9.0.0-1_amd64.deb    # ubuntu any: fd 9.0.0
$ ln -s $(which fdfind) ~/.local/bin/fd
$ export PATH=~/.local:$PATH

# centos
$ sudo dnf install fd-find
```

* from source

  > \[!NOTE]
  >
  > * install rust via
  >
  >   ```bash
  >   $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  >   $ source "$HOME/.cargo/env"
  >   $ cargo --version
  >   cargo 1.74.1 (ecb9851af 2023-10-18)
  >   ```
  > * [generate auto-completion](https://github.com/sharkdp/fd/blob/master/Makefile)

  |    SHELL   | COMMAND                           |
  | :--------: | --------------------------------- |
  |    bash    | `fd --gen-completions bash`       |
  |    fish    | `fd --gen-completions fish`       |
  |     zsh    | `fd --gen-completions zsh`        |
  |   elvsih   | `fd --gen-completions elvish`     |
  | powershell | `fd --gen-completions powershell` |

  ```bash
  $ git clone https://github.com/sharkdp/fd && cd fd

  # osx
  $ brew install rust
  $ cargo install amethyst_tools
  # wsl/ubuntu
  $ sudo apt install cargo

  $ cargo build                     # build
  $ cargo test                      # run unit tests and integration tests
  $ cargo install --debug --path .  # install in osx
  $ cargo install --path .          # install in ubuntu/wsl
  $ ln -sf /home/marslo/.cargo/bin/fd /home/marslo/.local/bin/fd

  # completion ( >= 9.0.0 )
  # wsl/ubuntu/centos
  $ fd --gen-completions bash | sudo tee /usr/share/bash-completion/completions/fd
  # or centos
  $ fd --gen-completions bash | sudo tee /etc/bash_completion.d/fd
  # osx
  $ fd --gen-completions bash | sudo tee $(brew --prefix)/etc/bash_completion.d/fd
  ```
* verify

  ```bash
  $ fd --version
  fd 9.0.0
  ```
* usage

  ```bash
  $ fd --hidden ^.env$
  .env

  $ fd --type f --strip-cwd-prefix --hidden --follow --exclude .git --exclude node_modules ifunc
  bin/ifunc.sh
  ```

### advanced usage

* crontab for delete '*.DS\_*'

  ```bash
  $ "$(type -P fd)" -IH --glob '*\.DS_*' $HOME | xargs -r -i rm '{}'
  # or
  $ "$(type -P fd)" -Iu --glob '*\.DS_*' $HOME | xargs -r -i rm '{}'
  # or
  $ "$(type -P fd)" --type f --hidden --follow --unrestricted --color=never --exclude .Trash --glob '*\.DS_*' $HOME  | xargs -r -i rm '{}'
  ```
* [`ff`](https://github.com/marslo/mylinux/raw/master/confs/home/.marslo/bin/ff)

  ![fd-ffs](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-a1690774f43cff82aef4b94ddec5c084c5bdecef%2Ffd-ff.png?alt=media)
* `ffs`

  ```bash
  # [f]ind [f]ile and [s]ort
  function ffs() {
    local opt=''
    while [[ $# -gt 0 ]]; do
      case "$1" in
            -g ) opt+="$1 "   ; shift   ;;
           -fg ) opt+="$1 "   ; shift   ;;
            -f ) opt+="$1 "   ; shift   ;;
           --* ) opt+="$1 $2 "; shift 2 ;;
            -* ) opt+="$1 "   ; shift   ;;
             * ) break                  ;;
      esac
    done

    local path=${1:-~/.marslo}
    local num=${2:-10}
    num=${num//-/}
    local depth=${3:-}
    depth=${depth//-/}
    local option='--type f'

    if [[ "${opt}" =~ '-g ' ]]; then
      # git show --name-only --pretty="format:" -"${num}" | awk 'NF' | sort -u
      # references: https://stackoverflow.com/a/54677384/2940319
      git log --date=iso-local --first-parent --pretty=%cd --name-status --relative |
          awk 'NF==1{date=$1}NF>1 && !seen[$2]++{print date,$0}' FS=$'\t' |
          head -"${num}"
    elif [[ "${opt}" =~ '-fg ' ]]; then
      # references: https://stackoverflow.com/a/63864280/2940319
      git ls-tree -r --name-only HEAD -z |
          TZ=PDT xargs -0 -I_ git --no-pager log -1 --date=iso-local --format="%ad | _" -- _ |
          sort -r |
          head -"${num}"
    elif [[ "${opt}" =~ '-f ' ]]; then
      option=${option: 1}
      [[ -n "${depth}" ]] && option="-maxdepth ${depth} ${option}"
      # shellcheck disable=SC2086
      find "${path}" ${option} \
                     -not -path '*/\.git/*' \
                     -not -path '*/node_modules/*' \
                     -not -path '*/go/pkg/*' \
                     -not -path '*/git/git*/*' \
                     -not -path '*/.marslo/utils/*' \
                     -not -path '*/.marslo/.completion/*' \
                     -printf "%10T+ | %p\n" |
      sort -r |
      head -"${num}"
    else
      if [[ "${opt}}" =~ .*-t.* ]] || [[ "${opt}" =~ .*--type.* ]]; then
        option="${option//--type\ f/}"
      fi
      option="${opt} ${option} --hidden --follow --unrestricted --ignore-file ~/.fdignore"
      [[ -n "${depth}"    ]] && option="--max-depth ${depth} ${option}"
      [[ '.' != "${path}" ]] && option="${path} ${option}"
      # shellcheck disable=SC2086,SC2027
      eval """ fd . "${option}" --exec stat --printf='%y | %n\n' | sort -r | head -"${num}" """
    fi
  }
  ```

  ![fd-ffs](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-328e74acfa18ca50fd44a69ebce77a4cc68bc7cb%2Ffd-ffs.png?alt=media)
* search for multiple pattern

  > \[!NOTE]
  >
  > * [#1139 add support for matching multiple patterns](https://github.com/sharkdp/fd/pull/1139#issuecomment-1297725086)
  > * [#315 Finding multiple patterns](https://github.com/sharkdp/fd/issues/315#issuecomment-841869872)

  ```bash
  $ fd --unrestricted '^*\.(png|gif|jpg)$'
  $ fd --unrestricted --extension png --extension jpg --extension gif
  ```

## [`rg`](https://github.com/BurntSushi/ripgrep) the faster [`mg`](https://github.com/marslo/mylinux/blob/master/confs/home/.marslo/bin/im.sh#L50)

> \[!NOTE]
>
> * [#193: \[Question\] how to search by filenames only?](https://github.com/BurntSushi/ripgrep/issues/193#issuecomment-775059326)
> * [How can I recursively find all files in current and subfolders based on wildcard matching?](https://stackoverflow.com/a/50840902/2940319)
> * [chinanf-boy/ripgrep-zh](https://github.com/chinanf-boy/ripgrep-zh/tree/master)
>   * [ripgrep-zh/GUIDE.zh.md](https://github.com/chinanf-boy/ripgrep-zh/blob/master/GUIDE.zh.md)
> * [How to get a git's branch with fuzzy finder?](https://stackoverflow.com/a/37007733/2940319)
> * [Integralist/RipGrep inline file replacements.sh](https://gist.github.com/Integralist/89ad7fe05f72941b87c6e3512c30d940)\
>   )

* install

  ```bash
  # with cargo
  $ cargo install ripgrep

  # osx
  $ brew install ripgrep

  # rhel/centos
  $ sudo yum install -y yum-utils
  $ sudo yum-config-manager --add-repo=https://copr.fedorainfracloud.org/coprs/carlwgeorge/ripgrep/repo/epel-7/carlwgeorge-ripgrep-epel-7.repo
  $ sudo yum install ripgrep
  # or via epel: https://marslo.github.io/ibook/linux/basic.html#tools-installation
  $ sudo yum install -y yum-utils epel-release
  $ sudo yum install ripgrep

  # ubuntu
  $ curl -LO https://github.com/BurntSushi/ripgrep/releases/download/14.0.3/ripgrep_14.0.3-1_amd64.deb
  $ sudo dpkg -i ripgrep_14.0.3-1_amd64.deb
  # or
  $ sudo apt install -y ripgrep

  # from source
  $ git clone https://github.com/BurntSushi/ripgrep && cd ripgrep
  $ cargo build --release
  $ ./target/release/rg --version
  0.1.3

  # completion
  # wsl/ubuntu/centos
  $ rg --generate complete-bash | sudo tee /usr/share/bash-completion/completions/rg
  # or centos
  $ rg --generate complete-bash | sudo tee /etc/bash_completion.d/rg
  # osx
  $ rg --generate complete-bash | sudo tee /usr/local/etc/bash_completion.d/rg
  ```

### usage

* crontab for delete '*.DS\_*'

  ```bash
  /usr/local/bin/rg --hidden --smart-case --files "$HOME" -g  '*\.DS_*' | xargs -r -i rm '{}'
  ```
* [search in dotfiles with ripgrep](https://til.hashrocket.com/posts/ezeddwpiso-search-in-dotfiles-with-ripgrep)

  > \[!NOTE|label:references:]
  >
  > * [#771 : .gitignore files might be searched without using '--hidden'](https://github.com/BurntSushi/ripgrep/issues/771)
  > * [#919 : RipGrep does not show hidden files even with the --hidden flag](https://github.com/BurntSushi/ripgrep/issues/919)

  ```bash
  $ rg --hidden 'alias cat'

  # or https://github.com/BurntSushi/ripgrep/issues/623#issuecomment-659909044
  alias rg="rg --hidden --glob '!.git'"

  # or `.ignore` or `.rgignore`
  $ cat ~/.rgignore
  .git/
  .tox/
  .github/
  ```
* info

  ```bash
  $ tree -a .
  .
  ├── .no-hidden
  └── no-hidden

  1 directory, 2 files

  $ rg --files --debug
  DEBUG|globset|crates/globset/src/lib.rs:416: glob converted to regex: Glob { glob: "**/.DS_Store?", re: "(?-u)^(?:/?|.*/)\\.DS_Store[^/]$", opts: GlobOptions { case_insensitive: false, literal_separator: true, backslash_escape: true }, tokens: Tokens([RecursivePrefix, Literal('.'), Literal('D'), Literal('S'), Literal('_'), Literal('S'), Literal('t'), Literal('o'), Literal('r'), Literal('e'), Any]) }
  DEBUG|globset|crates/globset/src/lib.rs:416: glob converted to regex: Glob { glob: "**/._*", re: "(?-u)^(?:/?|.*/)\\._[^/]*$", opts: GlobOptions { case_insensitive: false, literal_separator: true, backslash_escape: true }, tokens: Tokens([RecursivePrefix, Literal('.'), Literal('_'), ZeroOrMore]) }
  DEBUG|globset|crates/globset/src/lib.rs:421: built glob set; 0 literals, 7 basenames, 0 extensions, 0 prefixes, 0 suffixes, 0 required extensions, 2 regexes
  DEBUG|ignore::walk|crates/ignore/src/walk.rs:1741: ignoring ./.no-hidden: Ignore(IgnoreMatch(Hidden))
  no-hidden

  $ rg --files --debug --hidden
  DEBUG|globset|crates/globset/src/lib.rs:416: glob converted to regex: Glob { glob: "**/.DS_Store?", re: "(?-u)^(?:/?|.*/)\\.DS_Store[^/]$", opts: GlobOptions { case_insensitive: false, literal_separator: true, backslash_escape: true }, tokens: Tokens([RecursivePrefix, Literal('.'), Literal('D'), Literal('S'), Literal('_'), Literal('S'), Literal('t'), Literal('o'), Literal('r'), Literal('e'), Any]) }
  DEBUG|globset|crates/globset/src/lib.rs:416: glob converted to regex: Glob { glob: "**/._*", re: "(?-u)^(?:/?|.*/)\\._[^/]*$", opts: GlobOptions { case_insensitive: false, literal_separator: true, backslash_escape: true }, tokens: Tokens([RecursivePrefix, Literal('.'), Literal('_'), ZeroOrMore]) }
  DEBUG|globset|crates/globset/src/lib.rs:421: built glob set; 0 literals, 7 basenames, 0 extensions, 0 prefixes, 0 suffixes, 0 required extensions, 2 regexes
  no-hidden
  .no-hidden
  ```

  ![ag rg](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-1a6684d946b0ec303932d08e3f228a4cd7b6b9e6%2Fag-rg.png?alt=media)

### tips

* show file name only

  ```bash
  $ rg --hidden 'alias ping' --no-heading --files-with-matches
  alias.d/utils
  ```
* in vimgrep format

  ```bash
  $ rg --hidden 'alias ping' --no-heading
  alias.d/utils:13:  alias ping='/sbin/ping --apple-time -v'
  # or
  $ rg 'alias ping' --no-heading --line-number --with-filename
  alias.d/utils:13:  alias ping='/sbin/ping --apple-time -v'

  $ rg --hidden 'alias ping' --vimgrep
  alias.d/utils:13:3:  alias ping='/sbin/ping --apple-time -v'
  ```

### using inside in vim

> \[!NOTE|label:references:]
>
> * [Extending Vim with ripgrep](https://phelipetls.github.io/posts/extending-vim-with-ripgrep/)
> * [#425 - How to use inside vim?](https://github.com/BurntSushi/ripgrep/issues/425#issuecomment-381446152)
> * [jremmen/vim-ripgrep](https://github.com/jremmen/vim-ripgrep)

```vim
if executable("rg")
  set grepprg=rg\ --vimgrep\ --smart-case\ --hidden
  set grepformat=%f:%l:%c:%m
endif

" -- more --
" handling search and replace boilerplate using ripgrep
if executable('rg') | set grepformat+=%f:%l:%c:%m grepprg=rg\ --vimgrep\ --no-heading\ --smart-case | endif
" use feedkeys because we don't want to press enter at the end of this command
command! -nargs=1 FindReplaceAll :silent grep <args> | copen | call feedkeys(":cdo %s/" . <q-args> . "/") | redraw!
" use feedkeys because otherwise the screen isn't redrawn
nnoremap <silent> <C-r> :call feedkeys(':FindReplaceAll ')<CR>
```

## [`ag`](https://github.com/ggreer/the_silver_searcher) the faster [`mg`](https://github.com/marslo/mylinux/blob/master/confs/home/.marslo/bin/im.sh#L50)

* install

  ```bash
  # osx
  $ brew install the_silver_searcher

  # ubuntu >= 13.10
  $ apt-get install silversearcher-ag
  ```

## [`fzy`](https://github.com/jhawthorn/fzy)

* install

  ```bash
  # osx
  $ brew install fzy

  # debine
  $ sudo apt install fzy

  # source code
  $ git clone git@github.com:jhawthorn/fzy.git && cd fzy
  $ make
  $ sudo make install
  ```
* verify

  ```bash
  $ fzy --version
  fzy 1.0 © 2014-2018 John Hawthorn
  ```

## [`bat`](https://github.com/sharkdp/bat)

> \[!NOTE|label:references:]
>
> * [bat-extra](https://github.com/eth-p/bat-extras/blob/master/README.md#installation)
> * [Install and Use the Linux bat Command](https://www.linode.com/docs/guides/how-to-install-and-use-the-bat-command-on-linux/)
> * [Using vim as a man-page viewer under Unix](https://vim.fandom.com/wiki/Using_vim_as_a_man-page_viewer_under_Unix)
>   * `unset PAGER`
> * [CentOS 7 - Installing the latest bat command release version from GitHub](https://github.com/sharkdp/bat/issues/325#issuecomment-697947031)

* install

  ```bash
  # osx
  $ brew install bat
  ## extra
  $ brew install bat-extras

  # ubuntu
  $ sudo apt intall bat -y
  $ ln -s /usr/bin/batcat ~/.marslo/bin/bat

  # centos
  $ dnf install bat
  ## extra
  $ sudo dnf install dnf-plugins-core
  $ sudo dnf copr enable awood/bat-extras
  $ sudo dnf install bat-extras

  # ubuntu latest version
  $ sudo apt instal -y https://github.com/sharkdp/bat/releases/download/v0.23.0/bat-musl_0.23.0_amd64.deb
  $ ln -s /usr/bin/batcat ~/.marslo/bin/bat

  # from release package
  $ curl -fsSL https://github.com/sharkdp/bat/releases/download/v0.23.0/bat-v0.23.0-x86_64-unknown-linux-musl.tar.gz |
         tar xzf - -C ${iRCHOME}/utils/bat-v0.23.0
  $ ln -sf ${iRCHOME}/utils/bat-v0.23.0/bat ${iRCHOME}/bin/bat
  # or
  $ V=$(curl --silent "https://api.github.com/repos/sharkdp/bat/releases/latest" | grep -Eo '"tag_name": "v(.*)"' | sed -E 's/.*"([^"]+)".*/\1/') &&
      curl -sOL "https://github.com/sharkdp/bat/releases/download/$V/bat-$V-x86_64-unknown-linux-musl.tar.gz" &&
      tar xzvf "bat-$V-x86_64-unknown-linux-musl.tar.gz" -C . &&
      sudo sh -c "cp ./bat-$V-x86_64-unknown-linux-musl/bat /usr/local/bin/bat" &&
      rm bat-$V-x86_64-unknown-linux-musl.tar.gz &&
      unset V

  # from source
  $ git clone git@github.com:sharkdp/bat.git && cd bat
  $ git submodule update -f --init --recursive
  # or
  $ git clone --recurse-submodules git@github.com:sharkdp/bat.git && cd bat

  $ cargo install --locked bat

  # build a bat binary with modified syntaxes and themes
  $ bash assets/create.sh
  $ cargo install --path . --locked --force
  ```
* completion

  ```bash
  # -- recommended --
  $ type -P bat >/dev/null && eval "$(bat --completion bash)"

  # -- others --
  $ sed 's/{{PROJECT_EXECUTABLE}}/bat/'                                     "${iRCHOME}/utils/bat/assets/completions/bat.bash.in" | sudo tee /etc/bash_completion.d/bat
  # or
  $ sed 's/{{PROJECT_EXECUTABLE}}/-o nosort -o bashdefault -o default bat/' "${iRCHOME}/utils/bat/assets/completions/bat.bash.in" | sudo tee /etc/bash_completion.d/bat

  # or
  $ sed 's/{{PROJECT_EXECUTABLE}}/bat/'                                     -i "${iRCHOME}/utils/bat/assets/completions/bat.bash.in"
  $ sed 's/{{PROJECT_EXECUTABLE}}/-o nosort -o bashdefault -o default bat/' -i "${iRCHOME}/utils/bat/assets/completions/bat.bash.in"
  $ sudo ln -sf "${iRCHOME}/utils/bat/assets/completions/bat.bash.in" /usr/share/bash-completion/completions/bat

  # or without modify `bat.bash.in` and add complete into bashrc
  $ sudo ln -sf "${iRCHOME}/utils/bat/assets/completions/bat.bash.in" /usr/share/bash-completion/completions/bat
  $ echo 'type -t _bat >/dev/null 2>&1 && complete -F _bat -o nosort -o bashdefault -o default bat' >> ~/.bashrc
  ```
* verify

  ```bash
  $ bat --version
  bat 0.24.0 (28990bc-modified)
  ```

![bat cat](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-15eb71824642fd655d6921e6ab018d438453db52%2Fbat-cat.png?alt=media)

### usage

* `help()`

  ```bash
  # in your .bashrc/.zshrc/*rc
  alias bathelp='bat --plain --language=help'
  help() { "$@" --help 2>&1 | bathelp }

  # calling in bash:
  # $ help bat
  ```

  ![bat help](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-6c4e8c775cca0c7c1c19b1392537f3d362513263%2Fbat-help.png?alt=media)

  * for zsh

    ```bash
    $ alias -g -- -h='-h 2>&1 | bat --language=help --style=plain'
    $ alias -g -- --help='--help 2>&1 | bat --language=help --style=plain'
    ```
* [cygwin path issue](https://github.com/sharkdp/bat?tab=readme-ov-file#cygwin)

  ```bash
  bat() {
    local index
    local args=("$@")
    for index in $(seq 0 ${#args[@]}) ; do
      case "${args[index]}" in
        -* ) continue;;
         * ) [ -e "${args[index]}" ] && args[index]="$(cygpath --windows "${args[index]}") ";;
      esac
    done
    command bat "${args[@]}"
  }
  ```

### tips

* manpages themes

  ```bash
  $ bat --list-themes |
    fzf --preview="man git-checkout | sed -r 's/\x1B\[(([0-9]+)(;[0-9]+)*)?[mGKHfJ]//g' | bat --theme={} --color=always --plain --language=help" \
        --height 100% \
        --preview-window=up,85%,nofollow \
        --preview-label-pos='bottom'
  ```
* script themes

  ```bash
  $ bat --list-themes |
    fzf --preview="bat --theme={} --color=always /path/to/script" \
        --height 100% \
        --preview-window=up,85%,nofollow \
        --preview-label-pos='bottom'
  ```

### config

* [config-file](https://github.com/sharkdp/bat#format)

  ```bash
  $ bat --config-file
  /Users/marslo/.config/bat/config

  # if need modify
  $ export BAT_CONFIG_PATH="$(bat --config-file)"

  # generate standard config-file
  $ bat --generate-config-file
  Success! Config file written to /Users/marslo/.config/bat/config
  ```
* sample content

  ```bash
  $ bat $(bat --config-file) | sed -r '/^(#.*)$/d;/^\s*$/d'  | bat --language ini
         STDIN
     1   --theme="gruvbox-dark"
     2   --style="numbers,changes,header"
     3   --italic-text=always
     4   --pager="less --RAW-CONTROL-CHARS --quit-if-one-screen --mouse"
     5   --map-syntax "*.ino:C++"
     6   --map-syntax ".ignore:Git Ignore"
     7   --map-syntax='*.conf:INI'
     8   --map-syntax='/etc/apache2/**/*.conf:Apache Conf'
  ```

### theme

```bash
# list themes
$ bat --list-themes

# modify them
$ export BAT_THEME='gruvbox-dark'
# or
$ echo '--theme="gruvbox-dark"' >> $(bat --config-file)
```

* [new theme](https://github.com/sharkdp/bat/blob/master/README.md#adding-new-themes)

  ```bash
  $ mkdir -p "$(bat --config-dir)/themes"
  $ cd "$(bat --config-dir)/themes"

  # download a theme in '.tmtheme' format, for example:
  $ git clone https://github.com/greggb/sublime-snazzy

  # Update the binary cache
  $ bat cache --build
  ```

## `tldr`

> \[!NOTE|label:references:]
>
> * [tldr.sh](https://tldr.sh/) | [tlrc](https://tldr.sh/tlrc) | [python version](https://pypi.org/project/tldr/)
> * [client](https://github.com/tldr-pages/tldr/wiki/Clients)

### install

```bash
# node version
$ npm install -g tldr
# -- usage --
$ $(npm config get prefix)/bin/tldr --theme ocean <cmd>

# rust version
$ brew install --HEAD tlrc

# c version
$ brew install --HEAD tldr

# python version
$ python3 -m pip intall tldr
```

### config

* rust version

  > \[!TIP|label:references:]
  >
  > * config file :
  >   * linux and bsd: `$XDG_CONFIG_HOME/tlrc/config.toml` or `~/.config/tlrc/config.toml` if `$XDG_CONFIG_HOME` is unset
  >   * macos: `~/Library/Application Support/tlrc/config.toml`
  >   * windows: `%ROAMINGAPPDATA%\tlrc\config.toml`
  > * [iMarslo: .tlrc.toml](https://github.com/marslo/dotfiles/blob/main/.marslo/.tlrc.toml)`export TLRC_CONFIG="$HOME/.marslo/.tlrc.toml"`

  ```bash
  # rust version
  # -- default configure --
  $ tldr --gen-config > $(tldr --config-path)

  # -- user defined configure --
  $ export TLRC_CONFIG="$HOME/.marslo/.tlrc.toml"
  # or
  $ tldr --config "$HOME/.marslo/.tlrc.toml" <cmd>
  ```
* python version

  ```bash
  # tldr-pypi : https://pypi.org/project/tldr/
  export TLDR_COLOR_NAME='cyan'
  export TLDR_COLOR_DESCRIPTION='white'
  export TLDR_COLOR_EXAMPLE='green'
  export TLDR_COLOR_COMMAND='red'
  export TLDR_COLOR_PARAMETER='white'
  export TLDR_LANGUAGE='en'
  export TLDR_CACHE_ENABLED=1
  export TLDR_CACHE_MAX_AGE=720
  export TLDR_PAGES_SOURCE_LOCATION='https://raw.githubusercontent.com/tldr-pages/tldr/main/pages'
  export TLDR_DOWNLOAD_CACHE_LOCATION='https://tldr-pages.github.io/assets/tldr.zip'
  ```

## `cht.sh`

> \[!NOTE]
>
> * [chubin/cheat.sh](https://github.com/chubin/cheat.sh) | [cheat.sh](https://cheat.sh/) | - [cheat.sh/fzf](https://cheat.sh/fzf)
> * [gotbletu/fzf-cheat.sh](https://gist.github.com/gotbletu/538ffd9565bc38b5426dd9071ff1eecd)
> * [youtube: I made the greatest tool ever! | tmux & cht.sh & fzf](https://www.youtube.com/watch?v=hJzqEAf2U4I)
>   * [ThePrimeagen/.dotfiles/tmux-cht.sh](https://github.com/ThePrimeagen/.dotfiles/blob/master/bin/.local/scripts/tmux-cht.sh)
> * [kenos1/tmux-cht-sh/bin/tmux-cht-sh.sh](https://github.com/kenos1/tmux-cht-sh/blob/main/bin/tmux-cht-sh.sh)
> * [gohoyer/Alfred-Cheat.sh](https://github.com/gohoyer/Alfred-Cheat.sh)
> * [From FZF file preview to a browser for cht.sh to discovering the ideal solution](https://dev.to/melopilosyan/from-fzf-file-preview-to-a-browser-for-chtsh-to-discovering-the-ideal-solution-3ann)
> * [melopilosyan/confNest - cs](https://github.com/melopilosyan/confNest/blob/main/bin/cs)

```bash
# install
$ curl -fsSL https://cht.sh/:cht.sh --create-dirs -o ~/.local/bin/cht.sh
$ chmod +x ~/.local/bin/cht.sh

# completion
$ curl -fsSL https://cheat.sh/:bash_completion --create-dirs -o ~/.marslo/.completion/cht.sh
$ source ~/.marslo/.completion/cht.sh

# added in .bashrc
$ [[ -f "${iRCHOME}"/.completion/cht.sh ]] && source "${iRCHOME}"/.completion/cht.sh
```

### links

* [:intro](https://cht.sh/:intro)
* [\~snapshot](https://cht.sh/~snapshot)
* [:vim](https://cht.sh/:vim)
* [:styles](https://cht.sh/:styles)
* [:styles-demo](https://cht.sh/:styles-demo)
* :list
  * i.e.: [python/:list](https://cht.sh/python/:list)
* :learn
  * i.e.: [python/:learn](https://cht.sh/python/:learn)

### .cht.sh.conf

> \[!NOTE|label:references:]
>
> * path: `~/.cht.sh/`
> * file : `~/.cht.sh/cht.sh.conf`
> * [cht.sh](https://cht.sh/:cht.sh)\
>   configuration is stored in `~/.cht.sh/` (can be overridden with `CHTSH` env var.)

#### CHTSH environment

| ENVIRONMENT VAIRABLE        | VALUE                                         |
| --------------------------- | --------------------------------------------- |
| `CHTSH_HOME`                | `~/.cht.sh/`                                  |
| `CHTSH_CONF`                | `$CHTSH_HOME/cht.sh.conf`                     |
| `CHTSH_URL`                 | `https://cht.sh`                              |
| `CHTSH_MODE`                | `$(cat "$CHTSH_HOME/mode 2>/dev/null")`       |
| `CHTSH_CURL_OPTIONS`        | -                                             |
| `CHEATSH_INSTALLATION`      | `$(cat "$CHTSH_HOME/standalone" 2>/dev/null)` |
| `CHEATSH_TEST_STANDALONE`   | `YES/NO`                                      |
| `CHEATSH_TEST_SKIP_ONLINE`  | `YES/NO`                                      |
| `CHEATSH_TEST_SHOW_DETAILS` | `YES/NO`                                      |

#### theme

* list themes

  ```bash
  $ cht.sh :styles

  # or
  $ curl cht.sh/:styles
  ```
* show themes

  ```bash
  $ cht.sh :styles-demo

  # or
  $ cht.sh :styles |
    while read -r _s; do
      echo -e "\n---";
      echo -e "${_s}";
      echo -e "---";
      curl "cheat.sh/bash/advanced?style=${_s}";
    done
  ```
* configure theme

  ```bash
  $ cat ~/.cht.sh/cht.sh.conf
  CHTSH_QUERY_OPTIONS="style=arduino"
  ```
* themes
  * algol\_nu
  * arduino
  * native
  * solarized-dark
  * stata-dark

#### mode

> \[!NOTE|label:references:]
>
> * path : `~/.cht.sh/mode`

```bash
$ cht.sh --mode lite      # use https://cheat.sh/ only
$ cht.sh --mode auto      # use local installation
```

### `--shell`

> \[!NOTE|label:references:]

```bash
$ brew install --HEAD rlwrap
$ cht.sh --shell python
```

## `cheat`

> \[!NOTE|label:references:]
>
> * [cheat/chet](https://github.com/cheat/cheat) | [cheat/cheatsheets](https://github.com/cheat/cheatsheets)
> * [Related Projects](https://github.com/cheat/cheat/wiki/Related-Projects)
> * [docopt](http://docopt.org/)

```bash
$ brew install cheat
```

### configure

```bash
$ mkdir -p ~/.config/cheat && cheat --init > ~/.config/cheat/conf.yml

# -- config path --
$ cheat --conf
```

* reset cheatsheets repo

  ```bash
  $ cd ~/.config/cheat/cheatsheets
  $ rm -rf community
  $ git clone https://github.com/cheat/cheatsheets.git community
  ```

#### theme

* arduino
* github-dark
* gruvbox
* native
* onedark
* optional
  * doom-one
  * evergarden
  * lovelace
  * nord
  * solarized-dark256
  * vulcan

## [`ncdu` : NCurses Disk Usage](https://dev.yorhel.nl/ncdu)

> \[!TIP]
>
> * [code.blicky.net/yorhel/ncdu](https://code.blicky.net/yorhel/ncdu/)
> * [Ncdu 2: Less hungry and more Ziggy](https://dev.yorhel.nl/doc/ncdu2)

```bash
# deps install
$ sudo snap install zig --class --beta
$ sudo apt install libncurses-dev

$ make
$ sudo make install PREFIX=/usr/local

# verify
$ ncdu --version
ncdu 2.3
```

![ncdu](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-e6de89c18970fac93aff9a2c7c1d42567e0af3b2%2Fncdu.png?alt=media)

> \[!NOTE|label:Alternatives:]
>
> * CLI
>   * [`dust`: bootandy/dust](https://github.com/bootandy/dust)
>   * [`dutree`: nachoparker/dutree](https://github.com/nachoparker/dutree)
>   * [`dua`: Byron/dua-cli](https://github.com/Byron/dua-cli)
>   * [`pdu`: KSXGitHub/parallel-disk-usage](https://github.com/KSXGitHub/parallel-disk-usage)
> * TUI:
>   * [`ncdu`](https://dev.yorhel.nl/ncdu)
>   * [`ds`: scullionw/dirstat-rs](https://github.com/scullionw/dirstat-rs)
>   * [`gdu`: dundee/gdu](https://github.com/dundee/gdu)
>   * [`godu`: viktomas/godu](https://github.com/viktomas/godu)
>   * [`Vifm`](https://vifm.info/manual.shtml)

## theme and colors

### [`c`: bash-color](https://github.com/ppo/bash-colors)

> \[!TIP]
>
> * flags
>
>   ```css
>   ┌───────┬────────────────┬─────────────────┐   ┌───────┬─────────────────┬───────┐
>   │ Fg/Bg │ Color          │ Octal           │   │ Code  │ Style           │ Octal │
>   ├───────┼────────────────┼─────────────────┤   ├───────┼─────────────────┼───────┤
>   │  K/k  │ Black          │ \e[ + 3/4  + 0m │   │  s/S  │ Bold (strong)   │ \e[1m │
>   │  R/r  │ Red            │ \e[ + 3/4  + 1m │   │  d/D  │ Dim             │ \e[2m │
>   │  G/g  │ Green          │ \e[ + 3/4  + 2m │   │  i/I  │ Italic          │ \e[3m │
>   │  Y/y  │ Yellow         │ \e[ + 3/4  + 3m │   │  u/U  │ Underline       │ \e[4m │
>   │  B/b  │ Blue           │ \e[ + 3/4  + 4m │   │  f/F  │ Blink (flash)   │ \e[5m │
>   │  M/m  │ Magenta        │ \e[ + 3/4  + 5m │   │  n/N  │ Negative        │ \e[7m │
>   │  C/c  │ Cyan           │ \e[ + 3/4  + 6m │   │  h/H  │ Hidden          │ \e[8m │
>   │  W/w  │ White          │ \e[ + 3/4  + 7m │   │  t/T  │ Strikethrough   │ \e[9m │
>   ├───────┴────────────────┴─────────────────┤   ├───────┼─────────────────┼───────┤
>   │  High intensity        │ \e[ + 9/10 + *m │   │   0   │ Reset           │ \e[0m │
>   └────────────────────────┴─────────────────┘   └───────┴─────────────────┴───────┘
>                                                   Uppercase = Reset a style: \e[2*m
>   ```

![bash color](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-b68908d17261e9e22f7ac653b136bbc174b629e7%2Fbash-color.gif?alt=media)

### [`ansi`](https://github.com/fidian/ansi)

> \[!NOTE|label:references:]
>
> * [example](https://github.com/fidian/ansi/tree/master/examples)

* install

  ```bash
  $ curl -sL git.io/ansi -o "${iRCHOME}"/utils/ansi && chmod +x $_
  $ ln -sf $(realpath "${iRCHOME}"/utils/ansi) $(realpath "${iRCHOME}"/bin)/ansi
  ```

  ![ansi color tables](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-6e8421d708a1e3f02b147bc750d23ba423a2a7b3%2Fansi-color-codes.png?alt=media)

### [`diff-so-fancy`](https://github.com/so-fancy/diff-so-fancy)

> \[!NOTE|label:references:]
>
> * [Aos Dabbagh : diff-so-fancy](https://launchpad.net/~aos1/+archive/ubuntu/diff-so-fancy)

```bash
# ubuntu
$ sudo add-apt-repository ppa:aos1/diff-so-fancy
$ sudo apt update

$ sudo apt install diff-so-fancy

# verify
$ diff-so-fancy --version
Diff-so-fancy: https://github.com/so-fancy/diff-so-fancy
Version      : 1.4.2
```

## utility

### `elinks`

> \[!NOTE|label:references:]
>
> * [ELinks](https://en.wikipedia.org/wiki/ELinks)
> * MacOS:
>
>   ```bash
>   $ brew install felinks
>   $ which -a elinks
>   /usr/local/bin/elinks
>   ```
> * [\* iMarslo : open html in terminal](https://github.com/marslo/ibook/blob/marslo/docs/vim/tricky.html#open-html-in-terminal)
> * [ELinks - Full-Featured Text WWW Browser](http://elinks.or.cz/)
>   * [elinks.conf](http://elinks.or.cz/documentation/manpages/elinks.conf.5.html)
>   * [elinkskeys](http://elinks.or.cz/documentation/manpages/elinkskeys.5.html)

```bash
$ elinks https://google.com
```

![elinks google.com](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-561ed0442cb9e46e6a265231989d7da839869f7d%2Felinks.png?alt=media)

* configure

  > \[!NOTE|label:references:]
  >
  > * [Elinks: SSL Error](https://stackoverflow.com/a/40114376/2940319)

  ```bash
  $ cat ~/.elinks/elinks.conf
  set connection.ssl.cert_verify = 0
  ```

### [`duf`](https://unix.stackexchange.com/a/612111/29178)

![duf](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-33bf87f22dc9ea3620cbe8d6aafb1a38d011bf37%2Fduf.png?alt=media)

### [`enhancd`](https://github.com/babarot/enhancd)

> \[!NOTE|label:references:]
>
> * [mattn/ltsv.vim](https://gist.github.com/mattn/4737234)
> * [\* lfromanini/smartcd](https://github.com/lfromanini/smartcd)
> * [\* iMarslo : autocmd BufWritePre except](https://github.com/marslo/ibook/blob/marslo/docs/vim/tricky.html#autocmd-bufwritepre-except)
>
>   ```vim
>   " original
>   autocmd BufWritePre * :retab!                                   " automatic retab
>
>   " for ltsv
>   if has( "autocmd" )
>     autocmd BufRead,BufNewFile  *.ltsv                 set filetype=ltsv syntax=groovy noexpandtab
>     autocmd BufWritePre         *\(.ltsv\|.diffs\)\@<! :retab!    " automatic retab
>   endif
>   ```

* install

  ```bash
  $ git clone https://github.com/babarot/enhancd && source enhancd/init.sh

  # or
  $ curl -L git.io/enhancd | sh
  ```
* re-mapping cmd

  ```bash
  diff --git a/init.sh b/init.sh
  index 55a9c95..bc3ae89 100644
  --- a/init.sh
  +++ b/init.sh
  @@ -52,8 +52,8 @@ if [[ ! -f ${ENHANCD_DIR}/enhancd.log ]]; then
     touch "${ENHANCD_DIR}/enhancd.log"
   fi

  -# alias to cd
  -eval "alias ${ENHANCD_COMMAND:=cd}=__enhancd::cd"
  +# alias to ce
  +eval "alias ${ENHANCD_COMMAND:=ce}=__enhancd::cd"

   # Set the filter if empty
   if [[ -z ${ENHANCD_FILTER} ]]; then
  ```
* usage

  ```bash
  $ brew install fzy
  # debine
  $ sudo apt install fzy

  $ export ENHANCD_FILTER="fzf --height 35%:fzy"
  $ source /path/to/enhancd/init.sh
  $ ce .
  ```

  ![enhancd](https://676843113-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-Me-5q7RO3-g9rN8QNaK%2Fuploads%2Fgit-blob-9f39cc1598a23572d014e8575aff73eedb8db542%2Fecd-ec.gif?alt=media)

### [watchman](https://facebook.github.io/watchman/)
