Función para eliminar todos los comentarios de un búfer, sin moverlos para matar el anillo

9

Necesito poder eliminar todos los comentarios de un búfer del código elisp. Por ahora, estoy usando:

(goto-char (point-min))
(comment-kill (count-lines (point-min) (point-max)))

Sin embargo, comment-killes una función interactiva, y su uso principal es eliminar un comentario a la vez. Además, tiene efectos secundarios visibles molestos, ya que agrega todos los comentarios que mató al anillo de exterminio.

¿Hay una función que permita eliminar (no matar) algunos o todos los comentarios de un búfer?

T. Verron
fuente
Podrías hacer M-x flush-lines ^\s-*\/\/o algo por el estilo. No es perfecto, pero podría funcionar algunas veces.
wvxvw
@wvxvw Gracias por la sugerencia! Sin embargo, brevemente consideré ir por este camino, y concluí que sería demasiado complicado: las líneas al ras no funcionarían, porque los comentarios pueden no tomar toda la línea (supongo que reemplazar-regexp estaría bien); Más molesto, hay varias sintaxis para los comentarios, y se pueden anidar, lo que (probablemente) queda fuera del alcance de las expresiones regulares.
T. Verron
Por curiosidad, ¿desea que los comentarios se eliminen de forma permanente o simplemente desea eliminarlos temporalmente? ¿Quizás solo quieres esconderlos?
Dibujó el

Respuestas:

11

En general, no hay nada de malo en usar comandos como parte del código elisp. Esas funciones que solo están destinadas a un uso interactivo le (o deberían) advertir sobre eso. Ver next-linepor ejemplo.

Para eliminar, en lugar de matar, solo asegúrese de kill-ringque no haya cambiado:

(goto-char (point-min))
(let (kill-ring)
  (comment-kill (count-lines (point-min) (point-max))))
Malabarba
fuente
Sí, entiendo eso. Mi principal problema con este comando es el kill-ring (que respondes) y los posibles problemas de optimización (que seguirán siendo potenciales si no hay nada con lo que comparar).
T. Verron
7

La respuesta de @ Malabarba parece la solución más simple y elegante. Sin embargo, si hace esto lo suficiente como para garantizar su propia función, también puede adaptarse comment-killpara eliminar sin modificar el anillo de matar. Aquí está el código fuente de comment-killcon el cambio de una sola línea para definir comment-delete:

(defun comment-delete (arg)
  "Delete the first comment on this line, if any.  Don't touch
the kill ring.  With prefix ARG, delete comments on that many
lines starting with this one."
  (interactive "P")
  (comment-normalize-vars)
  (dotimes (_i (prefix-numeric-value arg))
    (save-excursion
      (beginning-of-line)
      (let ((cs (comment-search-forward (line-end-position) t)))
    (when cs
      (goto-char cs)
      (skip-syntax-backward " ")
      (setq cs (point))
      (comment-forward)
      ;; (kill-region cs (if (bolp) (1- (point)) (point))) ; original
      (delete-region cs (if (bolp) (1- (point)) (point)))  ; replace kill-region with delete-region
      (indent-according-to-mode))))
    (if arg (forward-line 1))))

Y aquí hay una función (NB: mínimamente probada) que proporciona alguna funcionalidad adicional, que le permite eliminar comentarios en la línea actual, en la región activa o en todo el búfer:

(defun comment-delete-dwim (beg end arg)
  "Delete comments without touching the kill ring.  With active
region, delete comments in region.  With prefix, delete comments
in whole buffer.  With neither, delete comments on current line."
  (interactive "r\nP")
  (let ((lines (cond (arg
                      (count-lines (point-min) (point-max)))
                     ((region-active-p)
                      (count-lines beg end)))))
    (save-excursion
      (when lines
        (goto-char (if arg (point-min) beg)))
      (comment-delete (or lines 1)))))

No he verificado problemas de rendimiento, pero tal vez hay un pequeño golpe por no tocar el anillo de matar. De todos modos, dudo que note problemas de rendimiento a menos que esté trabajando con un búfer verdaderamente masivo. Pero como es poco probable que use esta función con mucha frecuencia, parece que no valdría la pena trabajar en la optimización.

Dan
fuente
Ah, la función se ejecuta con bastante frecuencia y, a veces, en grandes buffers. Pero la maquinaria de la que forma parte tiene algunos cuellos de botella peores, al menos por ahora.
T. Verron