Elisp untuk menerapkan perintah hanya pada wilayah yang dipilih

18

Katakan, saya punya beberapa kode seperti ini:

(defun some-function ()
  (interactive)
  ;; do something
  )

Sekarang saya ingin some-functionberoperasi hanya pada wilayah yang dipilih di buffer? Bagaimana saya bisa melakukan itu? Juga, dapatkah ada dua jalur kode terpisah untuk melakukan sesuatu jika saya telah memilih beberapa wilayah dan melakukan sesuatu yang lain Jika saya belum memilih.

Sibi
sumber

Jawaban:

22
(defun some-function (beginning end)
  (interactive "r")
  (if (use-region-p)
      (message "The region is active, and is from %d to %d" beginning end)
    (message "The region is still there (from % d to %d), but it is inactive" 
             beginning end)))

Penggunaan (interactive "r")berarti bahwa parameter beginningdan endsecara otomatis akan menerima nilai-nilai dari wilayah awal dan akhir wilayah, masing-masing, ketika fungsi dipanggil. (Anda juga bisa mendapatkan nilai-nilai itu kapan saja menggunakan fungsi region-beginningdan region-end, masing-masing.)

Wilayah selalu ada (jika ada tanda di buffer saat ini), tetapi Anda mungkin tidak berpikir itu ada. Wilayah aktif saat disorot (teks dipilih). Anda dapat menguji apakah wilayah tersebut aktif menggunakan predikat region-active-p. Tetapi tes yang lebih baik biasanya use-region-p, karena (secara default) itu mengembalikan true (non- nil) hanya ketika wilayah tersebut aktif dan tidak kosong (titik dan tanda berbeda).

Awalnya, tidak ada highlight dari wilayah tersebut. Dan untuk waktu yang lama, meskipun penyorotan tersedia, itu bukan perilaku default. Agar penyorotan terjadi, Anda harus transient-mark-modemenghidupkan (atau menyalakan setidaknya untuk sementara). Secara default, transient-mark-modedihidupkan dalam versi Emacs terbaru.

Sangat membantu untuk melihat definisi predikat use-region-p:

(defun use-region-p ()
  (and (region-active-p)
       (or use-empty-active-region
           (> (region-end) (region-beginning)))))

use-empty-active-regionadalah opsi pengguna, yang nilai default-nya adalah nil(true), yang berarti bahwa secara default use-region-ptidak akan mengembalikan true jika wilayah itu kosong. Dalam hal itu, agar benar, akhir wilayah harus lebih besar dari awal (perilaku yang saya jelaskan di atas).

Dan jika kita melihat definisi region-active-p:

(defun region-active-p ()
  (and transient-mark-mode
       mark-active
       (mark)))

Kami melihat bahwa itu mengembalikan true (non- nil) ketika semua ini benar:

  • transient-mark-mode dihidupkan.
  • Tanda aktif ( mark-active).
  • Ada tanda di buffer saat ini.

Tanda aktif sebenarnya adalah tentang semua wilayah yang aktif. Saat aktif, dengan asumsi bahwa transient-mark-modeitu aktif dan ada tanda di buffer saat ini, wilayah tersebut disorot.

Drew
sumber
AFAICS jika tanda diatur ke titik, yaitu wilayah belum diperluas, tanda-aktif adalah nihil. Jadi mark-active dan transient-mark-mode adalah satu-satunya hal yang menambah nilai pada fungsi yang cukup berlebihan ini.
Andreas Röhler
1
@ AndreasRöhler: Tidak. C-SPC M-: mark-active=> t. Anda pasti dapat memiliki wilayah kosong yang tetap aktif.
Drew
Oke terima kasih. Masih berpikir mark-active dan region-active-p --defined sebagai extended zero-- haruslah dibutuhkan.
Andreas Röhler