Belajar Fzf - Custom Keybindings & Actions
Series/Belajar Fzf/Episode 15
Episode 15 of 23

Belajar Fzf - Custom Keybindings & Actions

Menghubungkan tombol dan event ke aksi-aksi fzf seperti accept, execute, execute-silent, become, reload, change-preview-window, select-all, dan toggle+ lewat --bind. Termasuk multi-action dengan tanda plus, binding kondisional per event, --expect untuk menangkap tombol terakhir, --no-clear, dan use case nyata: membuka editor, git add, hingga membunuh proses.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Pendahuluan

Di episode 14 kalian belajar memperlakukan item fzf sebagai data yang tidak boleh dieksekusi sembarangan. Sekarang giliran kebalikannya: kalian akan sengaja mengikat data itu pada aksi. --bind adalah jantung fzf yang sesungguhnya — ia mengubah alat pencari menjadi antarmuka tempat kalian memilih, lalu menjalankan sesuatu tanpa pernah menyentuh keyboard untuk mengetik perintah utuh.

Episode ini membahas anatomi --bind, aksi-aksi inti (accept, execute, execute-silent, become, reload, change-preview-window, preview-top, select-all, toggle+), cara merangkai beberapa aksi sekaligus dengan tanda +, binding kondisional per event, --expect untuk menangkap tombol terakhir yang ditekan, --no-clear, dan tiga use case nyata: membuka editor, git add, serta membunuh proses.

Bayangkan --bind seperti papan tombol di kokpit: tombol yang sama bisa memicu satu gerakan, dan rangkaian tombol bisa diprogram untuk memicu urutan gerakan. Semua dimulai dari satu kalimat kecil.

Anatomi --bind

--bind menerima daftar ekspresi KEY:ACTION yang dipisahkan koma. Pemicunya tidak hanya tombol fisik — ada juga event yang dipicu oleh kondisi fzf sendiri, seperti start (saat fzf mulai), load (saat daftar selesai dimuat), change (saat query berubah), focus (saat kursor berpindah item), hingga one dan zero (saat hasil menyisakan satu atau nol item).

Struktur dasar --bind
fzf --bind 'ctrl-j:down,ctrl-k:up'
fzf --bind 'ctrl-r:reload(ls -la)'
fzf --bind 'change:reload(rg -l {q})'
Tombol dan event sama-sama bisa menjadi pemicu aksi

Action untuk Mengakhiri: accept

accept adalah aksi paling dasar: menerima pilihan saat ini dan keluar dari fzf — inilah yang diikat ke tombol Enter secara default. Ia layak disebut pertama karena hampir semua aksi lain dirancang untuk mengantarkan kalian ke sini. Saudaranya, accept-non-empty, mencegah fzf keluar tanpa pilihan — berguna ketika membatalkan jauh lebih baik daripada menerima hasil kosong.

Enter hanya menerima bila ada pilihan
fzf --bind 'enter:accept-non-empty'
accept-non-empty tidak keluar saat daftar kosong

Mengeksekusi: execute, execute-silent, become

Inilah tiga aksi yang mengubah fzf dari daftar menjadi pelaksana perintah. Ketiganya mengganti {} dengan item yang sedang disorot:

  • execute(perintah) — menjalankan perintah, menampilkan output di layar, lalu kembali ke fzf.
  • execute-silent(perintah) — sama, tetapi output tidak ditampilkan; cocok untuk aksi yang suksesnya tidak perlu dilihat.
  • become(perintah) — menjalankan perintah dan menggantikan fzf sepenuhnya: proses fzf selesai, diganti proses baru.
execute: lihat lalu kembali
fzf --bind 'enter:execute(less {})'
Menampilkan file, kembali ke daftar setelah keluar
become: fzf berubah menjadi editor
fzf --bind 'enter:become(vim {})'
fzf digantikan vim; tidak ada jalan kembali ke daftar

Tip

Pilih execute ketika kalian ingin kembali ke daftar setelah selesai (misalnya menilik file), dan become ketika kalian ingin fzf menjadi program itu (misalnya membuka editor pada file terpilih). execute-silent untuk aksi yang tidak ingin menampilkan apa pun — panggilan git add atau kill adalah kandidat ideal.

Memuat Ulang Daftar: reload

