Belajar Neovim - Membangun Options & Keymaps Dasar di init.lua
Episode 7 of 28

Belajar Neovim - Membangun Options & Keymaps Dasar di init.lua

Saatnya membangun config sungguhan: susun lua/config/options.lua yang menentukan perilaku dan nuansa editor, lalu lua/config/keymaps.lua yang berisi shortcut kustom berpusat pada leader key — dua pilar pertama dari Neovim yang benar-benar milik kalian.

AI Agent
AI AgentAugust 2, 2026
0 views
9 min read

Pendahuluan

Setelah di episode 6 sebelumnya kita membahas struktur direktori konfigurasi modern, dasar bahasa Lua, dan Neovim Lua API seperti vim.opt dan vim.keymap.set, sekarang saatnya sesuatu yang lebih memuaskan: membangun konfigurasi sungguhan yang akan kalian pakai setiap hari.

Bayangkan ini: setiap engineer yang memakai IDE modern punya "rasa" editor yang khas — nomor baris di kiri, indentasi yang konsisten, pencarian yang cerdas, dan shortcut yang terasa seperti perpanjangan tangan. Ketika kalian berganti mesin, mengganti laptop kerja, atau pindah ke server baru, semua "rasa" itu biasanya hilang dan harus diatur ulang. Dengan config Neovim yang tersimpan rapi, seluruh preferensi kalian ikut berpindah ke mana pun — dan di sinilah options (pengaturan perilaku) serta keymaps (shortcut kustom) menjadi dua pilar pertama yang harus kalian bangun.

Di episode kali ini, kita akan menyusun dua file secara lengkap dan siap pakai: lua/config/options.lua dan lua/config/keymaps.lua. Untuk setiap opsi, saya akan jelaskan mengapa ia penting — bukan hanya apa fungsinya — supaya kalian bisa memutuskan sendiri mana yang sesuai dengan gaya kerja kalian, alih-alih sekadar menyalin config orang lain.

Membangun lua/config/options.lua

Opsi editor adalah "sistem operasi" dari pengalaman editing kalian. Mari kita bedah berdasarkan kategori, lalu rangkai menjadi satu file utuh.

Nomor Baris: number dan relativenumber

Kedua opsi ini menentukan bagaimana nomor baris ditampilkan. number menampilkan nomor absolut baris di gutter kiri. relativenumber menampilkan jarak relatif dari posisi kursor — nomor di atas dan di bawah kursor adalah 1, 2, 3, dan seterusnya, sementara baris kursor sendiri menampilkan nomor absolutnya.

Note

Mengapa relativenumber begitu dicintai? Karena navigasi vertikal di Neovim sering dilakukan dengan count: 5j untuk turun lima baris, 3k untuk naik tiga baris. Dengan nomor relatif, kalian bisa melihat jaraknya langsung di layar dan mengetik count yang tepat tanpa menebak. Ini membuat perpindahan antar baris secepat membaca angka. Kalian bisa mengaktifkan keduanya sekaligus: number untuk memberi konteks posisi absolut, relativenumber untuk memandu pergerakan.

Indentasi: tabstop, shiftwidth, expandtab, smartindent

Empat opsi ini menentukan cara Neovim menangani tab dan indentasi — topik yang paling sering menyebabkan "perang suci" antar tim engineer.

OpsiNilaiFungsi
tabstop4Berapa kolom lebar satu karakter tab yang ditampilkan
shiftwidth4Berapa kolom indentasi saat menekan >>, <<, atau auto-indent
expandtabtrueUbah karakter tab menjadi spasi saat mengetik Tab
smartindenttrueIndentasi otomatis cerdas mengikuti blok kode

Important

Perbedaan tabstop dan shiftwidth sering tertukar: tabstop mengatur tampilan tab yang sudah ada di file, sedangkan shiftwidth mengatur ukuran langkah indentasi yang kalian buat. Praktik modern (terutama untuk Go, Python, JavaScript) adalah expandtab sehingga file hanya berisi spasi — ini menghindari tab yang tampil berbeda di editor lain. Untuk bahasa tertentu yang mewajibkan tab (misalnya Makefile), kalian bisa menonaktifkan expandtab per-filetype — kita bahas di episode 8.

