From d684da753cb116d039ed8d8f401db066fd0809ae Mon Sep 17 00:00:00 2001 From: szktkfm Date: Sat, 23 Mar 2024 21:31:42 +0900 Subject: [PATCH] todo: test --- parser.go | 3 +- printer.go | 62 ++-- printer_test.go | 4 +- test.md | 872 ++++++++++++++++++++++++++++++++++++++++++++++++ testdata/02.md | 20 +- 5 files changed, 917 insertions(+), 44 deletions(-) create mode 100644 test.md diff --git a/parser.go b/parser.go index 1ba46ad..87a2f99 100644 --- a/parser.go +++ b/parser.go @@ -76,7 +76,8 @@ func (b *ModelBuilder) build() []TableModel { var cols []Column for i := range len(t.cols) { - cols = append(cols, Column{Title: NewCell(t.cols[i]), Width: 20}) + //todo: widthおかしい + cols = append(cols, Column{Title: NewCell(t.cols[i]), Width: 35}) } t := NewTable( diff --git a/printer.go b/printer.go index 9787679..bd3c76e 100644 --- a/printer.go +++ b/printer.go @@ -11,6 +11,22 @@ import ( "github.com/charmbracelet/log" ) +func Write(m Model) { + tw := TableWriter{} + tw.write(m) +} + +type TableWriter struct { + // segをフィールドに持つ必要ないのでは + segs []TableSegment + seg TableSegment + text string +} +type TableSegment struct { + Start int + End int +} + func (t *TableWriter) render(m TableModel) { var sb strings.Builder var width int @@ -39,13 +55,7 @@ func (t *TableWriter) render(m TableModel) { t.text = sb.String() } -func Write(m Model) { - tw := TableWriter{} - tw.write(m) -} - func (t *TableWriter) write(m Model) { - t.render(m.table) if m.inplace { @@ -54,11 +64,12 @@ func (t *TableWriter) write(m Model) { log.Fatal(err) } defer fp.Close() + t.findSegment(fp) fp.Seek(0, 0) b, _ := io.ReadAll(fp) - b = append(b[:t.seg.start-1], - append([]byte(t.text), b[t.seg.end:]...)...) + b = append(b[:t.seg.Start-1], + append([]byte(t.text), b[t.seg.End:]...)...) os.WriteFile(m.fpath, b, 0644) } else { @@ -70,11 +81,11 @@ func (t *TableWriter) write(m Model) { // ^\s*\|?\s*\-+ // TODO: delimeterの左寄せとか -var tableDelimLeft = regexp.MustCompile(`^\s*\:\-+\s*$`) -var tableDelimRight = regexp.MustCompile(`^\s*\-+\:\s*$`) -var tableDelimCenter = regexp.MustCompile(`^\s*\:\-+\:\s*$`) -var tableDelimNone = regexp.MustCompile(`^\s*\-+\s*$`) -var tableDelim = regexp.MustCompile(`^\s*\|?\s*\-+`) +// var tableDelimLeft = regexp.MustCompile(`^\s*\:\-+\s*$`) +// var tableDelimRight = regexp.MustCompile(`^\s*\-+\:\s*$`) +// var tableDelimCenter = regexp.MustCompile(`^\s*\:\-+\:\s*$`) +// var tableDelimNone = regexp.MustCompile(`^\s*\-+\s*$`) +var tableDelim = regexp.MustCompile(`^\s*\|?\s*\-+\s*\|?\s*`) func (t *TableWriter) findSegment(fp io.Reader) { // fmt.Println([]byte(fmt.Sprint(fp))) @@ -99,13 +110,12 @@ func (t *TableWriter) findSegment(fp io.Reader) { } pos += len(l) + 1 - - if tableDelimLeft.MatchString(l) || - tableDelimRight.MatchString(l) || - tableDelimCenter.MatchString(l) || - tableDelimNone.MatchString(l) || - tableDelim.MatchString(l) { + if tableDelim.MatchString(l) { // header check + log.Debug("line", l) + if prevline == "" { + continue + } if len(strings.Split(trimPipe(prevline), "|")) <= len(strings.Split(trimPipe(l), "|")) { inTable = true start = pos - len(l) - prevlen @@ -122,7 +132,9 @@ func (t *TableWriter) findSegment(fp io.Reader) { } // TODO: listで返す - t.seg = TableSegment{start: start, end: end} + log.Debug(t) + t.seg = TableSegment{Start: start, End: end} + log.Debugf("start: %d, end: %d", start, end) } func trimPipe(l string) string { @@ -134,13 +146,3 @@ func trimPipe(l string) string { } return l } - -type TableWriter struct { - segs []TableSegment - seg TableSegment - text string -} -type TableSegment struct { - start int - end int -} diff --git a/printer_test.go b/printer_test.go index b34e6e8..147cd88 100644 --- a/printer_test.go +++ b/printer_test.go @@ -19,8 +19,8 @@ func TestFindSegment(t *testing.T) { tw.findSegment(b) got := tw.seg want := TableSegment{ - start: 9, - end: 50, + Start: 9, + End: 50, } if diff := cmp.Diff(want, got); diff != "" { diff --git a/test.md b/test.md new file mode 100644 index 0000000..073da89 --- /dev/null +++ b/test.md @@ -0,0 +1,872 @@ +
+Special thanks to: +
+
+ +
+ Warp +
+ Warp is a modern, Rust-based terminal with AI built in so you and your team can build great software, faster. +
+ Visit warp.dev to learn more. +
+
+
+
+
+
+ +fzf - a command-line fuzzy finder [![github-actions](https://github.com/junegunn/fzf/workflows/Test%20fzf%20on%20Linux/badge.svg)](https://github.com/junegunn/fzf/actions) +=== + +fzf is a general-purpose command-line fuzzy finder. + + + +It's an interactive Unix filter for command-line that can be used with any +list; files, command history, processes, hostnames, bookmarks, git commits, +etc. + +Pros +---- + +- Portable, no dependencies +- Blazingly fast +- The most comprehensive feature set +- Flexible layout +- Batteries included + - Vim/Neovim plugin, key bindings, and fuzzy auto-completion + +Sponsors ❤️ +----------- + +I would like to thank all the sponsors of this project who make it possible for me to continue to improve fzf. + +If you'd like to sponsor this project, please visit https://github.com/sponsors/junegunn. + +miyanokomiyaJon GjengsetKyle L. DavisFrederick ZhangMoritz DietzMikkel MalmbergPierre DubouilhRyan Roden-CorrentJordan ArentsenMislav MarohnićAlex ViscreanuDavid BalateroOndrej SynacekMathias Jean JohansenBen ElanPaweł DudaSantiago LezicaTimo SulgDamien RajonArtBITHovisDarius JondaCristian DominguezChang-Hung LiangBen Lechlitneryashgeorge looshchTakumi KAGIYAMAPaul O'Leary McCannRobert BeegerVEEB ProjectsKhue DoanYoway BuornJosh ScalisiAlec Scottthanks.devArtur SapekGuillaume GelinMarcin S.Rob LevyGloria ZhaoPooriaWill ThompsonRolandMr. Henry + +Table of Contents +----------------- + + + +* [Installation](#installation) + * [Using Homebrew](#using-homebrew) + * [Using git](#using-git) + * [Using Linux package managers](#using-linux-package-managers) + * [Windows](#windows) + * [Setting up shell integration](#setting-up-shell-integration) + * [As Vim plugin](#as-vim-plugin) +* [Upgrading fzf](#upgrading-fzf) +* [Building fzf](#building-fzf) +* [Usage](#usage) + * [Using the finder](#using-the-finder) + * [Layout](#layout) + * [Search syntax](#search-syntax) + * [Environment variables](#environment-variables) + * [Options](#options) + * [Demo](#demo) +* [Examples](#examples) +* [`fzf-tmux` script](#fzf-tmux-script) +* [Key bindings for command-line](#key-bindings-for-command-line) +* [Fuzzy completion for bash and zsh](#fuzzy-completion-for-bash-and-zsh) + * [Files and directories](#files-and-directories) + * [Process IDs](#process-ids) + * [Host names](#host-names) + * [Environment variables / Aliases](#environment-variables--aliases) + * [Settings](#settings) + * [Supported commands](#supported-commands) + * [Custom fuzzy completion](#custom-fuzzy-completion) +* [Vim plugin](#vim-plugin) +* [Advanced topics](#advanced-topics) + * [Performance](#performance) + * [Executing external programs](#executing-external-programs) + * [Turning into a different process](#turning-into-a-different-process) + * [Reloading the candidate list](#reloading-the-candidate-list) + * [1. Update the list of processes by pressing CTRL-R](#1-update-the-list-of-processes-by-pressing-ctrl-r) + * [2. Switch between sources by pressing CTRL-D or CTRL-F](#2-switch-between-sources-by-pressing-ctrl-d-or-ctrl-f) + * [3. Interactive ripgrep integration](#3-interactive-ripgrep-integration) + * [Preview window](#preview-window) + * [Previewing an image](#previewing-an-image) +* [Tips](#tips) + * [Respecting `.gitignore`](#respecting-gitignore) + * [Fish shell](#fish-shell) + * [fzf Theme Playground](#fzf-theme-playground) +* [Related projects](#related-projects) +* [License](#license) + + + +Installation +------------ + +fzf project consists of the following components: + +- `fzf` executable +- `fzf-tmux` script for launching fzf in a tmux pane +- Shell integration + - Key bindings (`CTRL-T`, `CTRL-R`, and `ALT-C`) (bash, zsh, fish) + - Fuzzy completion (bash, zsh) +- Vim/Neovim plugin + +You can [download fzf executable][bin] alone if you don't need the extra +stuff. + +[bin]: https://github.com/junegunn/fzf/releases + +### Using Homebrew + +You can use [Homebrew](https://brew.sh/) (on macOS or Linux) +to install fzf. + +```sh +brew install fzf +``` + +> [!IMPORTANT] +> To set up shell integration (key bindings and fuzzy completion), +> see [the instructions below](#setting-up-shell-integration). + +fzf is also available [via MacPorts][portfile]: `sudo port install fzf` + +[portfile]: https://github.com/macports/macports-ports/blob/master/sysutils/fzf/Portfile + +### Using git + +Alternatively, you can "git clone" this repository to any directory and run +[install](https://github.com/junegunn/fzf/blob/master/install) script. + +```sh +git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf +~/.fzf/install +``` + +The install script will add lines to your shell configuration file to modify +`$PATH` and set up shell integration. + +### Using Linux package managers + +| Package Manager | Linux Distribution | Command | +| --------------- | ----------------------- | ---------------------------------- | +| APK | Alpine Linux | `sudo apk add fzf` | +| APT | Debian 9+/Ubuntu 19.10+ | `sudo apt install fzf` | +| Conda | | `conda install -c conda-forge fzf` | +| DNF | Fedora | `sudo dnf install fzf` | +| Nix | NixOS, etc. | `nix-env -iA nixpkgs.fzf` | +| Pacman | Arch Linux | `sudo pacman -S fzf` | +| pkg | FreeBSD | `pkg install fzf` | +| pkgin | NetBSD | `pkgin install fzf` | +| pkg_add | OpenBSD | `pkg_add fzf` | +| Portage | Gentoo | `emerge --ask app-shells/fzf` | +| Spack | | `spack install fzf` | +| XBPS | Void Linux | `sudo xbps-install -S fzf` | +| Zypper | openSUSE | `sudo zypper install fzf` | + + +### Setting up shell integration + +Add the following line to your shell configuration file. + +* bash + ```sh + # Set up fzf key bindings and fuzzy completion + eval "$(fzf --bash)" + ``` +* zsh + ```sh + # Set up fzf key bindings and fuzzy completion + eval "$(fzf --zsh)" + ``` +* fish + ```fish + # Set up fzf key bindings + fzf --fish | source + ``` + +> [!NOTE] +> `--bash`, `--zsh`, and `--fish` options are only available in fzf 0.48.0 or +> later. If you have an older version of fzf, or want finer control, you can +> source individual script files in the [/shell](/shell) directory. The +> location of the files may vary depending on the package manager you use. +> Please refer to the package documentation for more information. +> (e.g. `apt show fzf`) + +> [!TIP] +> You can disable CTRL-T or ALT-C binding by setting `FZF_CTRL_T_COMMAND` or +> `FZF_ALT_C_COMMAND` to an empty string when sourcing the script. +> For example, to disable ALT-C binding: +> +> * bash: `FZF_ALT_C_COMMAND= eval "$(fzf --bash)"` +> * zsh: `FZF_ALT_C_COMMAND= eval "$(fzf --zsh)"` +> * fish: `fzf --fish | FZF_ALT_C_COMMAND= source` +> +> Setting the variables after sourcing the script will have no effect. + +### As Vim plugin + +If you use +[vim-plug](https://github.com/junegunn/vim-plug), add this line to your Vim +configuration file: + +```vim +Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } +``` + +`fzf#install()` makes sure that you have the latest binary, but it's optional, +so you can omit it if you use a plugin manager that doesn't support hooks. + +For more installation options, see [README-VIM.md](README-VIM.md). + +Upgrading fzf +------------- + +fzf is being actively developed, and you might want to upgrade it once in a +while. Please follow the instruction below depending on the installation +method used. + +- git: `cd ~/.fzf && git pull && ./install` +- brew: `brew update; brew upgrade fzf` +- macports: `sudo port upgrade fzf` +- chocolatey: `choco upgrade fzf` +- vim-plug: `:PlugUpdate fzf` + +Building fzf +------------ + +See [BUILD.md](BUILD.md). + +Usage +----- + +fzf will launch interactive finder, read the list from STDIN, and write the +selected item to STDOUT. + +```sh +find * -type f | fzf > selected +``` + +Without STDIN pipe, fzf will traverse the file system under the current +directory to get the list of files. + +```sh +vim $(fzf) +``` + +> [!NOTE] +> You can override the default behavior +> * Either by setting `$FZF_DEFAULT_COMMAND` to a command that generates the desired list +> * Or by setting `--walker`, `--walker-root`, and `--walker-skip` options in `$FZF_DEFAULT_OPTS` + +> [!WARNING] +> A more robust solution would be to use `xargs` but we've presented +> the above as it's easier to grasp +> ```sh +> fzf --print0 | xargs -0 -o vim +> ``` + +> [!TIP] +> fzf also has the ability to turn itself into a different process. +> +> ```sh +> fzf --bind 'enter:become(vim {})' +> ``` +> +> *See [Turning into a different process](#turning-into-a-different-process) +> for more information.* + +### Using the finder + +- `CTRL-K` / `CTRL-J` (or `CTRL-P` / `CTRL-N`) to move cursor up and down +- `Enter` key to select the item, `CTRL-C` / `CTRL-G` / `ESC` to exit +- On multi-select mode (`-m`), `TAB` and `Shift-TAB` to mark multiple items +- Emacs style key bindings +- Mouse: scroll, click, double-click; shift-click and shift-scroll on + multi-select mode + +### Layout + +fzf by default starts in fullscreen mode, but you can make it start below the +cursor with `--height` option. + +```sh +vim $(fzf --height 40%) +``` + +Also, check out `--reverse` and `--layout` options if you prefer +"top-down" layout instead of the default "bottom-up" layout. + +```sh +vim $(fzf --height 40% --reverse) +``` + +You can add these options to `$FZF_DEFAULT_OPTS` so that they're applied by +default. For example, + +```sh +export FZF_DEFAULT_OPTS='--height 40% --layout=reverse --border' +``` + +### Search syntax + +Unless otherwise specified, fzf starts in "extended-search mode" where you can +type in multiple search terms delimited by spaces. e.g. `^music .mp3$ sbtrkt +!fire` + + + +If you don't prefer fuzzy matching and do not wish to "quote" every word, +start fzf with `-e` or `--exact` option. Note that when `--exact` is set, +`'`-prefix "unquotes" the term. + +A single bar character term acts as an OR operator. For example, the following +query matches entries that start with `core` and end with either `go`, `rb`, +or `py`. + +``` +^core go$ | rb$ | py$ +``` + +### Environment variables + +- `FZF_DEFAULT_COMMAND` + - Default command to use when input is tty + - e.g. `export FZF_DEFAULT_COMMAND='fd --type f'` +- `FZF_DEFAULT_OPTS` + - Default options + - e.g. `export FZF_DEFAULT_OPTS="--layout=reverse --inline-info"` +- `FZF_DEFAULT_OPTS_FILE` + - If you prefer to manage default options in a file, set this variable to + point to the location of the file + - e.g. `export FZF_DEFAULT_OPTS_FILE=~/.fzfrc` + +> [!WARNING] +> `FZF_DEFAULT_COMMAND` is not used by shell integration due to the +> slight difference in requirements. +> +> * `CTRL-T` runs `$FZF_CTRL_T_COMMAND` to get a list of files and directories +> * `ALT-C` runs `$FZF_ALT_C_COMMAND` to get a list of directories +> * `vim ~/**` runs `fzf_compgen_path()` with the prefix (`~/`) as the first argument +> * `cd foo**` runs `fzf_compgen_dir()` with the prefix (`foo`) as the first argument +> +> The available options are described later in this document. + +### Options + +See the man page (`man fzf`) for the full list of options. + +### Demo +If you learn by watching videos, check out this screencast by [@samoshkin](https://github.com/samoshkin) to explore `fzf` features. + + + + + +Examples +-------- + +* [Wiki page of examples](https://github.com/junegunn/fzf/wiki/examples) + * *Disclaimer: The examples on this page are maintained by the community + and are not thoroughly tested* +* [Advanced fzf examples](https://github.com/junegunn/fzf/blob/master/ADVANCED.md) + +`fzf-tmux` script +----------------- + +[fzf-tmux](bin/fzf-tmux) is a bash script that opens fzf in a tmux pane. + +```sh +# usage: fzf-tmux [LAYOUT OPTIONS] [--] [FZF OPTIONS] + +# See available options +fzf-tmux --help + +# select git branches in horizontal split below (15 lines) +git branch | fzf-tmux -d 15 + +# select multiple words in vertical split on the left (20% of screen width) +cat /usr/share/dict/words | fzf-tmux -l 20% --multi --reverse +``` + +It will still work even when you're not on tmux, silently ignoring `-[pudlr]` +options, so you can invariably use `fzf-tmux` in your scripts. + +Alternatively, you can use `--height HEIGHT[%]` option not to start fzf in +fullscreen mode. + +```sh +fzf --height 40% +``` + +Key bindings for command-line +----------------------------- + +The install script will setup the following key bindings for bash, zsh, and +fish. + +- `CTRL-T` - Paste the selected files and directories onto the command-line + - The list is generated using `--walker file,dir,follow,hidden` option + - You can override the behavior by setting `FZF_CTRL_T_COMMAND` to a custom command that generates the desired list + - Or you can set `--walker*` options in `FZF_CTRL_T_OPTS` + - Set `FZF_CTRL_T_OPTS` to pass additional options to fzf + ```sh + # Preview file content using bat (https://github.com/sharkdp/bat) + export FZF_CTRL_T_OPTS=" + --walker-skip .git,node_modules,target + --preview 'bat -n --color=always {}' + --bind 'ctrl-/:change-preview-window(down|hidden|)'" + ``` + - Can be disabled by setting `FZF_CTRL_T_COMMAND` to an empty string when + sourcing the script +- `CTRL-R` - Paste the selected command from history onto the command-line + - If you want to see the commands in chronological order, press `CTRL-R` + again which toggles sorting by relevance + - Set `FZF_CTRL_R_OPTS` to pass additional options to fzf + ```sh + # CTRL-/ to toggle small preview window to see the full command + # CTRL-Y to copy the command into clipboard using pbcopy + 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'" + ``` +- `ALT-C` - cd into the selected directory + - The list is generated using `--walker dir,follow,hidden` option + - Set `FZF_ALT_C_COMMAND` to override the default command + - Or you can set `--walker-*` options in `FZF_ALT_C_OPTS` + - Set `FZF_ALT_C_OPTS` to pass additional options to fzf + ```sh + # Print tree structure in the preview window + export FZF_ALT_C_OPTS=" + --walker-skip .git,node_modules,target + --preview 'tree -C {}'" + ``` + - Can be disabled by setting `FZF_ALT_C_COMMAND` to an empty string when + sourcing the script + +If you're on a tmux session, you can start fzf in a tmux split-pane or in +a tmux popup window by setting `FZF_TMUX_OPTS` (e.g. `export FZF_TMUX_OPTS='-p80%,60%'`). +See `fzf-tmux --help` for available options. + +More tips can be found on [the wiki page](https://github.com/junegunn/fzf/wiki/Configuring-shell-key-bindings). + +Fuzzy completion for bash and zsh +--------------------------------- + +### Files and directories + +Fuzzy completion for files and directories can be triggered if the word before +the cursor ends with the trigger sequence, which is by default `**`. + +- `COMMAND [DIRECTORY/][FUZZY_PATTERN]**` + +```sh +# Files under the current directory +# - You can select multiple items with TAB key +vim ** + +# Files under parent directory +vim ../** + +# Files under parent directory that match `fzf` +vim ../fzf** + +# Files under your home directory +vim ~/** + + +# Directories under current directory (single-selection) +cd ** + +# Directories under ~/github that match `fzf` +cd ~/github/fzf** +``` + +### Process IDs + +Fuzzy completion for PIDs is provided for kill command. + +```sh +# Can select multiple processes with or keys +kill -9 ** +``` + +### Host names + +For ssh and telnet commands, fuzzy completion for hostnames is provided. The +names are extracted from /etc/hosts and ~/.ssh/config. + +```sh +ssh ** +telnet ** +``` + +### Environment variables / Aliases + +```sh +unset ** +export ** +unalias ** +``` + +### Settings + +```sh +# Use ~~ as the trigger sequence instead of the default ** +export FZF_COMPLETION_TRIGGER='~~' + +# Options to fzf command +export FZF_COMPLETION_OPTS='--border --info=inline' + +# Use fd (https://github.com/sharkdp/fd) for listing path candidates. +# - The first argument to the function ($1) is the base path to start traversal +# - See the source code (completion.{bash,zsh}) for the details. +_fzf_compgen_path() { + fd --hidden --follow --exclude ".git" . "$1" +} + +# Use fd to generate the list for directory completion +_fzf_compgen_dir() { + fd --type d --hidden --follow --exclude ".git" . "$1" +} + +# Advanced customization of fzf options via _fzf_comprun function +# - The first argument to the function is the name of the command. +# - You should make sure to pass the rest of the arguments to fzf. +_fzf_comprun() { + local command=$1 + shift + + case "$command" in + cd) fzf --preview 'tree -C {} | head -200' "$@" ;; + export|unset) fzf --preview "eval 'echo \$'{}" "$@" ;; + ssh) fzf --preview 'dig {}' "$@" ;; + *) fzf --preview 'bat -n --color=always {}' "$@" ;; + esac +} +``` + +### Supported commands + +On bash, fuzzy completion is enabled only for a predefined set of commands +(`complete | grep _fzf` to see the list). But you can enable it for other +commands as well by using `_fzf_setup_completion` helper function. + +```sh +# usage: _fzf_setup_completion path|dir|var|alias|host COMMANDS... +_fzf_setup_completion path ag git kubectl +_fzf_setup_completion dir tree +``` + +### Custom fuzzy completion + +_**(Custom completion API is experimental and subject to change)**_ + +For a command named _"COMMAND"_, define `_fzf_complete_COMMAND` function using +`_fzf_complete` helper. + +```sh +# Custom fuzzy completion for "doge" command +# e.g. doge ** +_fzf_complete_doge() { + _fzf_complete --multi --reverse --prompt="doge> " -- "$@" < <( + echo very + echo wow + echo such + echo doge + ) +} +``` + +- The arguments before `--` are the options to fzf. +- After `--`, simply pass the original completion arguments unchanged (`"$@"`). +- Then, write a set of commands that generates the completion candidates and + feed its output to the function using process substitution (`< <(...)`). + +zsh will automatically pick up the function using the naming convention but in +bash you have to manually associate the function with the command using the +`complete` command. + +```sh +[ -n "$BASH" ] && complete -F _fzf_complete_doge -o default -o bashdefault doge +``` + +If you need to post-process the output from fzf, define +`_fzf_complete_COMMAND_post` as follows. + +```sh +_fzf_complete_foo() { + _fzf_complete --multi --reverse --header-lines=3 -- "$@" < <( + ls -al + ) +} + +_fzf_complete_foo_post() { + awk '{print $NF}' +} + +[ -n "$BASH" ] && complete -F _fzf_complete_foo -o default -o bashdefault foo +``` + +Vim plugin +---------- + +See [README-VIM.md](README-VIM.md). + +Advanced topics +--------------- + +### Performance + +fzf is fast. Performance should not be a problem in most use cases. However, +you might want to be aware of the options that can affect performance. + +- `--ansi` tells fzf to extract and parse ANSI color codes in the input, and it + makes the initial scanning slower. So it's not recommended that you add it + to your `$FZF_DEFAULT_OPTS`. +- `--nth` makes fzf slower because it has to tokenize each line. +- `--with-nth` makes fzf slower as fzf has to tokenize and reassemble each + line. + +### Executing external programs + +You can set up key bindings for starting external processes without leaving +fzf (`execute`, `execute-silent`). + +```bash +# Press F1 to open the file with less without leaving fzf +# Press CTRL-Y to copy the line to clipboard and aborts fzf (requires pbcopy) +fzf --bind 'f1:execute(less -f {}),ctrl-y:execute-silent(echo {} | pbcopy)+abort' +``` + +See *KEY BINDINGS* section of the man page for details. + +### Turning into a different process + +`become(...)` is similar to `execute(...)`/`execute-silent(...)` described +above, but instead of executing the command and coming back to fzf on +complete, it turns fzf into a new process for the command. + +```sh +fzf --bind 'enter:become(vim {})' +``` + +Compared to the seemingly equivalent command substitution `vim "$(fzf)"`, this +approach has several advantages: + +* Vim will not open an empty file when you terminate fzf with + CTRL-C +* Vim will not open an empty file when you press ENTER on an empty + result +* Can handle multiple selections even when they have whitespaces + ```sh + fzf --multi --bind 'enter:become(vim {+})' + ``` + +To be fair, running `fzf --print0 | xargs -0 -o vim` instead of `vim "$(fzf)"` +resolves all of the issues mentioned. Nonetheless, `become(...)` still offers +additional benefits in different scenarios. + +* You can set up multiple bindings to handle the result in different ways + without any wrapping script + ```sh + fzf --bind 'enter:become(vim {}),ctrl-e:become(emacs {})' + ``` + * Previously, you would have to use `--expect=ctrl-e` and check the first + line of the output of fzf +* You can easily build the subsequent command using the field index + expressions of fzf + ```sh + # Open the file in Vim and go to the line + git grep --line-number . | + fzf --delimiter : --nth 3.. --bind 'enter:become(vim {1} +{2})' + ``` + +### Reloading the candidate list + +By binding `reload` action to a key or an event, you can make fzf dynamically +reload the candidate list. See https://github.com/junegunn/fzf/issues/1750 for +more details. + +#### 1. Update the list of processes by pressing CTRL-R + +```sh +ps -ef | + fzf --bind 'ctrl-r:reload(ps -ef)' \ + --header 'Press CTRL-R to reload' --header-lines=1 \ + --height=50% --layout=reverse +``` + +#### 2. Switch between sources by pressing CTRL-D or CTRL-F + +```sh +FZF_DEFAULT_COMMAND='find . -type f' \ + fzf --bind 'ctrl-d:reload(find . -type d),ctrl-f:reload(eval "$FZF_DEFAULT_COMMAND")' \ + --height=50% --layout=reverse +``` + +#### 3. Interactive ripgrep integration + +The following example uses fzf as the selector interface for ripgrep. We bound +`reload` action to `change` event, so every time you type on fzf, the ripgrep +process will restart with the updated query string denoted by the placeholder +expression `{q}`. Also, note that we used `--disabled` option so that fzf +doesn't perform any secondary filtering. + +```sh +: | rg_prefix='rg --column --line-number --no-heading --color=always --smart-case' \ + fzf --bind 'start:reload:$rg_prefix ""' \ + --bind 'change:reload:$rg_prefix {q} || true' \ + --bind 'enter:become(vim {1} +{2})' \ + --ansi --disabled \ + --height=50% --layout=reverse +``` + +If ripgrep doesn't find any matches, it will exit with a non-zero exit status, +and fzf will warn you about it. To suppress the warning message, we added +`|| true` to the command, so that it always exits with 0. + +See ["Using fzf as interactive Ripgrep launcher"](https://github.com/junegunn/fzf/blob/master/ADVANCED.md#using-fzf-as-interactive-ripgrep-launcher) +for more sophisticated examples. + +### Preview window + +When the `--preview` option is set, fzf automatically starts an external process +with the current line as the argument and shows the result in the split window. +Your `$SHELL` is used to execute the command with `$SHELL -c COMMAND`. +The window can be scrolled using the mouse or custom key bindings. + +```bash +# {} is replaced with the single-quoted string of the focused line +fzf --preview 'cat {}' +``` + +Preview window supports ANSI colors, so you can use any program that +syntax-highlights the content of a file, such as +[Bat](https://github.com/sharkdp/bat) or +[Highlight](https://gitlab.com/saalen/highlight): + +```bash +fzf --preview 'bat --color=always {}' --preview-window '~3' +``` + +You can customize the size, position, and border of the preview window using +`--preview-window` option, and the foreground and background color of it with +`--color` option. For example, + +```bash +fzf --height 40% --layout reverse --info inline --border \ +|Package Manager |Linux Distribution |Command | +|-----------------------------------|-----------------------------------|-----------------------------------| +|APK |Alpine Linux |`sudo apk add fzf` | +|APT |Debian 9+/Ubuntu 19.10+ |`sudo apt install fzf` | +|Conda | |`conda install -c conda-forge fzf` | +|DNF |Fedora |`sudo dnf install fzf` | +|Nix |NixOS, etc. |`nix-env -iA nixpkgs.fzf` | +|Pacman |Arch Linux |`sudo pacman -S fzf` | +|pkg |FreeBSD |`pkg install fzf` | +|pkgin |NetBSD |`pkgin install fzf` | +|pkg_add |OpenBSD |`pkg_add fzf` | +|Portage |Gentoo |`emerge --ask app-shells/fzf` | +|Spack | |`spack install fzf` | +|XBPS |Void Linux |`sudo xbps-install -S fzf` | +|Zypper |openSUSE |`sudo zypper install fzf` | + +See the man page (`man fzf`) for the full list of options. + +More advanced examples can be found [here](https://github.com/junegunn/fzf/blob/master/ADVANCED.md). + +> [!WARNING] +> Since fzf is a general-purpose text filter rather than a file finder, **it is +> not a good idea to add `--preview` option to your `$FZF_DEFAULT_OPTS`**. +> +> ```sh +> # ********************* +> # ** DO NOT DO THIS! ** +> # ********************* +> export FZF_DEFAULT_OPTS='--preview "bat --style=numbers --color=always --line-range :500 {}"' +> +> # bat doesn't work with any input other than the list of files +> ps -ef | fzf +> seq 100 | fzf +> history | fzf +> ``` + +### Previewing an image + +fzf can display images in the preview window using one of the following protocols: + +* [Kitty graphics protocol](https://sw.kovidgoyal.net/kitty/graphics-protocol/) +* [iTerm2 inline images protocol](https://iterm2.com/documentation-images.html) +* [Sixel](https://en.wikipedia.org/wiki/Sixel) + +See [bin/fzf-preview.sh](bin/fzf-preview.sh) script for more information. + +```sh +fzf --preview 'fzf-preview.sh {}' +``` + +### Respecting `.gitignore` + +You can use [fd](https://github.com/sharkdp/fd), +[ripgrep](https://github.com/BurntSushi/ripgrep), or [the silver +searcher](https://github.com/ggreer/the_silver_searcher) to traverse the file +system while respecting `.gitignore`. + +```sh +# Feed the output of fd into fzf +fd --type f --strip-cwd-prefix | fzf + +# Setting fd as the default source for fzf +export FZF_DEFAULT_COMMAND='fd --type f --strip-cwd-prefix' + +# Now fzf (w/o pipe) will use the fd command to generate the list +fzf + +# To apply the command to CTRL-T as well +export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" +``` + +If you want the command to follow symbolic links and don't want it to exclude +hidden files, use the following command: + +```sh +export FZF_DEFAULT_COMMAND='fd --type f --strip-cwd-prefix --hidden --follow --exclude .git' +``` + +### Fish shell + +`CTRL-T` key binding of fish, unlike those of bash and zsh, will use the last +token on the command-line as the root directory for the recursive search. For +instance, hitting `CTRL-T` at the end of the following command-line + +```sh +ls /var/ +``` + +will list all files and directories under `/var/`. + +When using a custom `FZF_CTRL_T_COMMAND`, use the unexpanded `$dir` variable to +make use of this feature. `$dir` defaults to `.` when the last token is not a +valid directory. Example: + +```sh +set -g FZF_CTRL_T_COMMAND "command find -L \$dir -type f 2> /dev/null | sed '1d; s#^\./##'" +``` + +### fzf Theme Playground + +[fzf Theme Playground](https://vitormv.github.io/fzf-themes/) created by +[Vitor Mello](https://github.com/vitormv) is a webpage where you can +interactively create fzf themes. + diff --git a/testdata/02.md b/testdata/02.md index 47fecf9..c9e27e4 100644 --- a/testdata/02.md +++ b/testdata/02.md @@ -1,15 +1,13 @@ # title -|foo |TESTETESET |TEST | -|--------------------|------------|--------------------| -|test test test |test |TEST | -|test test test |test |TEST | -|test test test |test |TEST | -|test test test |test |TEST | -|test test test | |TEST | -|test test test | |TEST | -|test test test | |TEST | -|test test test | |TEST | -|test test test | |TEST | +|foo |TESTETEST |TEST | +|-----------------------------------|-----------------------------------|-----------------------------------| +|test test test |test |TEST | +|test test testddjdfi | |TEST | +|test test test | |TEST | +|test test test | |TEST | +|test test test | |TEST | +|test test test | |TEST | +|test test test | |TEST | end end \ No newline at end of file