Memformat kurung secara otomatis

9

Saya mencoba untuk membuat fungsi yang menempatkan / meluruskan / inden kurung keriting sesuai dengan pemformatan gaya Allman (untuk pengkodean dalam C).

Secara umum, saya penggemar antarmuka Smartparens tersedia untuk pengguna untuk menyesuaikan fungsionalitas. Saya telah menulis banyak fungsi lain menggunakan antarmuka Smartparens sehingga akan memiliki preferensi yang kuat untuk tidak beralih paket pada saat ini. Yang mengatakan, saya terbuka untuk implementasi paket-agnostik (misalnya, bisa defadvicerelevan di sini?).

Aktif untuk masalah yang dihadapi. Apa tujuan akhirnya? Mari kita anggap kita sedang mengkode dan mencapai negara yang diwakili di bawah ini. Simbol pipa mewakili kursor; Saya telah mengetik header fungsi dan kurung buka {, dan Smartparens secara otomatis menambahkan kurung penutup }. Pada titik ini, saya ingin itu menekan RET...

int main {|}

... mengarah ke yang berikut:

int main
{
    |
}

Saya sudah bisa menulis fungsi yang menghasilkan perilaku ini tetapi hanya berfungsi untuk indentasi tingkat pertama (misalnya, untuk fungsi utama kami dalam contoh di atas). Saya tidak bisa membuatnya berfungsi untuk tingkat indentasi berikutnya (lihat gif):

masukkan deskripsi gambar di sini

Kode yang relevan di bawah ini. Fungsi ini tidak cantik tapi saya pikir itu harus berfungsi ... Baris terakhir adalah antarmuka ke Smartparens.

Ada saran?


(defun my-create-newline-and-enter-sexp (&rest _ignored)
  "Open a new brace or bracket expression, with relevant newlines and indent. "
  (interactive)
  (progn
    (backward-char 2) (newline) (forward-char) (newline)     
    (indent-according-to-mode)                               
    (previous-line 2) (indent-according-to-mode)         
    (next-line) (next-line) (indent-according-to-mode)))      

(sp-local-pair 'c-mode "{" nil :post-handlers '((my-create-newline-and-enter-sexp "RET")))
tukang es
sumber

Jawaban:

11

Emacs-24.4's electric-pair-modemelakukan satu bagian dari apa yang Anda inginkan sudah (mode ini sangat mirip dengan autopair.el, tidak yakin bagaimana itu dibandingkan dengan smartparens). Dan c-toggle-auto-newlineapakah bagian lainnya.

Tapi sayangnya mereka tidak bekerja bersama. Mohon M-x report-emacs-bugagar kami dapat memperbaikinya.

Alih-alih c-toggle-auto-newline, Anda juga dapat menggunakan electric-layout-modedengan pengaturan seperti (setq electric-layout-rules '((?\{ . around) (?\} . around))).

Stefan
sumber
1
dilaporkan! alangkah baiknya jika keduanya bisa bekerja sama.
iceman
7

Terpecahkan. Urutan pergerakan kursor dari versi pertama saya (dalam posting asli) adalah funky.

Sebagai referensi untuk pembaca di masa mendatang, kode berikut harus berfungsi. Itu juga memerlukan paket Smartparens (yang bisa Anda dapatkan dari git-hub). Saya menjalankan Emacs 24.4. Ini bekerja dengan mode indent listrik diaktifkan atau dinonaktifkan.

(defun my-create-newline-and-allman-format (&rest _ignored)
"Allman-style formatting for C."
  (interactive)
  (progn
    (newline-and-indent)
    (previous-line) (previous-line) (search-forward "{") (backward-char) (newline-and-indent)
    (next-line) (indent-according-to-mode)))

Dan Anda juga harus memasukkan yang berikut ini di file init Anda, di suatu tempat setelah memuat paket Smartparens:

(sp-local-pair '(c-mode) "{" nil :post-handlers '((my-create-newline-and-allman-format "RET")))
tukang es
sumber
2
Daripada menggunakan hal-hal seperti previous-linedengan search-forwarduntuk mencoba dan menemukan kembali di mana Anda berada, Anda lebih baik mengingat posisi Anda dalam suatu variabel dan kemudian gunakan saja goto-char.
Stefan
Itu mungkin rute yang lebih kuat. Apakah ada fungsi / variabel / etc yang menurut Anda mungkin membantu dalam konteks ini? Saya hanya bisa memikirkan save-excursiontetapi saya yakin ada orang lain yang tidak saya kenal.
iceman
0

Inilah kode yang saya gunakan, hanya untuk memberi Anda lebih banyak ide untuk mengubah kode Anda:

(defun ins-c++-curly ()
  "Insert {}.
Threat is as function body when from endline before )"
  (interactive)
  (cond ((eq major-mode 'term-mode)
         (term-send-raw-string "{}")
         (term-send-raw-string "^B"))
        ((looking-back "\\()\\|try\\|else\\|const\\|:\\)$")
         (insert " {\n\n}")
         (indent-according-to-mode)
         (forward-line -1)
         (indent-according-to-mode))
        ((region-active-p)
         (let ((beg (region-beginning))
               (end (region-end)))
           (deactivate-mark)
           (goto-char beg)
           (insert "{")
           (goto-char (1+ end))
           (insert "}")))
        (t
         (insert "{}")
         (indent-according-to-mode)
         (backward-char))))

Saya lebih suka gaya penjepit gantung, karena menghemat ruang.

abo-abo
sumber