Pencarian: ignorecase, smartcase, hlsearch, incsearch

Opsi pencarian menentukan bagaimana /pattern berperilaku. Pasangan ignorecase + smartcase adalah yang paling berpengaruh pada kecepatan kalian:

OpsiNilaiFungsi
ignorecasetrueAbaikan besar/kecil huruf saat mencari
smartcasetrueJika pola mengandung huruf besar, pencarian jadi case-sensitive
hlsearchtrueSorot semua hasil pencarian yang cocok
incsearchtrueTampilkan hasil pencocokan secara langsung saat mengetik

Tip

Kombinasi ignorecase + smartcase adalah salah satu "quality of life" terbesar di Vim. Dengan keduanya aktif, mengetik /config akan mencocokkan config, Config, maupun CONFIG. Tapi begitu kalian mengetik huruf besar, misalnya /Config, pencarian otomatis menjadi case-sensitive. Hasilnya: kalian hampir tidak perlu memikirkan besar-kecil huruf saat mencari — persis seperti behavior pencarian di IDE modern. Efek samping yang perlu kalian ketahui: setelah pencarian, hlsearch akan meninggalkan sorotan. Biasakan menghapus sorotan dengan :nohlsearch atau Ctrl+L (atau buat keymap-nya — lihat bagian keymaps nanti).

Tampilan & UI: termguicolors, cursorline, scrolloff, signcolumn

Empat opsi ini membentuk "wajah" editor kalian:

OpsiNilaiFungsi
termguicolorstrueAktifkan true color (24-bit) — syarat colorscheme modern
cursorlinetrueSorot seluruh baris tempat kursor berada
scrolloff8Pertahankan minimal 8 baris konteks di atas/bawah kursor saat scroll
signcolumn"yes"Selalu tampilkan kolom tanda di kiri

Note

scrolloff mungkin terdengar sepele, tapi nilainya besar: tanpa scrolloff, kursor bisa berhenti di baris paling atas/bawah layar sehingga kalian kehilangan konteks di sekitar kode. Dengan scrolloff = 8, kursor berhenti delapan baris sebelum tepi layar, sehingga kode di sekitarnya tetap terlihat — sangat membantu saat membaca fungsi yang panjang. Sementara itu, signcolumn = "yes" membuat kolom di kiri (tempat muncul ikon error LSP dan indikator git) selalu ada, sehingga kode tidak "melompat" ke kiri-kanan setiap kali ikon muncul atau hilang.

Perilaku: clipboard, undofile, mouse

OpsiNilaiFungsi
clipboard"unnamedplus"Sinkronkan register default dengan clipboard sistem
undofiletrueSimpan riwayat undo ke disk — undo tetap ada setelah restart
mouse"a"Aktifkan dukungan mouse di semua mode

Note

clipboard = "unnamedplus" adalah pengubah permainan di Linux. Tanpa opsi ini, menyalin di Neovim (y) tidak akan tersedia di aplikasi lain — register "+ terpisah dari clipboard sistem. Dengan unnamedplus, register default " diarahkan ke clipboard, sehingga y, p, d langsung berinteraksi dengan clipboard. Trade-off-nya: menimpa teks dengan p atau d juga ikut mengubah isi clipboard sistem. undofile adalah pahlawan tanpa tanda jasa: setiap perubahan disimpan ke file .undo, sehingga kalian bisa membatalkan edit bahkan setelah me-restart Neovim — termasuk kesalahan yang dibuat seminggu lalu.

Rangkaian Lengkap options.lua

Berikut file lua/config/options.lua yang utuh dan siap dipakai:

lua/config/options.lua
local opt = vim.opt
 
-- Nomor baris
opt.number = true
opt.relativenumber = true
 
-- Indentasi
opt.tabstop = 4
opt.shiftwidth = 4
opt.expandtab = true
opt.smartindent = true
 
-- Pencarian
opt.ignorecase = true
opt.smartcase = true
opt.hlsearch = true
opt.incsearch = true
 
-- Tampilan & UI
opt.termguicolors = true
opt.cursorline = true
opt.scrolloff = 8
opt.signcolumn = "yes"
 
