doing 2.0.18 → 2.0.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/Gemfile.lock +15 -5
  4. data/README.md +1 -1
  5. data/bin/doing +2 -18
  6. data/doing.gemspec +5 -4
  7. data/doing.rdoc +2 -2
  8. data/generate_completions.sh +3 -3
  9. data/lib/doing/cli_status.rb +6 -2
  10. data/lib/doing/completion/bash_completion.rb +185 -0
  11. data/lib/doing/completion/fish_completion.rb +175 -0
  12. data/lib/doing/completion/string.rb +17 -0
  13. data/lib/doing/completion/zsh_completion.rb +140 -0
  14. data/lib/doing/completion.rb +39 -0
  15. data/lib/doing/version.rb +1 -1
  16. data/lib/doing/wwid.rb +18 -6
  17. data/lib/doing.rb +1 -1
  18. data/lib/helpers/fzf/.goreleaser.yml +119 -0
  19. data/lib/helpers/fzf/.rubocop.yml +28 -0
  20. data/lib/helpers/fzf/ADVANCED.md +565 -0
  21. data/lib/helpers/fzf/BUILD.md +49 -0
  22. data/lib/helpers/fzf/CHANGELOG.md +1193 -0
  23. data/lib/helpers/fzf/Dockerfile +11 -0
  24. data/lib/helpers/fzf/LICENSE +21 -0
  25. data/lib/helpers/fzf/Makefile +166 -0
  26. data/lib/helpers/fzf/README-VIM.md +486 -0
  27. data/lib/helpers/fzf/README.md +712 -0
  28. data/lib/helpers/fzf/bin/fzf-tmux +233 -0
  29. data/lib/helpers/fzf/doc/fzf.txt +512 -0
  30. data/lib/helpers/fzf/go.mod +17 -0
  31. data/lib/helpers/fzf/go.sum +31 -0
  32. data/lib/helpers/fzf/install +382 -0
  33. data/lib/helpers/fzf/install.ps1 +65 -0
  34. data/lib/helpers/fzf/main.go +14 -0
  35. data/lib/helpers/fzf/man/man1/fzf-tmux.1 +68 -0
  36. data/lib/helpers/fzf/man/man1/fzf.1 +1001 -0
  37. data/lib/helpers/fzf/plugin/fzf.vim +1048 -0
  38. data/lib/helpers/fzf/shell/completion.bash +381 -0
  39. data/lib/helpers/fzf/shell/completion.zsh +329 -0
  40. data/lib/helpers/fzf/shell/key-bindings.bash +96 -0
  41. data/lib/helpers/fzf/shell/key-bindings.fish +172 -0
  42. data/lib/helpers/fzf/shell/key-bindings.zsh +114 -0
  43. data/lib/helpers/fzf/src/LICENSE +21 -0
  44. data/lib/helpers/fzf/src/algo/algo.go +884 -0
  45. data/lib/helpers/fzf/src/algo/algo_test.go +197 -0
  46. data/lib/helpers/fzf/src/algo/normalize.go +492 -0
  47. data/lib/helpers/fzf/src/ansi.go +409 -0
  48. data/lib/helpers/fzf/src/ansi_test.go +427 -0
  49. data/lib/helpers/fzf/src/cache.go +81 -0
  50. data/lib/helpers/fzf/src/cache_test.go +39 -0
  51. data/lib/helpers/fzf/src/chunklist.go +89 -0
  52. data/lib/helpers/fzf/src/chunklist_test.go +80 -0
  53. data/lib/helpers/fzf/src/constants.go +85 -0
  54. data/lib/helpers/fzf/src/core.go +351 -0
  55. data/lib/helpers/fzf/src/history.go +96 -0
  56. data/lib/helpers/fzf/src/history_test.go +68 -0
  57. data/lib/helpers/fzf/src/item.go +44 -0
  58. data/lib/helpers/fzf/src/item_test.go +23 -0
  59. data/lib/helpers/fzf/src/matcher.go +235 -0
  60. data/lib/helpers/fzf/src/merger.go +120 -0
  61. data/lib/helpers/fzf/src/merger_test.go +88 -0
  62. data/lib/helpers/fzf/src/options.go +1691 -0
  63. data/lib/helpers/fzf/src/options_test.go +457 -0
  64. data/lib/helpers/fzf/src/pattern.go +425 -0
  65. data/lib/helpers/fzf/src/pattern_test.go +209 -0
  66. data/lib/helpers/fzf/src/protector/protector.go +8 -0
  67. data/lib/helpers/fzf/src/protector/protector_openbsd.go +10 -0
  68. data/lib/helpers/fzf/src/reader.go +201 -0
  69. data/lib/helpers/fzf/src/reader_test.go +63 -0
  70. data/lib/helpers/fzf/src/result.go +243 -0
  71. data/lib/helpers/fzf/src/result_others.go +16 -0
  72. data/lib/helpers/fzf/src/result_test.go +159 -0
  73. data/lib/helpers/fzf/src/result_x86.go +16 -0
  74. data/lib/helpers/fzf/src/terminal.go +2832 -0
  75. data/lib/helpers/fzf/src/terminal_test.go +638 -0
  76. data/lib/helpers/fzf/src/terminal_unix.go +26 -0
  77. data/lib/helpers/fzf/src/terminal_windows.go +45 -0
  78. data/lib/helpers/fzf/src/tokenizer.go +253 -0
  79. data/lib/helpers/fzf/src/tokenizer_test.go +112 -0
  80. data/lib/helpers/fzf/src/tui/dummy.go +46 -0
  81. data/lib/helpers/fzf/src/tui/light.go +987 -0
  82. data/lib/helpers/fzf/src/tui/light_unix.go +110 -0
  83. data/lib/helpers/fzf/src/tui/light_windows.go +145 -0
  84. data/lib/helpers/fzf/src/tui/tcell.go +721 -0
  85. data/lib/helpers/fzf/src/tui/tcell_test.go +392 -0
  86. data/lib/helpers/fzf/src/tui/ttyname_unix.go +47 -0
  87. data/lib/helpers/fzf/src/tui/ttyname_windows.go +14 -0
  88. data/lib/helpers/fzf/src/tui/tui.go +625 -0
  89. data/lib/helpers/fzf/src/tui/tui_test.go +20 -0
  90. data/lib/helpers/fzf/src/util/atomicbool.go +34 -0
  91. data/lib/helpers/fzf/src/util/atomicbool_test.go +17 -0
  92. data/lib/helpers/fzf/src/util/chars.go +198 -0
  93. data/lib/helpers/fzf/src/util/chars_test.go +46 -0
  94. data/lib/helpers/fzf/src/util/eventbox.go +96 -0
  95. data/lib/helpers/fzf/src/util/eventbox_test.go +61 -0
  96. data/lib/helpers/fzf/src/util/slab.go +12 -0
  97. data/lib/helpers/fzf/src/util/util.go +138 -0
  98. data/lib/helpers/fzf/src/util/util_test.go +40 -0
  99. data/lib/helpers/fzf/src/util/util_unix.go +47 -0
  100. data/lib/helpers/fzf/src/util/util_windows.go +83 -0
  101. data/lib/helpers/fzf/test/fzf.vader +175 -0
  102. data/lib/helpers/fzf/test/test_go.rb +2626 -0
  103. data/lib/helpers/fzf/uninstall +117 -0
  104. data/scripts/generate_bash_completions.rb +6 -12
  105. data/scripts/generate_fish_completions.rb +7 -16
  106. data/scripts/generate_zsh_completions.rb +6 -15
  107. metadata +144 -9
