Tips untuk bermain golf di vim

32

Baru-baru ini saya menyadari bagaimana vim bekerja sangat baik untuk bermain golf, terutama untuk . Juga, menurut meta vim adalah 'bahasa pemrograman' yang dapat diterima dengan baik setidaknya, untuk cakupan situs ini, yaitu.

Apa tips umum yang Anda miliki untuk bermain golf di Vim? Saya mencari ide yang dapat diterapkan untuk masalah kode-golf dan yang juga setidaknya agak spesifik untuk Vim (mis. "Hapus komentar" bukan jawaban).

Silakan kirim satu tip per jawaban.

DJMcMayhem
sumber
4
Ini adalah pertanyaan tips yang sangat membantu karena "Tips untuk bermain golf di vim" dan "Tips untuk menggunakan vim secara efisien sebagai editor teks" pada dasarnya adalah hal yang sama.
DLosc

Jawaban:

15

Waspadai varian huruf besar dari perintah umum. Ini sepele dapat menghemat satu keystroke dalam banyak konteks. Sebagai contoh:

A = $a
C = c$
D = d$
I = ^i
S = cc
X = dh
Y = yy

Satu lagi adalah menggunakan Gbukan gg, tetapi hanya jika Anda menggunakan hitungan! Misalnya, tanpa hitungan, ggpindah ke awal, dan Gpindah ke akhir. Namun, dengan hitungan, keduanya bergerak ke baris yang Anda tentukan, jadi 5Glebih pendek dari tapi setara dengan 5gg .

Yang lain, adalah untuk digunakan Hsebagai pengganti gg, tetapi penting untuk dicatat bahwa ini hanya berfungsi jika Anda dapat menjamin bahwa input apa pun tidak akan mengambil lebih dari jumlah baris default (saya percaya ini 24, tetapi mungkin bervariasi).

DJMcMayhem
sumber
1
Jika tantangan khusus editor golf (dan karena itu biasanya dicetak dengan penekanan tombol) huruf besar adalah dua penekanan tombol juga (begitu juga $, jadi setidaknya Cdan Dakan menghemat sesuatu).
Martin Ender
1
Sesuatu yang saya tidak jelas tentang ketika mencetak dalam penekanan tombol adalah apakah huruf berurutan yang memerlukan tombol shift hanya menghitung tombol shift sekali per kelompok, karena Anda bisa (setidaknya untuk tujuan praktis) menahannya sambil menekan tombol lainnya.
Alex A.
6
@AlexA. Secara pribadi, saya pikir pengubah tidak boleh dihitung. Mungkin kita perlu posting meta tentang ini ...
DJMcMayhem
Gdan ggtidak setara. Yang pertama pergi ke ujung buffer dan yang terakhir pergi ke awal.
Jordan
@ Jordan Itu poin yang bagus. Maksud saya mereka sama ketika diberi hitungan, misalnya 5Gsetara dengan 5gg. Saya akan menambahkan beberapa detail tentang hal itu.
DJMcMayhem
11

Kapan saja perintah gagal, itu akan membuat ding noise, yang akan membatalkan makro saat ini. Anda dapat (ab) menggunakan ini untuk membuat bentuk lingkaran kasar. Misalnya, jika Anda ingin mengulangi penekanan tombol <foobar>hingga buffer Anda memiliki kurang dari 3 baris di dalamnya. Anda dapat melakukan

qq<foobar>3G``@qq

yang berarti:

qq                 'Start recording in register q
  <foobar>         'Keystrokes
          3G       'Go to line 3. If line 3 doesn't exist, this is effectively a "break" statement.
            ``     'Jump back to previous cursor location
              @q   'Call macro q
                q  'Stop recording

Penting untuk dicatat bahwa jika Anda menguji ini dalam sesi vim, @qefek samping yang mungkin tidak diinginkan, karena makro diambil dari .vim_profile. Anda dapat menyiasati ini dengan beberapa cara berbeda. Mungkin solusi terbaik adalah meluncurkan vim dengan

vim -i NONE

Anda juga dapat menghapus .viminfo.

Jika Anda sudah meluncurkan vim, Anda bisa mengetik

qqq

di awal nol makro keluar.

Kondisi lain yang bisa Anda ganti dengan 3G adalah

f<char>    'Jump to first occurence of <char>. Also see F, t and T

atau

<number>|  'Go to the <number>'th character on the current line.
DJMcMayhem
sumber
8