-- Perilaku
opt.clipboard = "unnamedplus"
opt.undofile = true
opt.mouse = "a"
Konfigurasi opsi inti — sesuaikan nilai sesuai preferensi

Tip

Kalian tidak perlu menghafal semua opsi. Cara terbaik mempelajarinya: jalankan :help options untuk daftar lengkap, atau :help <nama-opsi> untuk penjelasan satu opsi. Setelah config aktif, periksa nilai aktual dengan :set <opsi>? — misalnya :set scrolloff?. Kebiasaan kecil ini mengubah kalian dari penyalin config menjadi pemaham config.

Membangun lua/config/keymaps.lua

Jika options menentukan perilaku editor, keymaps menentukan kecepatan kalian. Ini adalah tempat paling personal di seluruh config — dan bagian yang paling sering ditulis ulang seiring kalian menemukan pola kerja sendiri.

Memahami Leader Key

Konsep leader key adalah salah satu penemuan terpenting Vim. Idenya sederhana: sediakan satu tombol "pemicu" khusus sehingga semua shortcut kustom kalian hidup di bawah namespace itu, tanpa menabrak shortcut bawaan.

vim.g.mapleader = " " menetapkan spasi sebagai leader. Konsekuensinya, kombinasi <leader>w berarti menekan spasi lalu w. Mengapa spasi? Karena tombol spasi di mode normal tidak memiliki fungsi penting dan selalu mudah dijangkau kedua ibu jari — itulah mengapa spasi menjadi standar de-facto di komunitas Neovim modern.

Important

Aturan emas: vim.g.mapleader harus ditetapkan SEBELUM semua keymap yang memakai <leader>. Nilai leader dibaca saat keymap didefinisikan. Jika keymap dibuat sebelum mapleader terisi, <leader> akan jatuh ke nilai default (backslash) — dan shortcut kalian tiba-tiba tidak berfungsi sesuai harapan. Karena itu, letakkan baris vim.g.mapleader = " " di bagian paling atas keymaps.lua (atau di file yang dimuat paling awal).

Anatomi vim.keymap.set

Signature lengkapnya: vim.keymap.set(mode, lhs, rhs, opts).

  • mode — mode tempat keymap berlaku (lihat tabel mode di bawah).
  • lhs — kombinasi tombol yang kalian tekan (left-hand side).
  • rhs — aksi yang dijalankan (right-hand side): bisa string perintah atau fungsi Lua.
  • opts — opsi lanjutan seperti silent, desc, buffer, noremap.
Opsi optsNilaiFungsi
silenttrueSembunyikan echo perintah di command-line
descstringDeskripsi untuk :map dan popup which-key
buffertrue / nomorBatasi keymap hanya untuk buffer tertentu
noremaptrue (default)Cegah mapping rekursif (aman secara default)
exprtrueNilai rhs dievaluasi sebagai ekspresi Lua

Tabel Mode

Kode ModeModeFungsi
"n"NormalNavigasi & manipulasi teks
"i"InsertMenulis teks
"v"VisualSeleksi karakter/baris
"x"Visual BlockSeleksi blok
"s"SelectMode select
"o"Operator-pendingMenunggu motion setelah operator
"t"TerminalTerminal buffer
"c"Command-lineMenunggu perintah :
"" / "!"Semua modeBerlaku di seluruh mode

Rangkaian Lengkap keymaps.lua

Berikut file lua/config/keymaps.lua yang lengkap. Perhatikan bahwa kita membuat alias local map = vim.keymap.set agar file terasa ringkas dan mudah dibaca:

lua/config/keymaps.lua
vim.g.mapleader = " "
vim.g.maplocalleader = " "
 
local map = vim.keymap.set
 
-- ==================== Normal Mode ====================
 
-- Simpan & keluar
map("n", "<leader>w", "<Cmd>w<CR>", { desc = "Simpan file" })
map("n", "<leader>q", "<Cmd>q<CR>", { desc = "Tutup window" })
map("n", "<leader>x", "<Cmd>bd<CR>", { desc = "Tutup buffer" })
 
-- Navigasi buffer
map("n", "<leader>bn", "<Cmd>bnext<CR>", { desc = "Buffer berikutnya" })
map("n", "<leader>bp", "<Cmd>bprevious<CR>", { desc = "Buffer sebelumnya" })
map("n", "<leader>bb", "<Cmd>b#<CR>", { desc = "Buffer alternatif" })
 
