Jak mogę wykryć, czy bieżący znak jest znakiem komentarza dla tego trybu głównego?

12

Pracuję nad tą małą funkcją, która wyciąga następny wiersz do bieżącego wiersza. Chcę dodać funkcjonalność, aby jeśli bieżący wiersz był komentarzem do wiersza, a następny wiersz był również komentarzem do wiersza, wówczas znaki komentarza są usuwane po akcji „pull-up”.

Przykład:

Przed

;; comment 1▮
;; comment 2

Powołanie M-x modi/pull-up-line

Po

;; comment 1▮comment 2

Pamiętaj, że ;;znaki zostały usunięte wcześniej 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)))))

Powyższa funkcja działa, ale na razie, niezależnie od głównego trybu, rozważy /lub ;lub #jako komentarz charakterze: (looking-at "/\\|;\\|#").

Chciałbym uczynić tę linię bardziej inteligentną; specyficzne dla trybu głównego.

Rozwiązanie

Dzięki rozwiązaniu @ericstokes uważam, że poniżej opisano teraz wszystkie moje przypadki użycia :)

(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
źródło
Czy chcesz, aby był wystarczająco inteligentny, aby obsługiwać różne znaki początku i końca komentarza oraz komentarze wieloznakowe (np. Litery C /* ... */)?
erikstokes
Nie, to było wszystko, czego potrzebowałem. Dzięki!
Kaushal Modi
@erikstokes Z ciekawości, jak poradzisz sobie z komentarzami w stylu C?
Pradhan
To rozwiązanie działa od razu z komentarzami wieloliniowymi, nie trzeba nic specjalnego robić, ponieważ nie musimy usuwać żadnych znaków podczas dołączania komentarzy wielowierszowych.
Kaushal Modi
2
@Pradhan Istnieją ciągi comment-starti comment-endustawione na „/ *” i „* /” w c-mode(ale nie c++-mode). I c-comment-start-regexpto pasuje do obu stylów. Usuwasz znaki końcowe, a następnie początek po dołączeniu. Ale myślę, że moje rozwiązaniem byłoby uncomment-region, i niech Emacs przejmować się komentarz postać jest co. join-linecomment-region
erikstokes,

Odpowiedzi:

12

Można sprawdzić, czy obecna postać jest komentarz postać korzystając z tabeli składni: (looking-at "\\s<"). Wyrażenie regularne \\s<dopasuje dowolny znak ze składnią „komentuj początek”; \\s>dopasuje te ze składnią „koniec komentarza”.

Inną opcją jest zmienna comment-start, czyli ciąg wstawiony przez comment-dwimi znajomych. Zazwyczaj jest ustawiony na znak początkowy komentarza plus spację.

erikstokes
źródło
2

Jest o wiele prostsze rozwiązanie , proszę przestudiuj mój kod na https://github.com/redguardtoo/evil-nerd-commenter/blob/master/evil-nerd-commenter.el

Nie będę tutaj kopiować / wklejać całego kodu. ale oto kluczowe punkty:

  • komentarz ma własną czcionkę, wyszukaj czcionkę-blokuj-komentarz-twarz i czcionkę-blokuj-komentarz-ogranicznik-twarz w moim kodzie

  • użyj własnego interfejsu API Emacsa, aby odkomentować drugą linię, a następnie połącz ją z pierwszą linią

Powinien działać na wszystkich rozsądnych głównych trybach.

Ta sztuczka nie została wymyślona przeze mnie. W rzeczywistości pochodzi z własnego kodu Emacsa (a dokładniej z flyspell). To rozwiązanie powinno obsługiwać wszelkie obsługiwane przez Flyspell tryby głównych trybów

Chen Bin
źródło
3
Aby wyróżnić coś jako komentarz, należy odpowiednio skonfigurować tabelę składni, więc wątpię, czy jest to mądrzejsze niż alternatywa patrzenia na składnię.
wasamasa
Nauczyłem się tej sztuczki, czytając własny kod Emacsa (tak naprawdę to flyspell), jak udokumentowałem w moim kodzie.
chen bin
0

Jeśli szukasz tej funkcji dla kodu lisp (Elisp, Clojure, Scheme i Common Lisp), powinieneś wypróbować lispy , funkcję o nazwie lispy-fillrobi tego rodzaju rzeczy.

Jeśli szukasz tej funkcji w innym języku, powinieneś ponownie wybrać box2 (zweryfikowany dla Ci Python), wywoływana funkcja rebox-filllub inna wywoływana funkcja rebox-dwimtego typu.

Oba są świetnymi pakietami i nie są ze sobą w konflikcie, ponieważ są używane do różnych głównych trybów i oba są ( lispy-filli rebox-dwim) zobowiązane do M-q, całkiem schludne.

CodyChan
źródło