Apakah ada paket atau mode pelurusan otomatis untuk Emacs?

15

Ada saat-saat ketika saya mengedit file (manifestasi Wayang, misalnya) di mana saya ingin menyelaraskan konten buffer dengan cepat. Sebagai contoh, saya tahu saya bisa menggunakannyaalign-regexp atau alignuntuk menyelaraskan kode seperti ini, selama saya memilihnya:

# M-x align-regexp "=>" will line everything up nicely 
file { "/etc/foo":
  ensure => present,
  mode => "0666",
  source => "puppet:///modules/example/foo",
}

Tapi yang saya inginkan adalah agar ini terjadi dengan cepat - tanpa harus memilih wilayah atau seluruh buffer. Apakah ada paket atau mode yang akan melakukan ini, atau apakah ini sesuatu yang harus dibangun ke mode yang saya minati?

Sunting: Saya bertanya tentang Wayang dan CFEngine, karena itulah yang saya kode di sebagian besar hari ini dan saya memiliki preferensi yang kuat untuk teks selaras. Namun, saya juga penasaran (dan tidak mengungkapkan ini dengan baik) untuk mengetahui apakah on-the-fly alignment adalah fitur yang umum dalam mode Emacs (terutama dalam mode untuk bahasa pemrograman), atau jika kebanyakan orang menyelaraskan saat menyimpan atau di beberapa titik lain.

Saint Aardvark the Carpeted
sumber
Ada memperluas-wilayah , yang berguna untuk memilih cakupan yang lebih besar secara berturut-turut.
bastibe
1
Bisakah Anda menjelaskan lebih banyak tentang apa yang biasanya Anda selaraskan? Apakah hanya tanda-tanda yang sama dan dalam mode boneka? Anda dapat memodifikasi kode dalam jawaban Emacs SE ini untuk indentasi otomatis oleh @Malabarba untuk mendapatkan yang Anda inginkan. Cukup ganti indent-regiondengan align-to-equalsdan definisikan fungsi ini sebagai (defun align-to-equals (begin end) (interactive "r") (align-regexp begin end "\\(\\s-*\\)=" 1 1 nil)); dan emacs-lisp-mode-hookdengan puppet-mode-hook.
Kaushal Modi

Jawaban:

5

Jika Anda ingin menandai wilayah untuk penyelarasan otomatis, maka itu mungkin tidak terlalu sulit untuk dilakukan dengan sesuatu seperti:

(require 'cl-lib)

(defvar my--auto-align-overlays nil)
(make-variable-buffer-local 'my--auto-align-overlays)

(defun my-auto-align (beg end regexp)
  (interactive "r\nsRegexp: ")
  (let ((ol (make-overlay beg end)))
    (overlay-put ol 'evaporate t)
    (overlay-put ol 'my--auto-align-regexp regexp)
    (overlay-put ol 'modification-hooks '(my--auto-align-function))
    (push ol my--auto-align-overlays)
    (add-hook 'post-command-hook 'my--auto-align-pch nil t)))

(defun my--auto-align-function (ol &rest _args)
  (cl-pushnew ol my--auto-align-overlays)
  (add-hook 'post-command-hook 'my--auto-align-pch nil t))

(defun my--auto-align-pch ()
  (dolist (ol my--auto-align-overlays)
    (align-regexp (overlay-start ol) (overlay-end ol)
                  (concat "\\(\\s-*\\)" (overlay-get ol 'my--auto-align-regexp))
                  1 align-default-spacing))
  (setq my--auto-align-overlays nil)
  (remove-hook 'post-command-hook 'my--auto-align-pch))

Tetapi jika Anda ingin sepenuhnya otomatis, Anda harus menemukan cara untuk mengkarakterisasi daerah mana yang ingin Anda luruskan secara otomatis (dan dengan regexp mana), yang lebih sulit. Saya kira Anda bisa memberikan beberapa regexps, dan kemudian memindai buffer untuk baris berturut-turut yang cocok dengan salah satu regexps itu.

Stefan
sumber
Saya belum pernah menggunakan overlay sebelumnya, tetapi manual Elisp sepertinya mengatakan itu untuk mengubah penampilan - apakah saya mengerti itu? Jika demikian, apakah itu berarti jawaban ini hanya mengubah penampilan buffer, bukan konten sebenarnya dari file setelah disimpan? (Ini yang terakhir yang saya cari, tetapi mengubah penampilan akan menjadi pilihan yang menarik.)
Saint Aardvark the Carpeted
2
@SaintAardvarktheCarpeted Overlay biasanya digunakan untuk mengubah tampilan, tetapi penerapannya lebih dari itu. Dalam jawaban ini (IIUC), overlay digunakan untuk menandai wilayah yang akan disejajarkan (sehingga buffer benar-benar berubah, bukan hanya tampilan). Fungsi my-auto-alignini digunakan untuk mendefinisikan overlay ini (tandai wilayah yang ingin Anda selaraskan). Alasan (saya pikir) Stefan sedang mengalami semua masalah ini adalah karena (tidak seperti indentasi) jika Anda hanya mencoba menyelaraskan seluruh buffer, Anda akan mendapatkan hasil yang tidak diinginkan, jadi Anda perlu menyelaraskan potongan-potongan pada suatu waktu.
Malabarba
3

Mode Wayang menyediakan puppet-align-block. Anda dapat mengatur agar fungsi ini dipanggil secara otomatis, misalnya dengan menambahkannya ke post-command-hooklokal (belum diuji):

(defun puppet-auto-align ()
  (unless (puppet-in-string-or-comment-p)
    (puppet-align-block)))

(define-minor-mode puppet-auto-align-mode
  :init-value nil
  :keymap nil
  :lighter "PAl"
  :group 'puppet-lint
  (if puppet-auto-align-mode
      (add-hook 'post-command-hook #'puppet-auto-align nil 'local)
    (remove-hook 'post-command-hook #'puppet-auto-align 'local)))

(add-hook 'puppet-mode-hook #'puppet-auto-align-mode)

Perhatikan bahwa ada alasan bagus untuk tidak melakukan ini. Ini tidak terlalu pintar, dan akan menimpa penyelarasan manual yang mungkin Anda lakukan di mana saja, yang akan sangat rusak, jika penyelarasan otomatis tidak berfungsi untuk beberapa kode Wayang yang lebih berbelit-belit.

Karenanya - berbicara sebagai pengelola Mode Boneka - saya sarankan untuk tidak melakukannya, dan kami tidak akan membantu Anda atau menerima laporan bug, jika Anda menggunakan kode ini.

Juga, untuk blok sumber daya besar, mungkin lambat, jadi Anda mungkin ingin menggunakan pengatur waktu idle alih-alih post-command-hooksecara langsung.

lunaryorn
sumber