Como posso detectar se o caractere atual é um caractere de comentário para esse modo principal?


12

Estou trabalhando nessa pequena função que puxa a próxima linha para a linha atual. Desejo adicionar uma funcionalidade para que, se a linha atual for um comentário de linha e a próxima linha também for um comentário de linha, os caracteres do comentário sejam removidos após a ação "pull-up".

Exemplo:

Antes

;; comment 1▮
;; comment 2

Chamando M-x modi/pull-up-line

Depois de

;; comment 1▮comment 2

Observe que os ;;caracteres foram removidos antes 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)))))

A função acima funciona, mas por agora, independentemente do major-mode, que irá considerar /ou ;ou #como um caractere de comentário: (looking-at "/\\|;\\|#").

Eu gostaria de tornar essa linha mais inteligente; modo principal específico.

Solução

Graças à solução @ericstokes, acredito que o abaixo agora cobre todos os meus casos de 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)))))

Deseja que isso seja inteligente o suficiente para lidar com diferentes caracteres de início e fim de comentários e comentários com vários caracteres (por exemplo, C /* ... */)?
— precisa saber é o seguinte

Não, isso era tudo que eu precisava. Obrigado!
— precisa saber é o seguinte

@erikstokes Por curiosidade, como você lidaria com comentários no estilo C?
— Pradhan

Essa solução funciona com comentários de várias linhas também imediatamente, nada de especial precisa ser feito, porque não precisamos excluir nenhum caractere ao ingressar em comentários de várias linhas.
— precisa saber é o seguinte

2
@ Pradhan Existem as strings comment-starte comment-enddefinidas como "/ *" e "* /" em c-mode(mas não c++-mode). E tem c-comment-start-regexpisso que combina com os dois estilos. Você exclui os caracteres finais e o início após a junção. Mas eu acho que a minha solução seria uncomment-region, join-lineo comment-regione deixe Emacs preocupação sobre o caractere de comentário é o que.
— precisa saber é o seguinte

Respostas:


12

Você pode verificar se o caráter atual é um caractere de comentário utilizando a tabela de sintaxe: (looking-at "\\s<"). O regexp \\s<corresponderá a qualquer caractere com a sintaxe "comment start"; \\s>corresponderá àqueles com a sintaxe "fim do comentário".

Outra opção é a variável comment-start, que é a string inserida porcomment-dwim e amigos. Geralmente, é definido como o caractere de início do comentário mais algum espaço.


2

Existe um solução muito mais simples , por favor estude meu código em https://github.com/redguardtoo/evil-nerd-commenter/blob/master/evil-nerd-commenter.el

Não vou copiar / colar todo o código aqui. mas aqui estão os pontos principais:

  • comment tem sua própria fonte, procure font-lock-comment-face e font-lock-comment-delimiter-face no meu código

  • use a própria API do Emacs para descomentar a segunda linha e depois junte-a à primeira linha

Ele deve funcionar em quaisquer modos principais sensíveis.

Este truque não é inventado por mim. Na verdade, é do próprio código do Emacs (mais especificamente, flyspell). Portanto, a solução deve suportar todos os modos principais de flyspell


3
Para destacar algo como comentário, é necessário que a tabela de sintaxe seja configurada adequadamente, por isso duvido que seja mais inteligente que a alternativa de analisar a sintaxe.
— wasamasa

Eu aprendi esse truque lendo o código do Emacs (na verdade, é flyspell), conforme documentado no meu código.
— Chen bin

0

Se você está procurando esse recurso por código lisp (Elisp, Clojure, Scheme e Common Lisp), tente o lispy , uma função chamada lispy-fillfaz esse tipo de coisa.

Se você estiver procurando esse recurso por outro idioma, deverá rebox2 (verificado para Ce Python), uma função chamada rebox-fillou outra função chamadarebox-dwim fazer esse tipo de coisa.

Os dois são ótimos pacotes e não conflitam entre si, pois são usados ​​para modos principais diferentes e estão ambos ( lispy-fille rebox-dwim) vinculados a eles M-q, bem legais.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.