Bagaimana saya bisa mendeteksi jika karakter saat ini adalah karakter komentar untuk mode utama itu?

12

Saya sedang mengerjakan fungsi kecil ini yang menarik baris berikutnya ke baris saat ini. Saya ingin menambahkan fungsionalitas sehingga jika baris saat ini adalah komentar baris dan baris berikutnya juga merupakan komentar baris, maka karakter komentar akan dihapus setelah tindakan "pull-up".

Contoh:

Sebelum

;; comment 1▮
;; comment 2

Panggilan M-x modi/pull-up-line

Setelah

;; comment 1▮comment 2

Perhatikan bahwa ;;karakter dihapus yang sebelumnya comment 2.

(defun modi/pull-up-line ()
  "Join the following line onto the current one (analogous to `C-e', `C-d') or
`C-u M-^' or `C-u M-x join-line'.

If the current line is a comment and the pulled-up line is also a comment,
remove the comment characters from that line."
  (interactive)
  (join-line -1)
  ;; If the current line is a comment
  (when (nth 4 (syntax-ppss))
    ;; Remove the comment prefix chars from the pulled-up line if present
    (save-excursion
      (forward-char)
      (while (looking-at "/\\|;\\|#")
        (delete-forward-char 1))
      (when (looking-at "\\s-")
        (delete-forward-char 1)))))

Fungsi di atas bekerja tetapi untuk sekarang, terlepas dari besar-mode, itu akan mempertimbangkan /atau ;atau #sebagai karakter komentar: (looking-at "/\\|;\\|#").

Saya ingin membuat garis ini lebih cerdas; khusus mode utama.

Larutan

Berkat solusi @ericstokes, saya percaya bahwa di bawah ini sekarang mencakup semua kasus penggunaan saya :)

(defun modi/pull-up-line ()
  "Join the following line onto the current one (analogous to `C-e', `C-d') or
`C-u M-^' or `C-u M-x join-line'.

If the current line is a comment and the pulled-up line is also a comment,
remove the comment characters from that line."
  (interactive)
  (join-line -1)
  ;; If the current line is a comment
  (when (nth 4 (syntax-ppss))
    ;; Remove the comment prefix chars from the pulled-up line if present
    (save-excursion
      (forward-char)
      ;; Delete all comment-start or space characters
      (while (looking-at (concat "\\s<" ; comment-start char as per syntax table
                                 "\\|" (substring comment-start 0 1) ; first char of `comment-start'
                                 "\\|" "\\s-")) ; extra spaces
        (delete-forward-char 1)))))
Kaushal Modi
sumber
Apakah Anda ingin ini cukup pintar untuk menangani berbagai komentar mulai dan akhiri karakter dan komentar multi-karakter (misalnya C /* ... */)?
erikstokes
Tidak, hanya itu yang saya butuhkan. Terima kasih!
Kaushal Modi
@erikstokes Karena penasaran, bagaimana Anda menangani komentar gaya-C?
Pradhan
Solusi ini juga berfungsi dengan komentar multi-baris, tidak ada yang perlu dilakukan karena kita tidak perlu menghapus karakter apa pun ketika bergabung dengan komentar multiline.
Kaushal Modi
2
@Pradhan Ada comment-startdan comment-endstring yang diatur ke "/ *" dan "* /" di c-mode(tetapi tidak c++-mode). Dan ada c-comment-start-regexpyang cocok dengan kedua gaya. Anda menghapus karakter akhir lalu awal setelah bergabung. Tapi saya pikir solusi saya akan uncomment-region, join-lineyang comment-regiondan membiarkan Emacs khawatir tentang apa komentar karakter apa.
erikstokes

Jawaban:

12

Anda dapat memeriksa apakah karakter saat ini adalah komentar karakter dengan menggunakan tabel sintaks: (looking-at "\\s<"). Regexp \\s<akan mencocokkan karakter apa pun dengan sintaks "komentar mulai"; \\s>akan cocok dengan sintaks "komentar akhir".

Opsi lain adalah variabel comment-start, yang merupakan string yang dimasukkan oleh comment-dwimdan teman. Biasanya diatur ke karakter mulai komentar ditambah beberapa ruang.

erikstokes
sumber
2

Ada solusi yang lebih sederhana , silakan pelajari kode saya di https://github.com/redguardtoo/evil-nerd-commenter/blob/master/evil-nerd-commenter.el

Saya tidak akan menyalin / menempelkan semua kode di sini. tetapi inilah poin-poin utamanya:

  • komentar memiliki wajah font sendiri, cari font-lock-comment-face dan font-lock-comment-delimiter-face dalam kode saya

  • gunakan API Emacs sendiri untuk menghapus komentar pada baris kedua, lalu bergabung dengan baris pertama

Ini harus bekerja pada mode utama yang masuk akal.

Trik ini tidak saya temukan. Ini sebenarnya dari kode Emacs sendiri, (lebih khusus, flyspell). Jadi solusinya harus mendukung semua dukungan mode terbang utama mode

chen bin
sumber
3
Untuk menyorot sesuatu sebagai komentar, ini membutuhkan tabel sintaks untuk diatur dengan tepat, jadi saya ragu ini lebih pintar daripada alternatif melihat sintaks.
wasamasa
Saya belajar trik ini dengan membaca kode Emacs sendiri (sebenarnya, itu flyspell), ketika saya mendokumentasikan dalam kode saya.
chen bin
0

Jika Anda mencari fitur ini untuk kode lisp (Elisp, Clojure, Skema dan Common Lisp), maka Anda harus mencoba lispy , sebuah fungsi yang disebut lispy-fillmelakukan hal semacam ini.

Jika Anda mencari fitur ini untuk bahasa lain, maka Anda harus rebox2 (diverifikasi untuk Cdan Python), fungsi yang disebut rebox-fillatau fungsi lain yang disebut rebox-dwimmelakukan hal semacam ini.

Keduanya adalah paket yang bagus, dan tidak saling bertentangan karena keduanya digunakan untuk mode-mode utama yang berbeda, dan keduanya ( lispy-filldan rebox-dwim) terikat M-q, cukup rapi.

CodyChan
sumber