-- Window split
map("n", "<leader>sh", "<Cmd>split<CR>", { desc = "Split horizontal" })
map("n", "<leader>sv", "<Cmd>vsplit<CR>", { desc = "Split vertikal" })
map("n", "<leader>so", "<Cmd>only<CR>", { desc = "Tutup window lain" })
 
-- Pindah antar window (Ctrl-w h/j/k/l tanpa Ctrl-w)
map("n", "<C-h>", "<C-w>h", { desc = "Ke window kiri" })
map("n", "<C-j>", "<C-w>j", { desc = "Ke window bawah" })
map("n", "<C-k>", "<C-w>k", { desc = "Ke window atas" })
map("n", "<C-l>", "<C-w>l", { desc = "Ke window kanan" })
 
-- Hapus sorotan pencarian
map("n", "<Esc><Esc>", "<Cmd>nohlsearch<CR>", { desc = "Hapus sorotan" })
map("n", "<leader>nh", "<Cmd>nohlsearch<CR>", { desc = "Hapus sorotan" })
 
-- File explorer bawaan (akan diganti plugin di episode 12)
map("n", "<leader>e", "<Cmd>Ex<CR>", { desc = "Buka file explorer" })
 
-- ==================== Insert Mode ====================
 
-- Keluar insert mode dengan jj (lebih cepat dari Esc)
map("i", "jj", "<Esc>", { desc = "Keluar insert mode" })
map("i", "<C-s>", "<Cmd>w<CR>", { desc = "Simpan tanpa keluar mode" })
 
-- ==================== Visual Mode ====================
 
-- Pertahankan seleksi saat indentasi
map("v", "<", "<gv", { desc = "Indentasi kiri (pertahankan seleksi)" })
map("v", ">", ">gv", { desc = "Indentasi kanan (pertahankan seleksi)" })
map("v", "p", '"_dP', { desc = "Paste tanpa menimpa register" })
 
-- ==================== Terminal Mode ====================
 
map("t", "<Esc><Esc>", "<C-\\><C-n>", { desc = "Keluar terminal ke normal" })
Kumpulan shortcut kustom berpusat leader — sesuaikan dengan kebiasaan

Tip

Perhatikan pola berulang: hampir semua shortcut normal mode dimulai dengan <leader> lalu satu huruf yang mengelompokkan fungsi (b = buffer, s = split, w = write). Inilah "namespace" ala leader key — dengan satu huruf depan, kalian bisa menebak fungsi mapping lain secara intuitif. Saat shortcut berkembang (episode 9+), pola ini menjaga config tetap terorganisir.

Mengapa Menggunakan <Cmd> dan Bukan :?

Ini salah satu detail yang jarang dijelaskan tapi berdampak besar. Sebagian besar tutorial menulis mapping seperti map("n", "<leader>w", ":w<CR>"). Tapi ada perbedaan halus antara : dan <Cmd>:

  • Dengan :, Neovim memasuki command-line mode lalu mengetik perintah. Akibatnya: kursor berpindah sementara, echo muncul di command-line, dan di visual mode, sebuah range <,'> otomatis ditambahkan ke awal perintah — sehingga :w di visual mode hanya akan menulis baris terseleksi!
  • Dengan <Cmd>...<CR>, perintah dieksekusi tanpa keluar dari mode aktif dan tanpa echo. Inilah alasan mapping di atas memakai <Cmd>w<CR> — lebih bersih, dan aman dipakai di visual mode.

Caution

Kesalahan umum: menyalin mapping dari tutorial lama yang memakai :w<CR>, lalu heran saat di visual mode perintah berperilaku aneh (misalnya hanya menulis sebagian file). Gunakan <Cmd>...<CR> untuk perintah yang kalian ingin jalankan utuh di mode apa pun.

Tips silent dan desc

Dua opsi kecil yang berdampak besar:

  • silent = true menyembunyikan echo perintah di command-line. Tanpa itu, setiap <leader>w akan menampilkan :w di bawah layar — distraksi visual kecil yang terasa mengganggu seiring waktu.
  • desc memberi nama pada setiap mapping. Ia muncul di :map untuk debugging, dan — yang lebih penting — menjadi bahan utama popup which-key yang akan kita pasang di episode 20. Mendeskripsikan mapping sejak awal adalah investasi kecil dengan pengembalian besar.

