Как я могу определить, является ли текущий символ комментарием для этого основного режима?

12

Я работаю над этой маленькой функцией, которая подтягивает следующую строку к текущей. Я хочу добавить функциональность, чтобы, если текущая строка является комментарием к строке, а следующая строка также является комментарием к строке, символы комментария удаляются после действия «подтягивание».

Пример:

Перед

;; comment 1▮
;; comment 2

призвание M-x modi/pull-up-line

После

;; comment 1▮comment 2

Обратите внимание, что ;;символы удалены, которые были раньше 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)))))

Выше функция работает , но на данный момент, независимо от основного режима, он будет рассматривать /или ;или #как символ комментария: (looking-at "/\\|;\\|#").

Я хотел бы сделать эту линию более умной; специфичный для основного режима.

Решение

Благодаря решению @ericstokes я считаю, что нижеприведенное ниже охватывает все мои варианты использования :)

(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)))))
Каушал Моди
источник
Вы хотите, чтобы это было достаточно умно, чтобы обрабатывать различные начальные и конечные символы комментариев и многосимвольные комментарии (например, C /* ... */)?
erikstokes
Нет, это было все, что мне было нужно. Благодарность!
Каушал Моди
@erikstokes Из любопытства, как бы вы справились с комментариями в стиле C?
Прадхан
Это решение работает с многострочными комментариями тоже сразу, ничего особенного делать не нужно, потому что нам не нужно удалять символы при объединении многострочных комментариев.
Каушал Моди
2
@Pradhan Есть comment-startи comment-endстроки, которые установлены «/ *» и «* /» в c-mode(но не c++-mode). И c-comment-start-regexpэто соответствует обоим стилям. Вы удаляете конечные символы, а затем начало после присоединения. Но я думаю, что мое решение будет заключаться в том uncomment-region, join-lineчтобы comment-regionи Emacs беспокоился о том, что такое символ комментария.
erikstokes

Ответы:

12

Вы можете проверить , если текущий символ является символом комментария с помощью таблицы синтаксиса: (looking-at "\\s<"). Регулярное выражение \\s<сопоставит любой символ с синтаксисом «начало комментария»; \\s>будет соответствовать с синтаксисом «конец комментария».

Другим вариантом является переменная comment-start, которая является строкой, вставленной comment-dwimи друзьями. Обычно это начальный символ комментария плюс пробел.

erikstokes
источник
2

Существует гораздо более простое решение , пожалуйста, изучите мой код по адресу https://github.com/redguardtoo/evil-nerd-commenter/blob/master/evil-nerd-commenter.el

Я не буду копировать / вставлять весь код здесь. но вот ключевые моменты:

  • комментарий имеет свой собственный шрифт face, ищите font-lock-comment-face и font-lock-comment-delimiter-face в моем коде

  • используйте собственный API Emacs, чтобы раскомментировать вторую строку, а затем соедините ее с первой строкой

Он должен работать на любых разумных основных режимах.

Этот трюк не придуман мной. Это на самом деле из собственного кода Emacs (точнее, flyspell). Таким образом, решение должно поддерживать любые основные режимы, которые поддерживает flyspell.

чен бен
источник
3
Чтобы выделить что-то как комментарий, необходимо правильно настроить синтаксическую таблицу, поэтому я сомневаюсь, что это умнее, чем альтернативный взгляд на синтаксис.
васамаса
Я научился этому трюку, читая собственный код Emacs (на самом деле это flyspell), как я задокументировал в своем коде.
Чен бин
0

Если вы ищете эту функцию для кода lisp (Elisp, Clojure, Scheme и Common Lisp), то вам следует попробовать lispy , функция, lispy-fillкоторая вызывает такие вещи.

Если вы ищете эту функцию для другого языка, то вы должны rebox2 (проверено для Cи Python), вызываемая функция rebox-fillили другая вызываемая функция rebox-dwimделают подобные вещи.

Они оба являются отличными пакетами, и они не конфликтуют друг с другом, так как они используются для различных основных режимов, и они оба ( lispy-fillи rebox-dwim) связаны M-q, довольно аккуратно.

CodyChan
источник