Come posso rilevare se il personaggio attuale è un personaggio di commento per quella modalità principale?


12

Sto lavorando a questa piccola funzione che porta la riga successiva alla riga corrente. Voglio aggiungere una funzionalità in modo che se la riga corrente è un commento di riga e la riga successiva è anche un commento di riga, i caratteri del commento vengono rimossi dopo l'azione "pull-up".

Esempio:

Prima

;; comment 1▮
;; comment 2

chiamata M-x modi/pull-up-line

Dopo

;; comment 1▮comment 2

Nota che i ;;personaggi vengono rimossi prima 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)))))

La funzione di cui sopra funziona, ma per il momento, a prescindere dal maggiore-mode, si prenderà in considerazione /o ;o #come un carattere di commento: (looking-at "/\\|;\\|#").

Vorrei rendere questa linea più intelligente; specifico della modalità principale.

Soluzione

Grazie alla soluzione di @ericstokes, credo che il seguito ora copra tutti i miei casi d'uso :)

(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)))))

Vuoi che sia abbastanza intelligente da gestire diversi caratteri di inizio e fine dei commenti e commenti multi-carattere (ad es. C /* ... */)?
erikstokes

No, era tutto ciò di cui avevo bisogno. Grazie!
Kaushal Modi,

@erikstokes Per curiosità, come gestiresti i commenti in stile C?
Pradhan,

Questa soluzione funziona anche con i commenti su più righe, non è necessario eseguire operazioni speciali perché non è necessario eliminare alcun carattere quando si uniscono commenti su più righe.
Kaushal Modi,

2
@Pradhan Ci sono le stringhe comment-starte comment-endche sono impostate su "/ *" e "* /" in c-mode(ma non c++-mode). E c'è c-comment-start-regexpche corrisponde a entrambi gli stili. Stai eliminando i caratteri finali e quindi l'inizio dopo l'adesione. Ma penso che la mia soluzione sarebbe quella di uncomment-region, join-linela comment-regione lasciare Emacs preoccuparsi di ciò che carattere di commento è ciò.
erikstokes,

Risposte:


12

È possibile verificare se il carattere corrente è un commento di carattere utilizzando la tabella sintassi: (looking-at "\\s<"). La regexp \\s<corrisponderà a qualsiasi personaggio con la sintassi "comment start"; \\s>corrisponderà a quelli con sintassi "fine commento".

Un'altra opzione è la variabile comment-start, che è la stringa inserita da comment-dwime dagli amici. In genere è impostato sul carattere iniziale del commento più uno spazio.


2

C'è una soluzione molto più semplice , per favore studia il mio codice su https://github.com/redguardtoo/evil-nerd-commenter/blob/master/evil-nerd-commenter.el

Non copierò / incollerò tutto il codice qui. ma qui ci sono i punti chiave:

  • il commento ha la sua faccia font, cerca font-lock-comment-face e font-lock-comment-delimitatore-face nel mio codice

  • utilizzare la propria API di Emacs per decommentare la seconda riga, quindi unirla alla prima riga

Dovrebbe funzionare su tutte le principali modalità sensibili.

Questo trucco non è stato inventato da me. In realtà proviene dal codice di Emacs, (più specificamente, flyspell). Quindi la soluzione dovrebbe supportare qualsiasi supporto flyspell per le modalità principali


3
Per evidenziare qualcosa come un commento, richiede che la tabella della sintassi sia configurata in modo appropriato, quindi dubito che sia più intelligente dell'alternativa di guardare la sintassi.
Wasamasa,

Ho imparato questo trucco leggendo il codice di Emacs (in realtà è flyspell), come ho documentato nel mio codice.
chen bin,

0

Se stai cercando questa funzione per il codice lisp (Elisp, Clojure, Scheme e Common Lisp), allora dovresti provare lispy , una funzione chiamata lispy-fillfa questo tipo di cose.

Se stai cercando questa funzione per un'altra lingua, allora dovresti rebox2 (verificato per Ce Python), una funzione chiamata rebox-fillo un'altra funzione chiamata rebox-dwimfare questo tipo di cose.

Sono entrambi fantastici pacchetti, e non sono in conflitto tra loro poiché sono usati per diverse modalità principali, e sono entrambi ( lispy-fille rebox-dwim) legati M-q, piuttosto puliti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.