emacs - segun - tipos de parrafos y ejemplos
¿Cómo consigo que Emacs complete oraciones, pero no párrafos? (10)
Escribí lo siguiente que recorre una región e inserta líneas nuevas. En lugar de usar forward-sentence
que no funcionó para mí, utilizo re-search-forward "[.?!][]/"'')}]*//( //)"
, que encuentra todas las frases seguidas solo por dos espacios (la expresión regular es un sentence-end
modificado). La línea nueva se newline-and-indent
usando newline-and-indent
.
(defun fill-sentences-in-paragraph ()
"Put a newline at the end of each sentence in paragraph."
(interactive)
(save-excursion
(mark-paragraph)
(call-interactively ''fill-sentences-in-region)))
(defun fill-sentences-in-region (start end)
"Put a newline at the end of each sentence in region."
(interactive "*r")
(call-interactively ''unfill-region)
(save-excursion
(goto-char start)
(while (re-search-forward "[.?!][]/"'')}]*//( //)" end t)
(newline-and-indent))))
Para poder corregir texto mal formateado como el ejemplo "chat chat chat ...", fill-sentences-in-region
primeras llamadas unfill-region
que elimina el espacio en blanco que rompe las frases:
(defun unfill-region (beg end)
"Unfill the region, joining text paragraphs into a
single logical line. This is useful, e.g., for use
with ''visual-line-mode''."
(interactive "*r")
(let ((fill-column (point-max)))
(fill-region beg end)))
Utilizo visual-line-mode
y reemplazo mi relleno de párrafo predeterminado Mq
para fill-sentences-in-paragraph
con (global-set-key "/Mq" ''fill-sentences-in-paragraph)
.
He visto al menos dos recomendaciones sobre StackOverflow para insertar nuevas líneas entre oraciones al editar documentos LaTeX. La razón es que la práctica facilita el control de fuente, la diff
y la edición colaborativa.
Estoy básicamente convencido, pero soy flojo, y no quiero tener que pensar en eso.
Así que estoy buscando un hechizo de emacs para manejarlo por mí. Podría ser un modo menor, podría ser un conjunto de variables que deben establecerse.
Creo que lo que no quiero es
-
(set long-lines-auto-wrap ''t)
suave de texto (por ejemplo, utilizando los palangres y(set long-lines-auto-wrap ''t)
). Esto se debe a que no quiero imponer requisitos a los editores de mis colaboradores, y algunas veces uso otras herramientas de Unix para examinar estos archivos.
Creo que lo que quiero es
- Para
fill-paragraph
entre líneas nuevas que parecen marcar el final de una oración. - Una solución que funciona con
auto-fill-mode
sería una ventaja.
Es decir:
chat chat chat.
Una nueva oración
con envoltura tonta que necesita ser arreglada.
Mumble murmura
Transformado a:
chat chat chat.
Una nueva oración con envoltura tonta que necesita ser arreglada.
Mumble murmura
Tus comentarios y sugerencias son apreciados.
Editar: La sugerencia de Jouni K. Seppänen me señaló en LaTeX-fill-break-at-separators
, lo que sugiere que emacs casi sabe cómo hacer esto ya. De todos modos, me voy a leer un código y le informaré. Gracias de nuevo.
Versión más general de la misma pregunta: confrontación del editor: mantener líneas nuevas al final de las oraciones . Gracias, dreeves .
Puede no funcionar en todas las circunstancias, pero:
(defun my-fill-sentence ()
"Fill sentence separated by punctuation or blank lines."
(interactive)
(let (start end)
(save-excursion
(re-search-backward "//(^//s-*$//|[.?!]//)" nil t)
(skip-syntax-forward "^w")
(setq start (point-at-bol)))
(save-excursion
(re-search-forward "//(^//s-*$//|[.?!]//)" nil t)
(setq end (point-at-eol)))
(save-restriction
(narrow-to-region start end)
(fill-paragraph nil))))
Para que funcione con el modo auto-fill-mode
, agrega (setq normal-auto-fill-function ''my-fill-sentence)
a tu gancho de modo LaTeX (creo).
Si coloca un marcador de comentario al final de cada oración, Emacs no sabe mover la siguiente línea dentro del comentario:
chat chat chat.%
A new sentence
with goofed up wrapping that needs to be fixed.%
Mumble mumble%
Entonces Mq llena cada oración por separado, al menos en AUCTeX 11.85. (Si prueba esto en Emacs, parece haber un error donde si este es el primer párrafo en el búfer y escribe Mq, aparece un mensaje de error. Simplemente coloque una nueva línea antes del texto para evitarlo).
Si no desea escribir los caracteres de comentario, puede tomar LaTeX-fill-paragraph y modificarlo para que la puntuación al final de la línea funcione de manera similar a los comentarios.
Si las otras respuestas son demasiado automáticas, aquí hay un enfoque semiautomático. Básicamente, es lo que haría repetidamente si fuera a reformatear manualmente, pero condensado para poder presionar una sola tecla varias veces.
;; - go to the end of the line,
;; - do ^d to suck the previous line onto this one,
;; - make sure there''s only one space between the now-concatenated
;; lines, and then
;; - jump to the end and hit space so that (with auto-fill-mode)
;; the line nicely rewraps itself:
;; (turn on auto-fill-mode with M-x auto-fill-mode)
(defalias ''fill-sentence
(read-kbd-macro "C-e C-d SPC M-x just- one- space RET C-e SPC <backspace>"))
(define-key global-map [f4] ''fill-sentence) ; or whatever key you like
Supongo que sabes elisp.
Hay algunos enfoques que puede tomar:
Enganche en modo
auto-fill-mode
. Hay una gran cantidad de condicionales codificados allí, por lo que podría no funcionar para usted. Puedes jugar potencialmente con laauto-fill-function
y ver si tienes el gancho que necesitas allí.Haga un personaje (probablemente) "eléctrico" para que cuando lo presione, se inserte y luego llame a una función para determinar cómo llenar la línea en la que se encuentra.
Establezca un
after-change-hook
para llamar a una función que determina cómo llenar la oración. Se llamará a esta función después de cada cambio en el búfer, así que hágalo de manera eficiente. (Este mecanismo es utilizado porfont-lock
, así que no te preocupes demasiado. Suena lento, pero realmente no lo es, las personas escriben lentamente).
Una vez que se enganchó en el lugar correcto, solo tiene que implementar la lógica de llenado. La fuente para la sentence-at-point
(de thingatpt
) puede ser instructiva.
De todos modos, nunca he escuchado que alguien haga esto ... pero definitivamente es posible. Como la mayoría de las cosas en Emacs, es simplemente una cuestión de programación simple.
Esto es lo que uso , que en su mayoría fue copiado de Luca de Alfaro :
(defun fill-sentence ()
(interactive)
(save-excursion
(or (eq (point) (point-max)) (forward-char))
(forward-sentence -1)
(indent-relative t)
(let ((beg (point))
(ix (string-match "LaTeX" mode-name)))
(forward-sentence)
(if (and ix (equal "LaTeX" (substring mode-name ix)))
(LaTeX-fill-region-as-paragraph beg (point))
(fill-region-as-paragraph beg (point))))))
Yo unir esto a Mj
con
(global-set-key (kbd "M-j") ''fill-sentence)
Las referencias a "LaTeX"
son para soporte de AUCTeX . Si no usa AUCTeX, let
puede simplificarse a
(let (beg (point))
(forward-sentence)
(fill-region-as-paragraph beg (point)))
Me gusta mucho el macro de Chris Conway, pero solo funciona después de que rompas líneas manualmente cada frase. Soy un chico vago, así que quiero que emacs lo haga por mí. Esta mañana finalmente me senté y examiné el problema. La solución que tengo ahora es hackear la macro fill-region-as-paragraph
incorporada fill-region-as-paragraph
.
Después de aplicar el siguiente truco, una nueva opción newline-after-sentence
se establecerá en verdadero. El Mq
estándar ( fill-paragraph
) se llenará automáticamente y creará saltos de línea entre oraciones. Tenga en cuenta que las pruebas solo se realizan con GNU Emacs 23.3.1. Úselo bajo su propio riesgo.
La macro completa es larga, así que no la publicaré aquí. La idea es agregar los siguientes bucles en fill-region-as-paragraph
...
;; Insert a line break after each sentence
(while (< (point) to)
(forward-sentence)
(if (< (point) to) (fill-newline)))
;; This is the actual filling loop.
(goto-char from)
(let (sentbeg sentend)
(while (< (point) to)
(setq sentbeg (point))
(end-of-line)
(setq sentend (point))
(fill-one-line sentbeg sentend justify) ;; original filling loop
(forward-line)))))
...
Puedes encontrar la macro completa en mi repositorio de git . Algunos detalles también están escritos en mi blog . En caso de que no quiera leer mi pobre inglés, simplemente puede usar
$ curl http://fermi.mycloudnas.com/cgit.cgi/fill/plain/hack.el >> ~/.emacs
para agregar el truco a tus ~/.emacs
y probarlo. Los comentarios y los informes de errores son bienvenidos.
(defun wrap-at-sentences ()
"Fills the current paragraph, but starts each sentence on a new line."
(interactive)
(save-excursion
;; Select the entire paragraph.
(mark-paragraph)
;; Move to the start of the paragraph.
(goto-char (region-beginning))
;; Record the location of the end of the paragraph.
(setq end-of-paragraph (region-end))
;; Wrap lines with ''hard'' newlines (i.e., real line breaks).
(let ((use-hard-newlines ''t))
;; Loop over each sentence in the paragraph.
(while (< (point) end-of-paragraph)
;; Determine the region spanned by the sentence.
(setq start-of-sentence (point))
(forward-sentence)
;; Wrap the sentence with hard newlines.
(fill-region start-of-sentence (point))
;; Delete the whitespace following the period, if any.
(while (char-equal (char-syntax (preceding-char)) ?/s)
(delete-char -1))
;; Insert a newline before the next sentence.
(insert "/n")))))
(global-set-key (kbd "M-q") ''wrap-at-sentences)
He tenido la intención de hacer esto para siempre y recientemente encontré esta publicación de blog que funcionó bastante bien para mí. Así que aquí está (una versión ligeramente modificada de) lo que he estado usando durante unos días.
(defun auto-fill-by-sentences ()
(if (looking-back (sentence-end))
;; Break at a sentence
(progn
(LaTeX-newline)
t)
;; Fall back to the default
(do-auto-fill)))
(add-hook ''LaTeX-mode-hook (lambda () (setq auto-fill-function ''auto-fill-by-sentences)))
;; Modified from http://pleasefindattached.blogspot.com/2011/12/emacsauctex-sentence-fill-greatly.html
(defadvice LaTeX-fill-region-as-paragraph (around LaTeX-sentence-filling)
"Start each sentence on a new line."
(let ((from (ad-get-arg 0))
(to-marker (set-marker (make-marker) (ad-get-arg 1)))
tmp-end)
(while (< from (marker-position to-marker))
(forward-sentence)
;; might have gone beyond to-marker---use whichever is smaller:
(ad-set-arg 1 (setq tmp-end (min (point) (marker-position to-marker))))
ad-do-it
(ad-set-arg 0 (setq from (point)))
(unless (or (looking-back "^//s *")
(looking-at "//s *$"))
(LaTeX-newline)))
(set-marker to-marker nil)))
(ad-activate ''LaTeX-fill-region-as-paragraph)
Un enfoque alternativo sería dejar su archivo .tex como está y usar una herramienta como latexdiff (descrita en esta publicación de StackExchange) en lugar de diff de Unix. Esto produce un archivo .tex con marcas de cambios de seguimiento estilo Word y maneja espacios en blanco correctamente para que no tenga que preocuparse por dónde terminan sus oraciones.