reload(perintah) mengganti daftar item yang sedang ditampilkan dengan output perintah baru, tanpa keluar dari fzf. Ini adalah fondasi daftar yang hidup — kita akan membedahnya lebih dalam di episode 16, tetapi satu contoh singkat di sini: memuat ulang daftar proses dengan menekan satu tombol.

Reload daftar saat tombol ditekan
ps -ef | fzf --bind 'ctrl-r:reload(ps -ef)'
ps -ef dijalankan ulang, daftar diperbarui di tempat

Preview Dinamis: change-preview-window dan preview-top

Kadang preview tidak harus selalu di sisi kanan. change-preview-window(...) memindahkan dan mengubah ukuran preview saat itu juga, dan dengan beberapa set yang dipisahkan |, satu tombol bisa memutar posisinya. preview-top menggulung preview ke bagian paling atas — tepat ketika file yang sedang dilihat panjang dan kalian ingin kembali ke awal tanpa scroll manual.

Putar posisi preview
fzf --preview 'bat --color=always {}' \
    --bind 'ctrl-/:change-preview-window(right|down|hidden)'
ctrl-/ bergantian: kanan, bawah, lalu tersembunyi
Lompat ke atas preview
fzf --preview 'bat --color=always {}' --bind 'alt-t:preview-top'
alt-t menggulung preview kembali ke baris pertama

Seleksi Massal: select-all dan toggle+

Aksi-aksi ini mengisi sisi lain: memperlakukan banyak item sekaligus. select-all menandai seluruh hasil filter yang ada — bukan hanya yang terlihat di layar. toggle+ (nama lengkapnya toggle+down, yang diikat ke Tab secara default) menandai item aktif lalu bergerak ke bawah — memberi rasa "tandai satu demi satu ke bawah".

Tandai semua lalu terima
seq 20 | fzf --multi --bind 'ctrl-a:select-all+accept'
Dua aksi dirangkai: select-all diikuti accept

--expect: Menangkap Tombol Terakhir

Biasanya fzf hanya memberitahu item apa yang dipilih, bukan tombol apa yang menutupnya. --expect=TOMbol mengubah itu: tombol yang disebut ikut "dicatat", dan fzf mencetaknya sebagai baris pertama output, diikuti pilihan pada baris berikutnya.

Menangkap tombol terakhir
printf '%s\n' edit.pdf report.pdf | fzf --expect=ctrl-o
Output baris pertama adalah tombol yang menutup fzf

Outputnya kurang lebih seperti ini:

Contoh output --expect
ctrl-o
edit.pdf

Script pembacanya kemudian memeriksa baris pertama untuk memutuskan tindakan — semacam protokol tangan antara fzf dan script:

Script membaca tombol dan pilihan
read -r key < <(printf '%s\n' edit.pdf report.pdf | fzf --expect=ctrl-o)
read -r item
case "$key" in
    ctrl-o) open "$item" ;;
    *)      echo "dibatalkan: $item" ;;
esac

--no-clear: Meninggalkan Jejak di Layar

Secara default fzf membersihkan antarmukanya ketika selesai — layar kembali seperti sebelum fzf muncul. --no-clear menonaktifkan itu: hasil terakhir tetap terlihat setelah keluar. Kegunaan utamanya adalah mengurangi kedipan layar ketika sebuah aplikasi memanggil fzf beberapa kali berturut-turut, atau ketika kalian memang ingin hasil pencarian tetap terbaca setelah memilih.

Hasil tetap terlihat setelah keluar
foo=$(seq 100 | fzf --no-clear)
--no-clear tidak mengembalikan layar penuh sebelumnya

Warning

--no-clear membuat isi layar terakhir tetap menempel — termasuk isi preview. Bila preview menampilkan data sensitif (ingat episode 14), jejak itu bisa terbaca oleh orang yang datang kemudian. Gunakan --no-clear untuk workflow yang memang butuh, dan sadari bahwa ia adalah pengingat visual yang tidak sengaja menjadi jejak data.

Multi-Action dan Binding Kondisional

Dua tombol ajaib memperluas --bind: + merangkai beberapa aksi dalam satu ekspresi, dan event membuat binding berjalan kondisional. Rangkaian dijalankan berurutan dari kiri ke kanan:

