Masalah Anda dengan Vim adalah Anda tidak grok vi .
Anda menyebutkan memotong dengan yy
dan mengeluh bahwa Anda hampir tidak pernah ingin memotong garis keseluruhan. Sebenarnya programmer, mengedit kode sumber, sangat sering ingin bekerja pada seluruh baris, rentang garis dan blok kode. Namun, yy
hanya satu dari banyak cara untuk menarik teks ke dalam buffer salinan anonim (atau "daftar" seperti namanya in vi ).
"Zen" dari vi adalah Anda berbicara bahasa. Inisialnya y
adalah kata kerja. Pernyataan yy
ini adalah sinonim untuk y_
. Ini y
digandakan untuk membuatnya lebih mudah untuk mengetik, karena ini adalah operasi yang umum.
Ini juga dapat dinyatakan sebagai dd
P
(hapus baris saat ini dan tempel salinan kembali ke tempatnya; meninggalkan salinan dalam register anonim sebagai efek samping). The y
dan d
"kata kerja" mengambil gerakan apa pun sebagai "subjek" mereka. Dengan demikian yW
adalah "menarik dari sini (kursor) ke akhir kata saat ini / berikutnya (besar)" dan y'a
"menarik dari sini ke baris yang mengandung tanda bernama ' a '."
Jika Anda hanya memahami gerakan kursor dasar ke atas, bawah, kiri, dan kanan maka vi tidak akan lebih produktif daripada salinan "notepad" untuk Anda. (Oke, Anda masih akan memiliki penyorotan sintaks dan kemampuan untuk menangani file yang lebih besar dari piddling ~ 45KB atau lebih; tetapi bekerja dengan saya di sini).
vi memiliki 26 "tanda" dan 26 "register." Tanda ditetapkan ke lokasi kursor apa pun menggunakan m
perintah. Setiap tanda ditandai dengan satu huruf kecil. Jadi ma
setel tanda ' a ' ke lokasi saat ini, dan mz
setel tanda ' z '. Anda dapat pindah ke baris yang berisi tanda menggunakan perintah '
(kutipan tunggal). Dengan demikian 'a
pindah ke awal baris yang berisi tanda ' a '. Anda dapat pindah ke lokasi yang tepat dari sembarang tanda menggunakan perintah `
(backquote). Dengan demikian `z
akan pindah langsung ke lokasi yang tepat dari tanda ' z '.
Karena ini adalah "gerakan" mereka juga dapat digunakan sebagai subjek untuk "pernyataan" lainnya.
Jadi, salah satu cara untuk memotong teks pilihan sewenang-wenang adalah dengan menjatuhkan tanda (saya biasanya menggunakan ' a ' sebagai tanda "pertama" saya, ' z ' sebagai tanda berikutnya, ' b ' sebagai yang lain, dan ' e ' sebagai satu lagi (saya tidak ingat pernah secara interaktif menggunakan lebih dari empat tanda dalam 15 tahun penggunaan vi ; orang menciptakan konvensi sendiri tentang bagaimana tanda dan register digunakan oleh makro yang tidak mengganggu konteks interaktif seseorang). ke ujung teks yang kita inginkan; kita dapat mulai dari kedua sisi, itu tidak masalah. Kemudian kita dapat menggunakan d`a
untuk memotong atau y`a
menyalin. Dengan demikian seluruh proses memiliki 5 penekanan tombol overhead (enam jika kita mulai di "masukkan "mode dan diperlukan untukEscmode perintah keluar). Setelah kami dipotong atau disalin kemudian paste di salinan adalah keystroke tunggal: p
.
Saya mengatakan bahwa ini adalah salah satu cara untuk memotong atau menyalin teks. Namun, itu hanya satu dari banyak. Seringkali kita dapat secara lebih ringkas menggambarkan rentang teks tanpa menggerakkan kursor kita dan menjatuhkan tanda. Sebagai contoh jika saya dalam paragraf teks saya dapat menggunakan {
dan }
memindahkan masing-masing ke awal atau akhir paragraf. Jadi, untuk memindahkan paragraf teks saya memotongnya menggunakan {
d}
(3 penekanan tombol). (Jika saya sudah berada pada baris pertama atau terakhir paragraf saya kemudian dapat menggunakan d}
atau d{
masing - masing.
Gagasan "paragraf" default ke sesuatu yang biasanya masuk akal secara intuitif. Jadi sering berfungsi untuk kode dan prosa.
Seringkali kita mengetahui beberapa pola (ekspresi reguler) yang menandai satu ujung atau yang lain dari teks yang kami minati. Mencari maju atau mundur adalah gerakan di vi . Dengan demikian mereka juga dapat digunakan sebagai "subjek" dalam "pernyataan" kami. Jadi saya dapat menggunakan d/foo
untuk memotong dari baris saat ini ke baris berikutnya yang berisi string "foo" dan y?bar
untuk menyalin dari baris saat ini ke baris terbaru (sebelumnya) yang berisi "bar." Jika saya tidak ingin seluruh baris saya masih bisa menggunakan gerakan pencarian (sebagai pernyataan mereka sendiri), lepaskan tanda saya dan gunakan `x
perintah seperti yang dijelaskan sebelumnya.
Selain "kata kerja" dan "subjek" vi juga memiliki "objek" (dalam arti gramatikal dari istilah tersebut). Sejauh ini saya hanya menggambarkan penggunaan register anonim. Namun, saya dapat menggunakan salah satu dari 26 register "bernama" dengan mengawali referensi "objek" dengan "
(pengubah kutipan ganda). Jadi jika saya menggunakan "add
saya memotong baris saat ini ke register ' a ' dan jika saya gunakan "by/foo
maka saya menarik salinan teks dari sini ke baris berikutnya yang berisi "foo" ke dalam register ' b '. Untuk menempel dari register, saya cukup awali paste dengan urutan pengubah yang sama: "ap
menempel salinan ' a ' register '"bP
menempelkan salinan dari ' b ' ke sebelum baris saat ini.
Gagasan "awalan" ini juga menambahkan analogi dari kata sifat "kata sifat" dan "kata keterangan 'ke bahasa" manipulasi teks "kita. Sebagian besar perintah (kata kerja) dan gerakan (kata kerja atau objek, tergantung pada konteksnya) juga dapat mengambil awalan angka. 3J
berarti "bergabung dengan tiga baris berikutnya" dan d5}
berarti "hapus dari baris saat ini sampai akhir paragraf kelima turun dari sini."
Ini semua tingkat menengah vi . Tak satu pun dari itu adalah Vim spesifik dan ada trik jauh lebih maju di vi jika Anda siap untuk belajar mereka. Jika Anda hanya menguasai konsep-konsep perantara ini, maka Anda mungkin akan menemukan bahwa Anda jarang perlu menulis makro karena bahasa manipulasi teks cukup ringkas dan ekspresif untuk melakukan banyak hal dengan cukup mudah menggunakan bahasa "asli" editor.
Contoh trik lebih lanjut:
Ada sejumlah :
perintah, terutama :% s/foo/bar/g
teknik substitusi global. (Itu tidak maju tetapi :
perintah lain bisa). Seluruh :
rangkaian perintah secara historis diwarisi oleh inkarnasi sebelumnya vi sebagai ed (editor baris) dan kemudian utilitas ex (editor baris diperluas). Bahkan vi dinamai demikian karena antarmuka visual untuk ex .
:
perintah biasanya beroperasi di atas baris teks. ed dan ex ditulis di era ketika layar terminal tidak umum dan banyak terminal adalah perangkat "teletype" (TTY). Jadi itu biasa untuk bekerja dari salinan teks yang dicetak, menggunakan perintah melalui antarmuka yang sangat singkat (kecepatan koneksi umum adalah 110 baud, atau, kira-kira, 11 karakter per detik - yang lebih lambat daripada pengetik cepat; kelambatan umum terjadi pada sesi interaktif multi-pengguna; juga sering ada motivasi untuk menghemat kertas).
Jadi sintaksis sebagian besar :
perintah termasuk alamat atau rentang alamat (nomor baris) diikuti oleh perintah. Secara alami seseorang dapat menggunakan nomor baris literal: :127,215 s/foo/bar
untuk mengubah kemunculan pertama "foo" menjadi "bar" pada setiap baris antara 127 dan 215. Seseorang juga dapat menggunakan beberapa singkatan seperti .
atau $
untuk baris saat ini dan terakhir masing-masing. Kita juga bisa menggunakan awalan relatif +
dan -
merujuk ke offset setelah atau sebelum garis curent, masing-masing. Jadi: :.,$j
artinya "dari baris saat ini ke baris terakhir, gabungkan semuanya menjadi satu baris". :%
identik dengan :1,$
(semua baris).
The :... g
dan :... v
perintah menanggung sebagian penjelasan mereka sangat kuat. :... g
adalah awalan untuk "secara global" menerapkan perintah berikutnya untuk semua baris yang cocok dengan pola (ekspresi reguler) sambil :... v
menerapkan perintah tersebut untuk semua baris yang TIDAK cocok dengan pola yang diberikan ("v" dari "conVerse"). Seperti halnya perintah ex lainnya, ini dapat diawali dengan mengatasi / mencari referensi. Dengan demikian :.,+21g/foo/d
berarti "hapus semua baris yang berisi string" foo "dari yang sekarang hingga 21 baris berikutnya" sementara itu :.,$v/bar/d
berarti "dari sini ke akhir file, hapus semua baris yang TIDAK mengandung string" bar. "
Sungguh menarik bahwa umum perintah Unix grep sebenarnya terinspirasi oleh ini mantan perintah (dan dinamai cara di mana itu didokumentasikan). The ex perintah :g/re/p
(grep) adalah cara mereka didokumentasikan bagaimana "global" "mencetak" garis yang berisi "ekspresi reguler" (re). Ketika ed dan ex digunakan, :p
perintah adalah salah satu yang pertama yang dipelajari dan sering kali yang pertama digunakan saat mengedit file apa pun. Begitulah cara Anda mencetak konten saat ini (biasanya hanya satu halaman penuh pada saat menggunakan :.,+25p
atau semacamnya).
Perhatikan bahwa :% g/.../d
atau (pembalikan / pembalikan: :% v/.../d
adalah pola penggunaan yang paling umum. Namun ada beberapa ex
perintah lain yang perlu diingat:
Kita dapat menggunakan m
untuk memindahkan garis, dan j
untuk bergabung dengan garis. Misalnya jika Anda memiliki daftar dan ingin memisahkan semua barang yang cocok (atau sebaliknya TIDAK cocok dengan beberapa pola) tanpa menghapusnya, maka Anda dapat menggunakan sesuatu seperti: :% g/foo/m$
... dan semua "foo" baris akan dipindahkan ke akhir file. (Perhatikan tip lain tentang menggunakan ujung file Anda sebagai ruang awal). Ini akan mempertahankan urutan relatif semua baris "foo" sambil mengekstraknya dari daftar lainnya. (Ini setara dengan melakukan sesuatu seperti: 1G!GGmap!Ggrep foo<ENTER>1G:1,'a g/foo'/d
(salin file ke ekornya sendiri, filter ekor melalui grep
, dan hapus semua hal dari kepala).
Untuk bergabung dengan garis biasanya saya dapat menemukan pola untuk semua garis yang perlu digabungkan dengan pendahulunya (semua garis yang dimulai dengan "^" daripada "^ *" dalam beberapa daftar peluru, misalnya). Untuk itu saya akan menggunakan: :% g/^ /-1j
(untuk setiap baris yang cocok, naik satu baris dan bergabung dengan mereka). (BTW: untuk daftar peluru mencoba untuk mencari jalur peluru dan bergabung ke depan tidak bekerja untuk beberapa alasan ... itu dapat bergabung dengan salah satu baris peluru ke yang lain, dan itu tidak akan bergabung dengan garis peluru untuk semua dari kelanjutannya; itu hanya akan bekerja berpasangan pada pertandingan).
Hampir tidak perlu disebutkan, Anda dapat menggunakan teman lama kami s
(pengganti) dengan perintah g
dan v
(global / converse-global). Biasanya Anda tidak perlu melakukannya. Namun, pertimbangkan beberapa kasus di mana Anda ingin melakukan penggantian hanya pada garis yang cocok dengan beberapa pola lainnya. Seringkali Anda dapat menggunakan pola yang rumit dengan menangkap dan menggunakan kembali referensi untuk mempertahankan bagian dari garis yang Anda TIDAK ingin ubah. Namun, seringkali akan lebih mudah untuk memisahkan kecocokan dari substitusi: :% g/foo/s/bar/zzz/g
- untuk setiap baris yang berisi "foo" gantikan semua "bar" dengan "zzz." (Sesuatu seperti:% s/\(.*foo.*\)bar\(.*\)/\1zzz\2/g
hanya akan bekerja untuk kasus-kasus contoh "bar" yang DIHARAPKAN oleh "foo" pada baris yang sama; itu sudah cukup canggung, dan harus dihancurkan lebih lanjut untuk menangkap semua kasus di mana "bar" didahului "foo")
Intinya adalah bahwa ada lebih dari sekedar p
, s
dan d
garis-garis di ex
set perintah.
:
Alamat - alamat itu juga bisa merujuk pada tanda. Dengan demikian Anda dapat menggunakan::'a,'bg/foo/j
untuk bergabung dengan baris apa pun yang berisi string foo ke baris berikutnya, jika berada di antara garis antara tanda ' a ' dan ' b '. (Ya, semua ex
contoh perintah sebelumnya dapat dibatasi untuk himpunan bagian dari baris file dengan awalan dengan jenis ekspresi pengalamatan ini).
Itu sangat tidak jelas (Saya hanya menggunakan sesuatu seperti itu beberapa kali dalam 15 tahun terakhir). Namun, saya akan dengan bebas mengakui bahwa saya sering melakukan hal-hal secara iteratif dan interaktif yang mungkin bisa dilakukan lebih efisien jika saya meluangkan waktu untuk memikirkan mantra yang benar.
Lain sangat berguna vi atauPerintah ex adalah :r
membaca isi dari file lain. Dengan demikian: :r foo
menyisipkan konten file bernama "foo" di baris saat ini.
Lebih kuat adalah :r!
perintahnya. Ini membaca hasil dari suatu perintah. Ini sama dengan menangguhkan sesi vi , menjalankan perintah, mengarahkan outputnya ke file sementara, melanjutkan kembali sesi vi Anda , dan membaca konten dari temp. mengajukan.
Yang lebih kuat lagi adalah perintah !
(bang) dan :... !
( ex bang). Ini juga menjalankan perintah eksternal dan membaca hasilnya ke dalam teks saat ini. Namun, mereka juga memfilter pilihan teks kita melalui perintah! Ini kita bisa mengurutkan semua baris dalam file kita menggunakan 1G!Gsort
( G
adalah perintah vi "goto"; ini default untuk pergi ke baris terakhir file, tetapi dapat diawali dengan nomor baris, seperti 1, baris pertama). Ini setara dengan varian ex:1,$!sort
. Penulis sering menggunakan !
dengan Unix fmt atau utilitas lipat untuk mereformasi atau "pembungkus kata" pilihan teks. Makro yang sangat umum adalah{!}fmt
(memformat ulang paragraf saat ini). Pemrogram terkadang menggunakannya untuk menjalankan kode mereka, atau hanya sebagian, melalui indent atau alat pemformatan ulang kode lainnya.
Menggunakan :r!
dan !
perintah berarti utilitas atau filter eksternal apa pun dapat diperlakukan sebagai ekstensi editor kami. Saya kadang-kadang menggunakan ini dengan skrip yang menarik data dari database, atau dengan perintah wget atau lynx yang menarik data dari situs web, atau ssh perintah yang menarik data dari sistem jarak jauh.
Perintah ex berguna lainnya adalah :so
(kependekan dari :source
). Ini membaca isi file sebagai serangkaian perintah. Ketika Anda mulai vi secara normal, secara implisit, melakukan file :source
pada ~/.exinitrc
(dan Vim biasanya melakukan ini ~/.vimrc
, cukup alami). Kegunaannya adalah Anda dapat mengubah profil editor dengan cepat hanya dengan mencari di set makro, singkatan, dan pengaturan editor yang baru. Jika Anda licik, Anda bahkan dapat menggunakan ini sebagai trik untuk menyimpan urutan perintah pengeditan ex untuk diterapkan ke file sesuai permintaan.
Misalnya saya punya file tujuh baris (36 karakter) yang menjalankan file wc , dan menyisipkan komentar gaya-C di bagian atas file yang berisi data jumlah kata itu. Saya bisa menerapkan "makro" itu ke file dengan menggunakan perintah seperti:vim +'so mymacro.ex' ./mytarget
( +
Opsi baris perintah ke vi dan Vim biasanya digunakan untuk memulai sesi pengeditan pada nomor baris yang diberikan. Namun, sedikit fakta yang diketahui bahwa seseorang dapat mengikuti +
dengan perintah / ekspresi ex yang valid , seperti perintah "sumber" seperti Saya sudah selesai di sini, sebagai contoh sederhana saya memiliki skrip yang memanggil: vi +'/foo/d|wq!' ~/.ssh/known_hosts
untuk menghapus entri dari file host SSH saya yang dikenal non-interaktif saat saya kembali menggambar satu set server)
Biasanya jauh lebih mudah untuk menulis "macro" seperti itu menggunakan Perl, AWK, sed (yang, pada kenyataannya, seperti grep utilitas yang terinspirasi oleh perintah ed ).
The @
perintah mungkin yang paling jelas vi perintah. Dalam sesekali mengajar kursus administrasi sistem canggih selama hampir satu dekade, saya bertemu sangat sedikit orang yang pernah menggunakannya. @
mengeksekusi isi register seolah-olah itu adalah perintah vi atau ex .
Contoh: Saya sering menggunakan: :r!locate ...
untuk menemukan beberapa file di sistem saya dan membaca namanya ke dalam dokumen saya. Dari sana saya menghapus setiap klik yang tidak diinginkan, hanya menyisakan path lengkap ke file yang saya minati. Daripada dengan susah payah Tabmenelusuri setiap komponen path (atau lebih buruk lagi, jika saya terjebak pada mesin tanpa dukungan penyelesaian Tab) dalam salinan vi ) Saya hanya menggunakan:
0i:r
(untuk mengubah baris saat ini menjadi perintah yang valid : r ),
"cdd
(untuk menghapus baris ke dalam register "c") dan
@c
jalankan perintah itu.
Itu hanya 10 penekanan tombol (dan ungkapan "cdd
@c
itu secara efektif adalah makro jari untuk saya, jadi saya bisa mengetiknya hampir secepat kata enam huruf biasa).
Pikiran yang serius
Saya hanya mencakar ke permukaan kekuatan vi dan tidak satupun dari apa yang saya jelaskan di sini bahkan merupakan bagian dari "perbaikan" yang namanya vim ! Semua yang saya jelaskan di sini harus bekerja pada salinan lama vi dari 20 atau 30 tahun yang lalu.
Ada orang yang menggunakan kekuatan vi jauh lebih besar daripada yang pernah saya lakukan.