@@ -0,0 +1,565 @@
1
+ Advanced fzf examples
2
+ ======================
3
+
4
+ *(Last update: 2021/05/22)*
5
+
6
+ <!-- vim-markdown-toc GFM -->
7
+
8
+ * [Introduction](#introduction)
9
+ * [Screen Layout](#screen-layout)
10
+ * [`--height`](#--height)
11
+ * [`fzf-tmux`](#fzf-tmux)
12
+ * [Popup window support](#popup-window-support)
13
+ * [Dynamic reloading of the list](#dynamic-reloading-of-the-list)
14
+ * [Updating the list of processes by pressing CTRL-R](#updating-the-list-of-processes-by-pressing-ctrl-r)
15
+ * [Toggling between data sources](#toggling-between-data-sources)
16
+ * [Ripgrep integration](#ripgrep-integration)
17
+ * [Using fzf as the secondary filter](#using-fzf-as-the-secondary-filter)
18
+ * [Using fzf as interative Ripgrep launcher](#using-fzf-as-interative-ripgrep-launcher)
19
+ * [Switching to fzf-only search mode](#switching-to-fzf-only-search-mode)
20
+ * [Log tailing](#log-tailing)
21
+ * [Key bindings for git objects](#key-bindings-for-git-objects)
22
+ * [Files listed in `git status`](#files-listed-in-git-status)
23
+ * [Branches](#branches)
24
+ * [Commit hashes](#commit-hashes)
25
+ * [Color themes](#color-themes)
26
+ * [Generating fzf color theme from Vim color schemes](#generating-fzf-color-theme-from-vim-color-schemes)
27
+
28
+ <!-- vim-markdown-toc -->
29
+
30
+ Introduction
31
+ ------------
32
+
33
+ fzf is an interactive [Unix filter][filter] program that is designed to be
34
+ used with other Unix tools. It reads a list of items from the standard input,
35
+ allows you to select a subset of the items, and prints the selected ones to
36
+ the standard output. You can think of it as an interactive version of *grep*,
37
+ and it's already useful even if you don't know any of its options.
38
+
39
+ ```sh
40
+ # 1. ps: Feed the list of processes to fzf
41
+ # 2. fzf: Interactively select a process using fuzzy matching algorithm
42
+ # 3. awk: Take the PID from the selected line
43
+ # 3. kill: Kill the process with the PID
44
+ ps -ef | fzf | awk '{print $2}' | xargs kill -9
45
+ ```
46
+
47
+ [filter]: https://en.wikipedia.org/wiki/Filter_(software)
48
+
49
+ While the above example succinctly summarizes the fundamental concept of fzf,
50
+ you can build much more sophisticated interactive workflows using fzf once you
51
+ learn its wide variety of features.
52
+
53
+ - To see the full list of options and features, see `man fzf`
54
+ - To see the latest additions, see [CHANGELOG.md](CHANGELOG.md)
55
+
56
+ This document will guide you through some examples that will familiarize you
57
+ with the advanced features of fzf.
58
+
59
+ Screen Layout
60
+ -------------
61
+
62
+ ### `--height`
63
+
64
+ fzf by default opens in fullscreen mode, but it's not always desirable.
65
+ Oftentimes, you want to see the current context of the terminal while using
66
+ fzf. `--height` is an option for opening fzf below the cursor in
67
+ non-fullscreen mode so you can still see the previous commands and their
68
+ results above it.
69
+
70
+ ```sh
71
+ fzf --height=40%
72
+ ```
73
+
74
+ ![image](https://user-images.githubusercontent.com/700826/113379893-c184c680-93b5-11eb-9676-c7c0a2f01748.png)
75
+
76
+ You might also want to experiment with other layout options such as
77
+ `--layout=reverse`, `--info=inline`, `--border`, `--margin`, etc.
78
+
79
+ ```sh
80
+ fzf --height=40% --layout=reverse
81
+ fzf --height=40% --layout=reverse --info=inline
82
+ fzf --height=40% --layout=reverse --info=inline --border
83
+ fzf --height=40% --layout=reverse --info=inline --border --margin=1
84
+ fzf --height=40% --layout=reverse --info=inline --border --margin=1 --padding=1
85
+ ```
86
+
87
+ ![image](https://user-images.githubusercontent.com/700826/113379932-dfeac200-93b5-11eb-9e28-df1a2ee71f90.png)
88
+
89
+ *(See `Layout` section of the man page to see the full list of options)*
90
+
91
+ But you definitely don't want to repeat `--height=40% --layout=reverse
92
+ --info=inline --border --margin=1 --padding=1` every time you use fzf. You
93
+ could write a wrapper script or shell alias, but there is an easier option.
94
+ Define `$FZF_DEFAULT_OPTS` like so:
95
+
96
+ ```sh
97
+ export FZF_DEFAULT_OPTS="--height=40% --layout=reverse --info=inline --border --margin=1 --padding=1"
98
+ ```
99
+
100
+ ### `fzf-tmux`
101
+
102
+ Before fzf had `--height` option, we would open fzf in a tmux split pane not
103
+ to take up the whole screen. This is done using `fzf-tmux` script.
104
+
105
+ ```sh
106
+ # Open fzf on a tmux split pane below the current pane.
107
+ # Takes the same set of options.
108
+ fzf-tmux --layout=reverse
109
+ ```
110
+
111
+ ![image](https://user-images.githubusercontent.com/700826/113379973-f1cc6500-93b5-11eb-8860-c9bc4498aadf.png)
112
+
113
+ The limitation of `fzf-tmux` is that it only works when you're on tmux unlike
114
+ `--height` option. But the advantage of it is that it's more flexible.
115
+ (See `man fzf-tmux` for available options.)
116
+
117
+ ```sh
118
+ # On the right (50%)
119
+ fzf-tmux -r
120
+
121
+ # On the left (30%)
122
+ fzf-tmux -l30%
123
+
124
+ # Above the cursor
125
+ fzf-tmux -u30%
126
+ ```
127
+
128
+ ![image](https://user-images.githubusercontent.com/700826/113379983-fa24a000-93b5-11eb-93eb-8a3d39b2f163.png)
129
+
130
+ ![image](https://user-images.githubusercontent.com/700826/113380001-0577cb80-93b6-11eb-95d0-2ba453866882.png)
131
+
132
+ ![image](https://user-images.githubusercontent.com/700826/113380040-1d4f4f80-93b6-11eb-9bef-737fb120aafe.png)
133
+
134
+ #### Popup window support
135
+
136
+ But here's the really cool part; tmux 3.2 added support for popup windows. So
137
+ you can open fzf in a popup window, which is quite useful if you frequently
138
+ use split panes.
139
+
140
+ ```sh
141
+ # Open tmux in a tmux popup window (default size: 50% of the screen)
142
+ fzf-tmux -p
143
+
144
+ # 80% width, 60% height
145
+ fzf-tmux -p 80%,60%
146
+ ```
147
+
148
+ ![image](https://user-images.githubusercontent.com/700826/113380106-4a9bfd80-93b6-11eb-8cee-aeb1c4ce1a1f.png)
149
+
150
+ > You might also want to check out my tmux plugins which support this popup
151
+ > window layout.
152
+ >
153
+ > - https://github.com/junegunn/tmux-fzf-url
154
+ > - https://github.com/junegunn/tmux-fzf-maccy
155
+
156
+ Dynamic reloading of the list
157
+ -----------------------------
158
+
159
+ fzf can dynamically update the candidate list using an arbitrary program with
160
+ `reload` bindings (The design document for `reload` can be found
161
+ [here][reload]).
162
+
163
+ [reload]: https://github.com/junegunn/fzf/issues/1750
164
+
165
+ ### Updating the list of processes by pressing CTRL-R
166
+
167
+ This example shows how you can set up a binding for dynamically updating the
168
+ list without restarting fzf.
169
+
170
+ ```sh
171
+ (date; ps -ef) |
172
+ fzf --bind='ctrl-r:reload(date; ps -ef)' \
173
+ --header=$'Press CTRL-R to reload\n\n' --header-lines=2 \
174
+ --preview='echo {}' --preview-window=down,3,wrap \
175
+ --layout=reverse --height=80% | awk '{print $2}' | xargs kill -9
176
+ ```
177
+
178
+ ![image](https://user-images.githubusercontent.com/700826/113465047-200c7c00-946c-11eb-918c-268f37a900c8.png)
179
+
180
+ - The initial command is `(date; ps -ef)`. It prints the current date and
181
+ time, and the list of the processes.
182
+ - With `--header` option, you can show any message as the fixed header.
183
+ - To disallow selecting the first two lines (`date` and `ps` header), we use
184
+ `--header-lines=2` option.
185
+ - `--bind='ctrl-r:reload(date; ps -ef)'` binds CTRL-R to `reload` action that
186
+ runs `date; ps -ef`, so we can update the list of the processes by pressing
187
+ CTRL-R.
188
+ - We use simple `echo {}` preview option, so we can see the entire line on the
189
+ preview window below even if it's too long
190
+
191
+ ### Toggling between data sources
192
+
193
+ You're not limited to just one reload binding. Set up multiple bindings so
194
+ you can switch between data sources.
195
+
196
+ ```sh
197
+ find * | fzf --prompt 'All> ' \
198
+ --header 'CTRL-D: Directories / CTRL-F: Files' \
199
+ --bind 'ctrl-d:change-prompt(Directories> )+reload(find * -type d)' \
200
+ --bind 'ctrl-f:change-prompt(Files> )+reload(find * -type f)'
201
+ ```
202
+
203
+ ![image](https://user-images.githubusercontent.com/700826/113465073-4af6d000-946c-11eb-858f-2372c0955f67.png)
204
+
205
+ ![image](https://user-images.githubusercontent.com/700826/113465072-46321c00-946c-11eb-9b6f-cda3951df579.png)
206
+
207
+ Ripgrep integration
208
+ -------------------
209
+
210
+ ### Using fzf as the secondary filter
211
+
212
+ * Requires [bat][bat]
213
+ * Requires [Ripgrep][rg]
214
+
215
+ [bat]: https://github.com/sharkdp/bat
216
+ [rg]: https://github.com/BurntSushi/ripgrep
217
+
218
+ fzf is pretty fast for filtering a list that you will rarely have to think
219
+ about its performance. But it is not the right tool for searching for text
220
+ inside many large files, and in that case you should definitely use something
221
+ like [Ripgrep][rg].
222
+
223
+ In the next example, Ripgrep is the primary filter that searches for the given
224
+ text in files, and fzf is used as the secondary fuzzy filter that adds
225
+ interactivity to the workflow. And we use [bat][bat] to show the matching line in
226
+ the preview window.
227
+
228
+ This is a bash script and it will not run as expected on other non-compliant
229
+ shells. To avoid the compatibility issue, let's save this snippet as a script
230
+ file called `rfv`.
231
+
232
+ ```bash
233
+ #!/usr/bin/env bash
234
+
235
+ # 1. Search for text in files using Ripgrep
236
+ # 2. Interactively narrow down the list using fzf
237
+ # 3. Open the file in Vim
238
+ IFS=: read -ra selected < <(
239
+ rg --color=always --line-number --no-heading --smart-case "${*:-}" |
240
+ fzf --ansi \
241
+ --color "hl:-1:underline,hl+:-1:underline:reverse" \
242
+ --delimiter : \
243
+ --preview 'bat --color=always {1} --highlight-line {2}' \
244
+ --preview-window 'up,60%,border-bottom,+{2}+3/3,~3'
245
+ )
246
+ [ -n "${selected[0]}" ] && vim "${selected[0]}" "+${selected[1]}"
247
+ ```
248
+
249
+ And run it with an initial query string.
250
+
251
+ ```sh
252
+ # Make the script executable
253
+ chmod +x rfv
254
+
255
+ # Run it with the initial query "algo"
256
+ ./rfv algo
257
+ ```
258
+
259
+ > Ripgrep will perform the initial search and list all the lines that contain
260
+ `algo`. Then we further narrow down the list on fzf.
261
+
262
+ ![image](https://user-images.githubusercontent.com/700826/113683873-a42a6200-96ff-11eb-9666-26ce4091b0e4.png)
263
+
264
+ I know it's a lot to digest, let's try to break down the code.
265
+
266
+ - Ripgrep prints the matching lines in the following format
267
+ ```
268
+ man/man1/fzf.1:54:.BI "--algo=" TYPE
269
+ man/man1/fzf.1:55:Fuzzy matching algorithm (default: v2)
270
+ man/man1/fzf.1:58:.BR v2 " Optimal scoring algorithm (quality)"
271
+ src/pattern_test.go:7: "github.com/junegunn/fzf/src/algo"
272
+ ```
273
+ The first token delimited by `:` is the file path, and the second token is
274
+ the line number of the matching line. They respectively correspond to `{1}`
275
+ and `{2}` in the preview command.
276
+ - `--preview 'bat --color=always {1} --highlight-line {2}'`
277
+ - As we run `rg` with `--color=always` option, we should tell fzf to parse
278
+ ANSI color codes in the input by setting `--ansi`.
279
+ - We customize how fzf colors various text elements using `--color` option.
280
+ `-1` tells fzf to keep the original color from the input. See `man fzf` for
281
+ available color options.
282
+ - The value of `--preview-window` option consists of 5 components delimited
283
+ by `,`
284
+ 1. `up` — Position of the preview window
285
+ 1. `60%` — Size of the preview window
286
+ 1. `border-bottom` — Preview window border only on the bottom side
287
+ 1. `+{2}+3/3` — Scroll offset of the preview contents
288
+ 1. `~3` — Fixed header
289
+ - Let's break down the latter two. We want to display the bat output in the
290
+ preview window with a certain scroll offset so that the matching line is
291
+ positioned near the center of the preview window.
292
+ - `+{2}` — The base offset is extracted from the second token
293
+ - `+3` — We add 3 lines to the base offset to compensate for the header
294
+ part of `bat` output
295
+ - ```
296
+ ───────┬──────────────────────────────────────────────────────────
297
+ │ File: CHANGELOG.md
298
+ ───────┼──────────────────────────────────────────────────────────
299
+ 1 │ CHANGELOG
300
+ 2 │ =========
301
+ 3 │
302
+ 4 │ 0.26.0
303
+ 5 │ ------
304
+ ```
305
+ - `/3` adjusts the offset so that the matching line is shown at a third
306
+ position in the window
307
+ - `~3` makes the top three lines fixed header so that they are always
308
+ visible regardless of the scroll offset
309
+ - Once we selected a line, we open the file with `vim` (`vim
310
+ "${selected[0]}"`) and move the cursor to the line (`+${selected[1]}`).
311
+
312
+ ### Using fzf as interative Ripgrep launcher
313
+
314
+ We have learned that we can bind `reload` action to a key (e.g.
315
+ `--bind=ctrl-r:execute(ps -ef)`). In the next example, we are going to **bind
316
+ `reload` action to `change` event** so that whenever the user *changes* the
317
+ query string on fzf, `reload` action is triggered.
318
+
319
+ Here is a variation of the above `rfv` script. fzf will restart Ripgrep every
320
+ time the user updates the query string on fzf. Searching and filtering is
321
+ completely done by Ripgrep, and fzf merely provides the interactive interface.
322
+ So we lose the "fuzziness", but the performance will be better on larger
323
+ projects, and it will free up memory as you narrow down the results.
324
+
325
+ ```bash
326
+ #!/usr/bin/env bash
327
+
328
+ # 1. Search for text in files using Ripgrep
329
+ # 2. Interactively restart Ripgrep with reload action
330
+ # 3. Open the file in Vim
331
+ RG_PREFIX="rg --column --line-number --no-heading --color=always --smart-case "
332
+ INITIAL_QUERY="${*:-}"
333
+ IFS=: read -ra selected < <(
334
+ FZF_DEFAULT_COMMAND="$RG_PREFIX $(printf %q "$INITIAL_QUERY")" \
335
+ fzf --ansi \
336
+ --disabled --query "$INITIAL_QUERY" \
337
+ --bind "change:reload:sleep 0.1; $RG_PREFIX {q} || true" \
338
+ --delimiter : \
339
+ --preview 'bat --color=always {1} --highlight-line {2}' \
340
+ --preview-window 'up,60%,border-bottom,+{2}+3/3,~3'
341
+ )
342
+ [ -n "${selected[0]}" ] && vim "${selected[0]}" "+${selected[1]}"
343
+ ```
344
+
345
+ ![image](https://user-images.githubusercontent.com/700826/113684212-f9ff0a00-96ff-11eb-8737-7bb571d320cc.png)
346
+
347
+ - Instead of starting fzf in `rg ... | fzf` form, we start fzf without an
348
+ explicit input, but with a custom `FZF_DEFAULT_COMMAND` variable. This way
349
+ fzf can kill the initial Ripgrep process it starts with the initial query.
350
+ Otherwise, the initial Ripgrep process will keep consuming system resources
351
+ even after `reload` is triggered.
352
+ - Filtering is no longer a responsibility of fzf; hence `--disabled`
353
+ - `{q}` in the reload command evaluates to the query string on fzf prompt.
354
+ - `sleep 0.1` in the reload command is for "debouncing". This small delay will
355
+ reduce the number of intermediate Ripgrep processes while we're typing in
356
+ a query.
357
+
358
+ ### Switching to fzf-only search mode
359
+
360
+ *(Requires fzf 0.27.1 or above)*
361
+
362
+ In the previous example, we lost fuzzy matching capability as we completely
363
+ delegated search functionality to Ripgrep. But we can dynamically switch to
364
+ fzf-only search mode by *"unbinding"* `reload` action from `change` event.
365
+
366
+ ```sh
367
+ #!/usr/bin/env bash
368
+
369
+ # Two-phase filtering with Ripgrep and fzf
370
+ #
371
+ # 1. Search for text in files using Ripgrep
372
+ # 2. Interactively restart Ripgrep with reload action
373
+ # * Press alt-enter to switch to fzf-only filtering
374
+ # 3. Open the file in Vim
375
+ RG_PREFIX="rg --column --line-number --no-heading --color=always --smart-case "
376
+ INITIAL_QUERY="${*:-}"
377
+ IFS=: read -ra selected < <(
378
+ FZF_DEFAULT_COMMAND="$RG_PREFIX $(printf %q "$INITIAL_QUERY")" \
379
+ fzf --ansi \
380
+ --color "hl:-1:underline,hl+:-1:underline:reverse" \
381
+ --disabled --query "$INITIAL_QUERY" \
382
+ --bind "change:reload:sleep 0.1; $RG_PREFIX {q} || true" \
383
+ --bind "alt-enter:unbind(change,alt-enter)+change-prompt(2. fzf> )+enable-search+clear-query" \
384
+ --prompt '1. ripgrep> ' \
385
+ --delimiter : \
386
+ --preview 'bat --color=always {1} --highlight-line {2}' \
387
+ --preview-window 'up,60%,border-bottom,+{2}+3/3,~3'
388
+ )
389
+ [ -n "${selected[0]}" ] && vim "${selected[0]}" "+${selected[1]}"
390
+ ```
391
+
392
+ * Phase 1. Filtering with Ripgrep
393
+ ![image](https://user-images.githubusercontent.com/700826/119213880-735e8a80-bafd-11eb-8493-123e4be24fbc.png)
394
+ * Phase 2. Filtering with fzf
395
+ ![image](https://user-images.githubusercontent.com/700826/119213887-7e191f80-bafd-11eb-98c9-71a1af9d7aab.png)
396
+
397
+ - We added `--prompt` option to show that fzf is initially running in "Ripgrep
398
+ launcher mode".
399
+ - We added `alt-enter` binding that
400
+ 1. unbinds `change` event, so Ripgrep is no longer restarted on key press
401
+ 2. changes the prompt to `2. fzf>`
402
+ 3. enables search functionality of fzf
403
+ 4. clears the current query string that was used to start Ripgrep process
404
+ 5. and unbinds `alt-enter` itself as this is a one-off event
405
+ - We reverted `--color` option for customizing how the matching chunks are
406
+ displayed in the second phase
407
+
408
+ Log tailing
409
+ -----------
410
+
411
+ fzf can run long-running preview commands and render partial results before
412
+ completion. And when you specify `follow` flag in `--preview-window` option,
413
+ fzf will "`tail -f`" the result, automatically scrolling to the bottom.
414
+
415
+ ```bash
416
+ # With "follow", preview window will automatically scroll to the bottom.
417
+ # "\033[2J" is an ANSI escape sequence for clearing the screen.
418
+ # When fzf reads this code it clears the previous preview contents.
419
+ fzf --preview-window follow --preview 'for i in $(seq 100000); do
420
+ echo "$i"
421
+ sleep 0.01
422
+ (( i % 300 == 0 )) && printf "\033[2J"
423
+ done'
424
+ ```
425
+
426
+ ![image](https://user-images.githubusercontent.com/700826/113473303-dd669600-94a3-11eb-88a9-1f61b996bb0e.png)
427
+
428
+ Admittedly, that was a silly example. Here's a practical one for browsing
429
+ Kubernetes pods.
430
+
431
+ ```bash
432
+ #!/usr/bin/env bash
433
+
434
+ read -ra tokens < <(
435
+ kubectl get pods --all-namespaces |
436
+ fzf --info=inline --layout=reverse --header-lines=1 --border \
437
+ --prompt "$(kubectl config current-context | sed 's/-context$//')> " \
438
+ --header $'Press CTRL-O to open log in editor\n\n' \
439
+ --bind ctrl-/:toggle-preview \
440
+ --bind 'ctrl-o:execute:${EDITOR:-vim} <(kubectl logs --namespace {1} {2}) > /dev/tty' \
441
+ --preview-window up,follow \
442
+ --preview 'kubectl logs --follow --tail=100000 --namespace {1} {2}' "$@"
443
+ )
444
+ [ ${#tokens} -gt 1 ] &&
445
+ kubectl exec -it --namespace "${tokens[0]}" "${tokens[1]}" -- bash
446
+ ```
447
+
448
+ ![image](https://user-images.githubusercontent.com/700826/113473547-1d7a4880-94a5-11eb-98ef-9aa6f0ed215a.png)
449
+
450
+ - The preview window will *"log tail"* the pod
451
+ - Holding on to a large amount of log will consume a lot of memory. So we
452
+ limited the initial log amount with `--tail=100000`.
453
+ - With `execute` binding, you can press CTRL-O to open the log in your editor
454
+ without leaving fzf
455
+ - Select a pod (with an enter key) to `kubectl exec` into it
456
+
457
+ Key bindings for git objects
458
+ ----------------------------
459
+
460
+ I have [blogged](https://junegunn.kr/2016/07/fzf-git) about my fzf+git key
461
+ bindings a few years ago. I'm going to show them here again, because they are
462
+ seriously useful.
463
+
464
+ ### Files listed in `git status`
465
+
466
+ <kbd>CTRL-G</kbd><kbd>CTRL-F</kbd>
467
+
468
+ ![image](https://user-images.githubusercontent.com/700826/113473779-a9d93b00-94a6-11eb-87b5-f62a8d0a0efc.png)
469
+
470
+ ### Branches
471
+
472
+ <kbd>CTRL-G</kbd><kbd>CTRL-B</kbd>
473
+
474
+ ![image](https://user-images.githubusercontent.com/700826/113473758-87dfb880-94a6-11eb-82f4-9218103f10bd.png)
475
+
476
+ ### Commit hashes
477
+
478
+ <kbd>CTRL-G</kbd><kbd>CTRL-H</kbd>
479
+
480
+ ![image](https://user-images.githubusercontent.com/700826/113473765-91692080-94a6-11eb-8d38-ed4d41f27ac1.png)
481
+
482
+
483
+ The full source code can be found [here](https://gist.github.com/junegunn/8b572b8d4b5eddd8b85e5f4d40f17236).
484
+
485
+ Color themes
486
+ ------------
487
+
488
+ You can customize how fzf colors the text elements with `--color` option. Here
489
+ are a few color themes. Note that you need a terminal emulator that can
490
+ display 24-bit colors.
491
+
492
+ ```sh
493
+ # junegunn/seoul256.vim (dark)
494
+ 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'
495
+ ```
496
+
497
+ ![seoul256](https://user-images.githubusercontent.com/700826/113475011-2c192d80-94ae-11eb-9d17-1e5867bae01f.png)
498
+
499
+ ```sh
500
+ # junegunn/seoul256.vim (light)
501
+ 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'
502
+ ```
503
+
504
+ ![seoul256-light](https://user-images.githubusercontent.com/700826/113475022-389d8600-94ae-11eb-905f-0939dd535837.png)
505
+
506
+ ```sh
507
+ # morhetz/gruvbox
508
+ 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'
509
+ ```
510
+
511
+ ![gruvbox](https://user-images.githubusercontent.com/700826/113475042-494dfc00-94ae-11eb-9322-cd03a027305a.png)
512
+
513
+ ```sh
514
+ # arcticicestudio/nord-vim
515
+ 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'
516
+ ```
517
+
518
+ ![nord](https://user-images.githubusercontent.com/700826/113475063-67b3f780-94ae-11eb-9b24-5f0d22b63399.png)
519
+
520
+ ```sh
521
+ # tomasr/molokai
522
+ 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'
523
+ ```
524
+
525
+ ![molokai](https://user-images.githubusercontent.com/700826/113475085-8619f300-94ae-11eb-85e4-2766fc3246bf.png)
526
+
527
+ ### Generating fzf color theme from Vim color schemes
528
+
529
+ The Vim plugin of fzf can generate `--color` option from the current color
530
+ scheme according to `g:fzf_colors` variable. You can find the detailed
531
+ explanation [here](https://github.com/junegunn/fzf/blob/master/README-VIM.md#explanation-of-gfzf_colors).
532
+
533
+ Here is an example. Add this to your Vim configuration file.
534
+
535
+ ```vim
536
+ let g:fzf_colors =
537
+ \ { 'fg': ['fg', 'Normal'],
538
+ \ 'bg': ['bg', 'Normal'],
539
+ \ 'preview-bg': ['bg', 'NormalFloat'],
540
+ \ 'hl': ['fg', 'Comment'],
541
+ \ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
542
+ \ 'bg+': ['bg', 'CursorLine', 'CursorColumn'],
543
+ \ 'hl+': ['fg', 'Statement'],
544
+ \ 'info': ['fg', 'PreProc'],
545
+ \ 'border': ['fg', 'Ignore'],
546
+ \ 'prompt': ['fg', 'Conditional'],
547
+ \ 'pointer': ['fg', 'Exception'],
548
+ \ 'marker': ['fg', 'Keyword'],
549
+ \ 'spinner': ['fg', 'Label'],
550
+ \ 'header': ['fg', 'Comment'] }
551
+ ```
552
+
553
+ Then you can see how the `--color` option is generated by printing the result
554
+ of `fzf#wrap()`.
555
+
556
+ ```vim
557
+ :echo fzf#wrap()
558
+ ```
559
+
560
+ Use this command to append `export FZF_DEFAULT_OPTS="..."` line to the end of
561
+ the current file.
562
+
563
+ ```vim
564
+ :call append('$', printf('export FZF_DEFAULT_OPTS="%s"', matchstr(fzf#wrap().options, "--color[^']*")))
565
+ ```
@@ -0,0 +1,49 @@
1
+ Building fzf
2
+ ============
3
+
4
+ Build instructions
5
+ ------------------
6
+
7
+ ### Prerequisites
8
+
9
+ - Go 1.13 or above
10
+
11
+ ### Using Makefile
12
+
13
+ ```sh
14
+ # Build fzf binary for your platform in target
15
+ make
16
+
17
+ # Build fzf binary and copy it to bin directory
18
+ make install
19
+
20
+ # Build fzf binaries and archives for all platforms using goreleaser
21
+ make build
22
+
23
+ # Publish GitHub release
24
+ make release
25
+ ```
26
+
27
+ > :warning: Makefile uses git commands to determine the version and the
28
+ > revision information for `fzf --version`. So if you're building fzf from an
29
+ > environment where its git information is not available, you have to manually
30
+ > set `$FZF_VERSION` and `$FZF_REVISION`.
31
+ >
32
+ > e.g. `FZF_VERSION=0.24.0 FZF_REVISION=tarball make`
33
+
34
+ Third-party libraries used
35
+ --------------------------
36
+
37
+ - [mattn/go-runewidth](https://github.com/mattn/go-runewidth)
38
+ - Licensed under [MIT](http://mattn.mit-license.org)
39
+ - [mattn/go-shellwords](https://github.com/mattn/go-shellwords)
40
+ - Licensed under [MIT](http://mattn.mit-license.org)
41
+ - [mattn/go-isatty](https://github.com/mattn/go-isatty)
42
+ - Licensed under [MIT](http://mattn.mit-license.org)
43
+ - [tcell](https://github.com/gdamore/tcell)
44
+ - Licensed under [Apache License 2.0](https://github.com/gdamore/tcell/blob/master/LICENSE)
45
+
46
+ License
47
+ -------
48
+
49
+ [MIT](LICENSE)