Rangkaian aksi dengan tanda plus
git ls-files -m -o --exclude-standard | fzf --multi \
    --bind 'ctrl-a:select-all' \
    --bind 'enter:execute-silent(git add {+})+reload(git ls-files -m -o --exclude-standard)'
execute-silent lalu reload, dalam satu tekanan tombol

Untuk mengubah perilaku kunci secara dinamis — semacam "mode" — fzf menyediakan toggle-bind(KEY): tombol yang dijadikan argumen akan dihidupkan dan dimatikan bergantian. Gabungkan dengan binding event, dan kalian bisa mematikan reload saat tidak dibutuhkan:

Mematikan binding dengan toggle-bind
fzf --bind 'alt-b:toggle-bind(ctrl-r)' \
    --bind 'ctrl-r:reload(ps -ef)' \
    --bind 'change:reload(ps -ef)'
alt-b menghidupkan dan mematikan tombol ctrl-r

Dengan alt-b, kalian bisa menonaktifkan reload otomatis saat melihat daftar yang sedang tenang, lalu menyalakannya kembali. Event change, focus, one, dan zero memberi dimensi kondisional yang sama untuk aksi yang hanya perlu terjadi dalam keadaan tertentu.

Use Case Nyata

Akhirnya, tiga alur kerja yang langsung terasa di meja kerja sehari-hari:

Buka editor pada file terpilih — fzf digantikan editor, {} menjadi argumennya:

Buka file di editor
fzf --bind 'enter:become($EDITOR {})'

git add tanpa meninggalkan fzf — tandai banyak file, tambahkan ke staging, daftar dimuat ulang:

git add massal dengan reload
git ls-files -m -o --exclude-standard | fzf --multi \
    --bind 'ctrl-a:select-all' \
    --bind 'enter:execute-silent(git add {+})+reload(git ls-files -m -o --exclude-standard)'

Bunuh proses terpilih — PID diambil dari field pertama ({1}), aksi berjalan tanpa menampilkan apa pun:

Kill proses dari daftar ps
ps -eo pid,comm | fzf --bind 'enter:execute-silent(kill {1})'

Kesalahan Umum

KesalahanGejalaSolusi
Lupa mengutip {} di aksiInjection atau perintah keliruKutip placeholder seperti di episode 14
Memakai execute padahal ingin becomeSelalu kembali ke daftarbecome untuk menggantikan proses fzf
Menaruh + di awal rangkaianError parseRangkaian dimulai dari aksi pertama setelah :
--expect diabaikanTidak ada baris tombol di output--expect menambahkan baris pertama; baca dengan read berurutan
Reload di change terlalu agresifDaftar berkedip tiap ketikanBatasi dengan sleep di dalam perintah reload
{+} pada nama file ber-spasiArgumen terpecahGunakan {+f} atau pembatas null sesuai konteks

Caution

Rangkaian + dieksekusi berurutan, dan aksi yang mengakhiri proses fzf (accept, become, abort) menghentikan sisa rangkaian. Urutkan dengan sengaja: taruh aksi yang harus selesai sebelum fzf menutup di depan, dan aksi penutup di paling belakang.

Penutup

Pada episode 15 ini kalian mengambil kendali penuh atas tombol dan aksi fzf: anatomi --bind dengan tombol maupun event sebagai pemicu; aksi inti accept, execute, execute-silent, become, reload, change-preview-window, preview-top, select-all, dan toggle+; perangkaian beberapa aksi dengan +; binding kondisional lewat event dan toggle-bind; --expect yang menjadikan tombol terakhir sebagai data; --no-clear; serta tiga use case nyata dari membuka editor, git add massal, hingga membunuh proses.

Pesan yang harus dibawa pulang: --bind mengubah fzf dari alat memilih menjadi alat bertindak — daftar, pilih, lalu eksekusi, semua dalam satu gerakan.

Namun sejauh ini aksi reload baru kalian sentuh sekilas. Bagaimana jika daftar yang dimuat ulang bukan sekadar refresh, melainkan aliran data yang terus berubah, dikendalikan bahkan oleh proses di luar fzf? Di episode 16 kita membuka babak baru: dynamic reload & HTTP API — daftar yang hidup lewat --reload, --change, dan penjadwalan berkala, pelacakan lintas reload dengan --track dan --id-nth, serta kendali penuh fzf dari program lain lewat --listen.

Belajar Fzf - Custom Keybindings & Actions | Belajar Fzf