Mengingat ini...

function s:MyFn()
endfunction

command -range MyCommand :call s:MyFn()

... bagaimana saya bisa membedakan antara jenis rentang yang ditentukan untuk suatu perintah (atau fungsi yang dipanggilnya)? Secara khusus, bagaimana cara membedakan antara rentang yang ditentukan sebagai sepasang nomor baris, dan rentang yang ditentukan sebagai sepasang tanda (biasanya '<'>). Dalam semua upaya saya dan hal-hal yang telah saya baca, informasi ini tampaknya mendapatkan banyak segera setelah perintah dipanggil.

Saya memeriksa yang berikut ini, yang mana yang mendekati, tetapi tampaknya lebih rendah dari masalah ini;-

Bagaimana mendeteksi keberadaan seleksi Visual dalam skrip VimL

https://vi.stackexchange.com/questions/11025/

Saya menemukan bahwa jika saya melakukan ini ...

function s:MyFn(range)
  if a:range == 0
    " No range specified
  elseif a:range == 1
    " Single line specified
  else
    " a:range == 2
  endif
endfunction

command -range MyCommand :call s:MyFn(<range>)

Ini setidaknya memecahkan sebagian dari masalah. Tetapi dalam kasus a:range == 2, saya tidak dapat menemukan cara untuk menentukan apakah rentangnya adalah sepasang nomor baris atau sepasang tanda (biasanya, tetapi tidak harus, dari pilihan visual). Jika pemilihan visualnya berdasarkan garis, maka perbedaannya sebagian besar bersifat akademis. Tetapi perbedaan itu penting untuk pemilihan visual karakter dan blok-bijaksana. Jika saya TAHU bahwa seleksi visual sedang berlaku maka saya dapat menentukan jenis seleksi itu. Akar masalah adalah mendeteksi apakah seleksi visual berlaku sama sekali; Saya tidak bisa berasumsi bahwa pemilihan visual digunakan dan menggunakan penanda '< dan '> karena rentangnya dapat ditentukan sebagai dua nomor baris dan penanda pemilihan visual bisa saja merupakan sisa dari sebelumnya (tidak terkait) penggunaan

vim
0
Rich 11 Mei 2021, 14:15

2 jawaban

Jawaban Terbaik

Rentang diperluas ke sepasang nomor baris sebelum digunakan oleh perintah atau fungsi sehingga rentang asli secara efektif hilang pada saat Anda menggunakan nilai yang diperluas.

:help getcmdline() dapat digunakan untuk… mendapatkan baris perintah mentah, termasuk rentang, tetapi hanya dapat digunakan dalam pemetaan mode baris perintah sehingga Anda harus sedikit kreatif. Berikut ini cuplikan cepat dan kotor untuk Anda mulai:

" save the current range in a global variable
" insert the name of your custom command for further typing
function! FirstStep()
    let g:my_range = getcmdline()
    return 'MyCommand'
endfunction

" the actual implementation of the desired functionality
" do what you have to do with g:my_range
function! SecondStep()
    if g:my_range == "'<,'>"
        echo "range is purely visual"
    elseif g:my_range =~ '\d\+,\d\+'
        echo "range is purely numerical"
    else
        echo "range is neither purely visual nor purely numerical"
        echo "support for other ranges not yet implemented"
    endif
endfunction

" expression mapping
" inserts the result of FirstStep() in the command-line
cnoremap <expr> MyCommand FirstStep()

" the actual command that calls the actual function
" that actually implements the desired functionality
command! -range=% MyCommand call SecondStep()

Ini terlihat seperti ini:

example

1
romainl 11 Mei 2021, 19:24

Setelah Anda menekan : (dengan tombol atau dengan pemetaan), Anda sudah masuk ke mode baris perintah secara efektif meninggalkan mode sebelumnya (baik itu Visual atau Normal). Jadi tidak ada cara bagi perintah/fungsi Anda untuk membedakan antara "dapatkan di sini dari Visual atau dari mode lain".

Sebenarnya, Anda memiliki dua opsi: buat perintah selalu untuk menggunakan mode visual terakhir (diam-diam mengabaikan rentang apa pun yang diteruskan pada baris perintah); atau mulai dari pemetaan mode Visual (mungkin dengan "expr" atau "cmd" dll.).

1
Matt 11 Mei 2021, 11:54