Ada lebih banyak versi singkat dari perintah ex yang Anda pikirkan. Misalnya, Anda mungkin sudah tahu bahwa :globalbisa disingkat :g, tetapi apakah Anda tahu itu :nnoremapsetara dengan :nn?

Sebaiknya jalankan :h :foosemua perintah ex yang Anda gunakan dalam jawaban untuk melihat apakah ada versi yang lebih pendek.

Gagang pintu
sumber
6
:%s/\n//g

adalah selalu setara dengan

:%s/\n//

yang kebetulan juga setara dengan

:%s/\n

cukup mengejutkan. (Secara umum, tanpa bendera, garis miring terakhir dalam :sekspresi tidak pernah diperlukan.)

Gagang pintu
sumber
2
Ini berfungsi untuk baris baru, tetapi tidak berfungsi untuk karakter apa pun yang dapat muncul lebih dari satu kali dalam satu baris. Misalnya :%s/xtidak menghapus setiap kemunculan x, hanya yang pertama pada setiap baris.
DJMcMayhem
1
Anda juga dapat menggunakan :&&untuk mengulangi perintah pengganti dan benderanya.
DJMcMayhem
6

Katakanlah Anda berada dalam mode sisipkan, dan Anda ingin membuat perintah mode normal tunggal. Anda dapat menulis seperti ini:

isome_text<esc><foobar>gisome_more_text

Jangan lakukan itu. Sebagai gantinya, gunakan <C-o>, yang mengeksekusi satu perintah normal lalu segera kembali ke mode penyisipan.

isome_text<C-o><foobar>some_more_text
DJMcMayhem
sumber
Saya tidak berpikir ruang-ruang itu diperlukan juga
Gugatan Dana Monica
@QPaysTaxes Anda benar, mereka tidak. Saya pikir itu akan membuatnya lebih mudah dibaca. Saya akan mengeditnya.
DJMcMayhem
Anda tidak perlu <CR>setelah <foobar>mengirim perintah?
Dana Gugatan Monica
@QPaysTaxes Hanya jika itu adalah perintah ex atau pencarian. (Misalnya setiap perintah dimulai dengan :, /atau ?)
DJMcMayhem
Oh, salahku. Saya bingung perintah dan mode normal. Cool: D
Dana Gugatan Monica
5

Ada tiga operator "perubahan kasus",

gu    "Convert to lowercase
gU    "Convert to uppercase
g~    "Toggle case

Karena ini adalah operator, mereka mengambil gerakan, jadi untuk mengubah karakter saat ini menjadi huruf kecil yang akan Anda gunakan

gul

Di sinilah trik asyik masuk. :) Jika Anda ingin mengubah huruf satu karakter atau baris saat ini, itu satu byte lebih pendek dalam mode visual. Misalnya gulsetara dengan

vu

Dan gu_(_ adalah baris saat ini) setara dengan

Vu

Trik ini tidak berfungsi untuk beralih, karena v?memicu pencarian mundur dalam mode visual, (seperti halnya v/tetapi bergerak ke arah yang berlawanan) sehingga Anda membutuhkannya vg?. Namun, di sinilah Anda dapat menggunakan ~operator, untuk menyimpan lebih banyak byte! (Terima kasih @ Doorknob untuk menunjukkan ini)

Anda dapat melihat trik ini beraksi pada jawaban vim saya di sini , dan pada jawaban V yang setara pada dan posting.

DJMcMayhem
sumber
1
Jangan lupa ~, yang mengubah huruf karakter di bawah kursor dan memindahkan satu ke kanan!
Gagang Pintu
5

Alfabet dalam 10 penekanan tombol

Semua pujian untuk teknik ini diberikan kepada Lynn, yang pertama kali menggunakannya dalam jawaban ini . Saya menulisnya di sini untuk anak cucu.

Gunakan sepuluh penekanan tombol berikut untuk menarik alfabet huruf kecil:

:h<_␍jjYZZ

(Di mana carriage return, yaitu tombol Enter.)

Penjelasan

:h<_␍membuka bagian bantuan v_b_<_example(contoh pemilihan visual blockwise), yang kebetulan mengandung teks abcdefghijklmnopqrstuvwyxz. jjYbergerak ke bawah ke garis itu dan menariknya, lalu ZZmenutup jendela bantuan.

Jordan
sumber
4

Ketahui register Anda