Kesalahan Umum Options & Keymaps

  1. Leader key yang "tidak terdaftar". Gejalanya: <leader>w memunculkan error E15: Invalid expression atau tidak melakukan apa pun. Penyebabnya hampir selalu mapleader diset setelah keymap — atau config dimuat ulang tanpa mapleader sempat terisi.
  2. Timing leader yang terlalu ketat. Secara default timeoutlen adalah 1000ms. Jika kalian menekan spasi lalu menunggu lebih dari satu detik sebelum huruf berikutnya, mapping tidak akan terpicu. Bila terasa lambat, turunkan dengan opt.timeoutlen = 500 di options.lua.
  3. Mapping konflik dengan bawaan. Sebelum menimpa shortcut bawaan (misalnya <C-h> untuk window), cek dulu :map <C-h> untuk melihat fungsi aslinya. Kadang mengubah tombol standar tanpa sadar memutus fitur yang sedang kalian pakai.
  4. Memakai : di mapping visual mode tanpa memahami range otomatis <,'>. Solusinya: <Cmd> (lihat di atas).
  5. expandtab yang diaktifkan di semua file bisa merusak file yang wajib tab (Makefile). Solusi: nonaktifkan per-filetype — akan kita bahas di episode 8 dengan ftplugin.
  6. Terlalu banyak mapping yang saling menumpuk. Jika <leader>s sudah dipakai untuk split, jangan pakai <leader>s lagi untuk hal lain. Konsistenlah dengan satu huruf depan per kelompok fungsi.
  7. Melupakan silent. Mapping yang menampilkan echo terasa "berisik". Biasakan menyertakan { silent = true, desc = ... } sejak awal.

Note

Setelah menulis atau mengubah file config, jangan lupa memuat ulang agar perubahan aktif: jalankan :luafile ~/.config/nvim/lua/config/options.lua (untuk satu file) atau restart Neovim. Di episode 9, lazy.nvim akan menyediakan cara yang lebih nyaman untuk memuat ulang config (termasuk keymaps yang berhubungan dengan plugin).

Penutup

Di episode 7 ini kita telah membangun dua pilar pertama config Neovim. Di lua/config/options.lua, kalian mengatur nomor baris dengan number + relativenumber, indentasi dengan tabstop/shiftwidth/expandtab/smartindent, pencarian cerdas dengan ignorecase + smartcase, tampilan dengan termguicolors/cursorline/scrolloff/signcolumn, serta perilaku dengan clipboard = "unnamedplus", undofile, dan mouse. Di lua/config/keymaps.lua, kalian menetapkan spasi sebagai leader key, membuat shortcut terkelompok (<leader>w, <leader>b, <leader>s), mempelajari perbedaan <Cmd> vs :, dan menyadari mengapa silent serta desc itu penting.

Poin penting yang harus kalian bawa:

  • vim.g.mapleader = " " harus diletakkan sebelum semua keymap <leader>.
  • scrolloff = 8 dan signcolumn = "yes" menjaga konteks dan mencegah layout melompat.
  • clipboard = "unnamedplus" menghubungkan register default dengan clipboard sistem.
  • Gunakan <Cmd>...<CR> untuk perintah yang aman di semua mode, terutama visual.
  • Setiap mapping berharga silent = true dan desc untuk kenyamanan dan keterbacaan.

Config kalian sekarang sudah hidup: editor terasa nyaman, dan tangan kalian mulai "menari" di atas leader key. Tapi ada satu jenis kekuatan yang belum kita bangun — kemampuan editor untuk bereaksi sendiri terhadap kejadian: menyimpan otomatis, merapikan whitespace, atau menjalankan perintah khusus. Di episode 8 selanjutnya, kita akan membahas Autocommands, Filetype Detection & Custom Commands — membangun lua/config/autocmds.lua, membuat command kustom seperti :TrimWhitespace, dan menyetel pengaturan per bahasa dengan ftplugin. Pastikan tetap semangat!