Mengapa Vim / Neovim sangat baik? Fakta bahwa toolkit Anda bukan hanya editor (yang dengan sendirinya sangat dapat diperluas dengan plugin dan memiliki fungsi dasar yang kaya dan sangat fleksibel dalam bidang penyesuaian), tetapi juga seluruh lingkungan kerja Anda , dengan semua toolkit unix-way termasuk dari gnu / coreutils dan tidak hanya. Anda dapat mengambil program atau juru bahasa apa pun tanpa meninggalkan editor dan menggunakannya langsung di editor.
Kata Pengantar
Posting ini ditulis dengan tergesa-gesa untuk lingkaran pribadi orang, tetapi saya memutuskan bahwa sangat mungkin untuk mempostingnya di Habr. Bagi sebagian orang, ini bisa menjadi inspirasi, seseorang akan membantu untuk lebih memahami filosofi Vim, dan seseorang akan mengambil beberapa trik untuk diri mereka sendiri. Untuk berjaga-jaga, saya akan membuat reservasi yang seharusnya tidak saya harapkan bahwa saya akan membuktikan sesuatu kepada seseorang di komentar, misalnya, untuk meyakinkan Anda bahwa Anda pasti harus melepaskan IDE Anda yang gemuk dan mulai menggunakan Vim, saya sama sekali tidak tertarik dengan hal ini.
Untuk bisnis
Di sini, misalnya, ambil sepotong kode (dari konfigurasi proyek Haskell), daftar dependensi paket (contoh dalam ruang hampa):
build-depends: X11 , base , directory , extra , GLFW-b , safe , aeson , containers , data-default , text , process , time , dbus
Apa yang kita inginkan?
- Urutkan dependensi berdasarkan abjad
- Sortir case-insensitive (
X11
dan GLFW-b
tidak harus naik di atas segalanya) - Pulihkan koma (
aeson
akan menuju ke paling atas dan seharusnya tidak lagi memiliki koma di sebelah kiri, tetapi X11
harus memiliki koma di sebelah kiri) - Pulihkan lekukan (sehingga Anda juga bisa mendapatkan perintah dari sejarah dan menggunakannya kembali di konfigurasi lain dengan tingkat bersarang yang berbeda, atau bahkan mengikat perintah hotkey di konfigurasi Vim)
Solusi
Pertama-tama, pilih (dengan menyoroti visual) daftar dependensi kecuali baris pertama build-depends
. Anda tentu saja dapat cukup menekan V
(mode visual dengan pemilihan baris demi baris) dan memilih garis yang diperlukan melalui jk
atau panah atas dan bawah. Dalam kasus saya, saya melakukan ini dengan satu gelombang tangan saya menggunakan hotkey khusus untuk mode visual:
xn iz <esc>[zV]z
Misalnya, berada di tengah daftar dependensi, saya hanya menekan viz
dan semua dependensi disorot, karena seluruh lipatan disorot, yang pada gilirannya adalah blok bersarang saat ini (karena saya telah menetapkan foldmethod
sebagai indent
). Tetapi Anda juga dapat secara manual mengetik [zV]z
secara berurutan tanpa hotkey khusus ( [z
melompat ke awal flip, a ]z
ke akhir), tetapi karena bagi saya operasi seperti itu sering digunakan, maka saya mempersingkatnya menjadi viz
- tidak ada pengubah seperti pergeseran dan kompres pada refleks dalam sekejap (analog standar terdekat adalah vip
untuk memilih blok ke garis kosong terdekat).
Kemudian tekan :
(titik dua) untuk masuk ke mode perintah untuk menjalankan perintah relatif terhadap sorotan visual saat ini. Bahkan, mode perintah yang biasa, tetapi dengan segera menambahkan marker seleksi, mis. akan terlihat seperti :'<,'>
mana '<,'>
adalah rentang pilihan, di mana '<
adalah baris pertama dari pemilihan visual, dan '>
adalah yang terakhir.
Setelah kita klik !
(tanda seru) pada keyboard, ini berarti bahwa semua yang berjalan lebih jauh adalah perintah shell / bash (tergantung pada pengaturan). Akan terlihat seperti :'<,'>!
. Bahkan, setelah memilih, Anda bisa langsung mengklik !
dan dapatkan hasil yang sama - :'<,'>!
.
Operasi ini akan mengalihkan garis yang disorot ke perintah STDIN dan mengganti garis yang disorot dengan knalpot STDOUT dari perintah ini. Misalnya, Anda dapat menggunakan perintah sort
, murni untuk verifikasi, hasilnya bukan apa yang kita butuhkan - '<,'>!sort
dan tekan Enter , kita dapatkan:
build-depends: , aeson , base , containers , data-default , dbus , directory , extra , GLFW-b , process , safe , text , time X11
Fashion dengan coreutils dan menara umum
Kembalikan pilihan sebelumnya (Anda dapat menekan gv
untuk mengembalikan pilihan terakhir) dan tekan !
dan kemudian panah atas - ini akan mengembalikan perintah terakhir dari sejarah, jadi kita tidak perlu menulis lagi, kita cukup mengekstrak perintah sebelumnya dari sejarah dan mengubahnya. Untuk mengedit perintah yang lebih nyaman, Anda dapat menekan Ctrl
+ f
- ini akan membuka tambahan. sebuah jendela dengan pengeditan standar normal perintah, dengan semua kemampuan Vim, omong-omong, semua tim sebelumnya dari sejarah akan terlihat di sana sebagai baris terpisah, yang juga dapat dipilih, diedit dan dieksekusi.
Apa hal yang benar untuk dilakukan - Anda dapat memikirkan suatu penemuan, maksud saya adalah ini: pertama kita menghapus koma, mengurutkannya tanpa mereka (tanpa case-case), kemudian kita mengembalikan koma, kecuali untuk baris pertama.
Pertama, hapus koma (dan baris pertama memiliki lekukan tambahan sehingga semua baris memiliki lekukan yang sama) menggunakan perintah sed
dengan ekspresi reguler ( [, ]
- koma atau spasi, dan kemudian spasi lain, \(\w\)
lolos dari tanda kurung untuk menyorot blokir untuk substitusi, sehingga tersedia sebagai \1
, \w
adalah karakter alfabet pertama, dalam penggantian kita akan mengembalikan karakter alfabet dengan mengganti \1
):
:'<,'>!sed 's/[, ] \(\w\)/\1/'
Kami mendapatkan yang berikut ini:
build-depends: X11 base directory extra GLFW-b safe aeson containers data-default text process time dbus
Selanjutnya, kita pipe (melalui simbol |
adalah fitur bash) ke perintah sort sort
, melewati -f
untuk case insensitivity:
:'<,'>!sed 's/[, ] \(\w\)/\1/' | sort -f
Kami mendapatkan:
build-depends: aeson base containers data-default dbus directory extra GLFW-b process safe text time X11
Hampir selesai! Tetap hanya menambahkan koma, dan baris pertama - beberapa spasi. Kami menggunakan sed
sama, dalam sintaks operasinya Anda dapat menentukan string dan rentang string (seperti dalam Vim itu sendiri, sintaksnya sama, baik, atau hampir sama). Awalan 1
akan berarti baris pertama, 2,$
berarti kisaran dari baris ke-2 sampai akhir ( $
, seperti ^
berarti awal file, dengan analogi dengan karakter yang sama dalam ekspresi reguler yang berarti akhir dan awal dari baris). Kami akan menggunakan \w
untuk melewati lekukan dan segera memilih karakter alfabet pertama: 1s/\w/ &/
- di sini kami melakukan penggantian untuk baris pertama, mengembalikan karakter alfabet pertama melalui &
(mirip dengan \1
, hanya &
berarti segalanya di bawah seluruh regex, sedangkan \1
berarti blok pertama yang dibungkus dengan tanda kurung), menambahkan beberapa spasi di depannya. Untuk baris yang tersisa, alih-alih dua spasi, tambahkan koma + spasi diikuti oleh: 2,$s/\w/, &/
, seluruh perintah akan seperti ini: sed -e '1s/\w/ &/' -e '2,$s/\w/, &/'
, - -e
kita gunakan untuk memisahkan 2 operasi dari satu sama lain. Di Vim, seluruh operasi akan terlihat seperti:
:'<,'>!sed 's/[, ] \([^, ]\)/\1/' | sort -f | sed -e '1s/\w/ &/' -e '2,$s/\w/, &/'
Kami mendaftar dan mendapatkan:
build-depends: aeson , base , containers , data-default , dbus , directory , extra , GLFW-b , process , safe , text , time , X11
Selesai! Tidak perlu lagi menulis kedua, cukup ketikkan beberapa karakter pertama, misalnya :: :'<,'>!se
(sebenarnya, Anda hanya perlu menekan !se
), dan gunakan panah atas untuk mendapatkan perintah yang diinginkan dari sejarah. Dengan satu atau lain cara, saya sering merekomendasikan berlatih menulis hal-hal seperti itu segera . Dengan demikian, Anda berdua akan memompa keterampilan kerja harian Anda di bash dan di Vim sendiri pada dasarnya Anda melakukan hal yang sama.
Pada akhirnya, seluruh perintah ini dapat ditugaskan ke hotkey, atau diabstraksi menjadi fungsi, dan digunakan kembali di mana-mana untuk satu atau dua.
Menggunakan PL pihak ketiga
Alih-alih meluncurkan sesuatu dari coreutils, Anda dapat menjalankan juru bahasa dari beberapa jenis bahasa yang nyaman bagi Anda, saya suka melakukan hal-hal seperti itu melalui Perl6 (baru-baru ini diubah namanya menjadi Raku ):
:'<,'>!perl6 -e 'my @x=lines.map(*.subst(/<[,\s]>\s(\w)/,{$0})).sort(*.lc); @x.shift.subst(/\w/,{q/ /~$_}).say; .subst(/\w/,{q/, /~$_}).say for @x'
Ya, setidaknya pada zoskopi (simpul.js):
:'<,'>!node -e 'let fs=require("fs"), x=fs.readFileSync(process.stdin.fd).toString().replace(/\n$/,'').split(/\n/).map(x=>x.replace(/[, ] (\w)/,"$1")).sort((a,b)=>a.toLowerCase().localeCompare(b.toLowerCase())); console.log(x.shift().replace(/(\w)/," $1")); process.stdout.write(x.map(x=>x.replace(/(\w)/,", $1")).join("\n"))'
Ini juga dapat dilakukan pada VimL / Vimscript di dalam Vim itu sendiri, tanpa memanggil perintah eksternal. Tapi posting ini bukan tentang itu.
Tentu saja, seperti yang sudah Anda duga, Anda dapat dengan mudah menyimpan skrip Anda ke file terpisah, atau bahkan mengkompilasi program Anda sendiri yang mengambil sesuatu untuk masuk ke STDIN dan mengeluarkan sesuatu yang diproses dalam STDOUT dan menggunakannya dalam Vim hanya dengan menelepon (yang , sekali lagi, dapat ditugaskan ke hotkey):
:'<,'>!~/my-program-or-script
Dengan demikian, ketika Anda menulis kode dalam Vim, tidak hanya Vim itu sendiri siap membantu Anda, tetapi juga seluruh lingkungan kerja Anda.
Salah satu contoh paling sederhana adalah menolak file JSON:
:%!jq
Hanya dengan beberapa penekanan tombol, mengapa menciptakan kembali AST parser dan prettifayer untuk JSON untuk editor / IDE / apa pun yang baru, ketika Anda bisa mengambil dan menjalankan file melalui jq
tanpa meninggalkan Vim? Saya tidak berbicara tentang fakta bahwa Anda dapat memproses file JSON besar Anda melalui jq
dengan cara ini, tanpa meninggalkan Vim, temukan misalnya kunci yang diinginkan di pohon, urutkan, tinggalkan hanya data yang diperlukan, dll.