Menyentak atau menghapus teks ke dalam register tertentu (mis. "aY) Untuk menggunakannya nanti tidak selalu diperlukan. Vim memiliki beberapa register yang secara otomatis diisi dengan subyek berbagai perintah. Ketik :help registersuntuk melihat semuanya, tapi inilah beberapa catatan khusus:

  • Register tanpa nama: ""- Teks terakhir yang ditarik atau dihapus.

  • Register bernomor "0- Teks terakhir yang ditarik.

  • Register bernomor "1- "9- Teks terakhir yang dihapus kecuali jika kurang dari satu baris. Setiap kali "1diisi isinya sebelumnya digeser ke "2dan seterusnya.

  • Register penghapusan kecil: "-- Teks terakhir lebih pendek dari satu baris yang telah dihapus.

  • Teks yang dimasukkan terakhir: ".

Secara khusus, register "-dan "1dapat berguna bersama, memungkinkan Anda untuk menghapus beberapa teks dengan misalnya ddke dalam "1register dan menghapus beberapa teks lainnya Dke dalam "-(tentu saja, semantik tidak identik, tetapi seringkali mereka tidak perlu ).

Semua register bisa sedikit sulit untuk dilacak, tetapi Anda dapat melihat konten semua register Anda kapan saja dengan mengetik :registers.

Jordan
sumber
3

Ini muncul dalam obrolan sebelumnya, jadi saya pikir saya sebaiknya mempostingnya sebagai tip lengkap.

<C-a>dan <C-x>menambah dan mengurangi angka berikutnya di telepon. Ini adalah fitur yang sangat berguna untuk beberapa matematika sederhana, tetapi juga memungkinkan untuk retas kecil yang rapi.

Katakanlah Anda harus melompat ke nomor berikutnya. Sebagai contoh, kita perlu berubah

I need 2 spell better

untuk

I need to spell better

Cara yang jelas adalah melompat ke 2, lalu lakukan:

sto                "Synonymous with 'clto'

Karena ini lebih pendek dari

:s/2/to<cr>

Ada banyak cara untuk melompat ke 2. Misalnya,

/2<cr>
ww 
2w
ee
2e
8|
f2

Serta banyak cara lainnya.

Ini semua adalah 2 (atau lebih) penekanan tombol. Namun, karena <C-a>dan <C-x>tidak hanya angka kenaikan / penurunan, tetapi juga melompat ke nomor berikutnya, kita dapat mengambil byte dengan

<C-a>sto
DJMcMayhem
sumber
3

Gerakan golf

Seringkali jika Anda bekerja dengan blok teks (terutama dalam tantangan ), Anda harus pindah ke karakter pertama atau terakhir dalam buffer. Gdan ggcukup bagus, tetapi ada beberapa hal yang mengganggu. Misalnya, untuk mendapatkan karakter terakhir, Anda perlu G$dan ggtidak akan selalu menempatkan Anda di kolom pertama jika ada spasi putih terkemuka. Berikut adalah beberapa gerakan yang lebih baik, meskipun perhatikan bahwa itu hanya berfungsi jika teks Anda tidak memiliki garis kosong di tengahnya:

  • Karakter pertama buffer: {lebih baik daripada gg0. Jika ada baris kosong di tengah teks, Anda juga bisa menggunakan goyang membawa Anda ke karakter pertama di buffer tidak peduli apa.

  • Karakter terakhir buffer: }lebih baik daripadaG$

Ini juga berfungsi sebagai argumen untuk operator, tetapi perhatikan bahwa itu adalah gerakan karakter-bijaksana, bukan gerakan garis-bijaksana!

DJMcMayhem
sumber
Hlebih golf darigg
Kritixi Lithos
@KritixiLithos kecuali itu Htidak dapat diandalkan. Perilaku itu tergantung pada ukuran jendela yang terlihat dan di mana Anda berada di buffer. (Dipetakan kembali dalam V untuk menghindari kebingungan ini)
DJMcMayhem
2

Lakukan perhitungan dengan register ekspresi

Anda dapat melakukan perhitungan dalam mode normal dan mode insert.

Mode normal

Dalam mode normal, jika Anda mengetikkan @=kursor Anda akan pindah ke baris perintah, di mana Anda dapat memasukkan ekspresi apa pun. Ketika Anda menekan enter, hasil dari ekspresi akan dieksekusi sebagai perintah mode normal.

Misalnya, Anda ingin pergi ke kolom tengah dari baris saat ini. Panggilan fungsi col('$')mengembalikan jumlah kolom dalam baris, sehingga kami dapat melakukan apa dengan mengetik berikut ini:

@=col('$')/2<CR>|

Ketika Anda menekan enter, kursor kembali ke buffer dan vim menunggu operator (seperti |) seolah-olah Anda baru saja memasukkan nomor. Atau, Anda bisa memasukkan ini:

@=col('$')/2.'|'

... tapi tentu saja itu lebih banyak byte.

Masukkan mode

Anda dapat menggunakan register ekspresi dalam mode sisipkan juga, dengan menekan <Ctrl-r>=alih-alih @=. Ini berfungsi sama dalam mode normal, kecuali hasil ekspresi yang Anda masukkan akan dieksekusi dalam mode insert. Misalnya, jika Anda mengetik <Ctrl-r>=col('$')<CR>, jumlah kolom pada baris saat ini akan dimasukkan pada kursor seolah-olah Anda telah mengetiknya.

Untuk informasi lebih lanjut tentang register ekspresi, ketik :help "=.

Menggunakan kembali ekspresi

Ekspresi terakhir yang Anda gunakan disimpan dalam register ekspresi "=,. Mengetik @=<CR>dalam mode normal atau <Ctrl-r>=<CR>dalam mode insert akan mengevaluasi ekspresi lagi, memungkinkan Anda untuk menggunakannya seperti makro.

Lakukan perhitungan dalam substitusi

Anda dapat mengevaluasi ekspresi saat melakukan penggantian ekspresi reguler juga. Yang harus Anda lakukan adalah memulai substitusi Anda dengan \=. Misalnya, Anda ingin memberi nomor pada baris dalam file ini:

foo
bar
baz

Panggilan fungsi line('.')mengembalikan nomor baris saat ini, sehingga pekerjaan itu mudah. Memasuki ini:

:s/^/\=line('.').' '/g<CR>

... menghasilkan hasil yang diinginkan:

1 foo
2 bar
3 baz

Untuk menggunakan grup yang ditangkap dalam ekspresi seperti itu, Anda dapat menggunakan submatch()fungsi, di mana misalnya submatch(0)setara dengan \0dalam substitusi biasa, submatch(1)setara dengan \1, dll. Sayangnya ini memakan banyak penekanan tombol, sayangnya.

Untuk informasi lebih lanjut tentang substitusi ekspresi, ketik :help sub-replace-expression.

Jordan
sumber
Untuk contoh terakhir Anda ada cara yang lebih pendek. Sebagai contoh i1 <esc>bqqywjPb<C-a>@qq@qadalah solusi mode normal murni yaitu 5 byte lebih pendek. Dan jika Anda menggunakan unix, Anda bahkan dapat melakukannya :%!nl. Meski begitu, kiat-kiatnya tetap bagus!
DJMcMayhem
1
Tujuan saya adalah untuk mendemonstrasikan cara menggunakan fitur ini, bukan bagaimana menghitung garis dalam penekanan tombol paling sedikit.
Jordan
1

Anda dapat secara langsung memodifikasi teks makro, yang bisa secara signifikan lebih pendek daripada persyaratan berbelit-belit. Sebagai contoh, katakanlah Anda ingin menempelkan sesuatu n kali, di mana n adalah input pengguna. Saya pertama kali mencoba melakukan ini:

qq/[1-9]<enter><c-x>``p@qq@q

Penjelasan:

qq                             #Start Recording
  /[1-9]<enter>                #Search for a number that isn't 0.
                <c-x>          #Decrement that number
                     ``p       #jump back to your previous location and paste.
                        @q     #Recursive call to macro 'q'
                          q@q  #Stop recording, and run the macro

Ini adalah 18 penekanan tombol, dan cara yang sangat buruk untuk melakukannya. Alih-alih, buka lokasi nomor itu, dan lakukan ini:

Ap<esc>"qdd@q

Penjelasan:

Ap<esc>                 #Append a 'p' to the end of the current line.
       "qdd             #Delete the current line into register q
           @q           #Run macro q.

Ini adalah 9 penekanan tombol, peningkatan besar.

Edit:

Bahkan lebih pendek adalah menjalankan makro untuk nomor Anda, dan kemudian ketik perintah Anda. Sebagai contoh:

"qdd@qp

Penjelasan:

"qdd         #Delete the current line into register q
    @q       #Run register q
      p      #Paste

7 penekanan tombol.

DJMcMayhem
sumber
1
1. Gunakan D, bukan dd. 2. Jika perintah tidak melibatkan register, Anda dapat membuatnya lebih pendek. Misalnya, jika Anda ingin mengulang karakter xsebanyak nomor di bawah kursor, alih-alih "qD@qix<esc>, gunakan D@"ix<esc>.
Gagang Pintu