Есть ли способ остановить `fill-абзац` в конце предложения? - PullRequest
6 голосов
/ 26 сентября 2011

Иногда желательно начинать каждое предложение в абзаце с отдельной строки.Например, это облегчает разбор больших текстовых документов, поскольку изменение одного предложения не повлияет на весь абзац.Некоторые системы разметки (например, * roff) также требуют, чтобы каждое предложение начиналось с новой строки.

Есть ли способ, например, путем разумного переопределения paragraph-separate и paragraph-start, сделать fill-paragraph остановкой междупредложения?

(примечание: я использую Emacs 23.3.1)


Обновление: пример разметки mdoc (* roff):

The
.Nm
utility makes a series of passes with increasing block sizes.
In each pass, it either reads or writes (or both) a number of
non-consecutive blocks at increasing offsets relative to the ideal
alignment, which is assumed to be multiples of the block size.
The results are presented in terms of time elapsed, transactions per
second and kB per second.

Это одинабзац с тремя предложениями, каждое из которых начинается на отдельной строке, даже если есть место для первого слова в предыдущей строке.В настоящее время fill-paragraph преобразует это в

The
.Nm
utility makes a series of passes with increasing block sizes.  In each
pass, it either reads or writes (or both) a number of non-consecutive
blocks at increasing offsets relative to the ideal alignment, which is
assumed to be multiples of the block size.  The results are presented
in terms of time elapsed, transactions per second and kB per second.

, чего я хочу избежать.


Обновление: в предложениях и абзацах

Я вижучто мой вопрос немного неясен, потому что я использовал термин «абзац» для обозначения того, что Emacs называет абзацем, и того, что заканчивается как непрерывный блок текста на выходе любого используемого мной процессора (groff, latex и т. д.).Чтобы уточнить,

  • Мне нужно объединить предложения без каких-либо пустых строк между ними;groff не любит пустые строки, в то время как latex рассматривает их как разделители абзацев.
  • Мне нужно fill-paragraph для работы с отдельными предложениями, т.е. я хочу переопределить абзац как нечто, начинающееся после пустой строки иликонец предыдущего абзаца и заканчивается точкой, за которой следует либо символ новой строки, либо по крайней мере два пробельных символа.
  • Я бы хотел, чтобы fill-paragraph разбил блок текста на отдельные предложения, ноЯ не думаю, что это можно сделать легко.

Например, если я наберу следующее:

The
.Nm
utility makes a series of passes with increasing block sizes.
In each pass, it either reads or writes (or both) a number of non-consecutive blocks at increasing offsets relative to the ideal alignment, which is assumed to be multiples of the block size.
The results are presented in terms of time elapsed, transactions per second and kB per second.

, затем переместите точку в строку, которая начинается с "Вкаждый проход "и нажмите M-q, я должен получить следующее:

The
.Nm
utility makes a series of passes with increasing block sizes.
In each pass, it either reads or writes (or both) a number of
non-consecutive blocks at increasing offsets relative to the ideal
alignment, which is assumed to be multiples of the block size.
The results are presented in terms of time elapsed, transactions per second and kB per second.

Обратите внимание, что последнее предложение остается нетронутым.

Ответы [ 3 ]

1 голос
/ 26 сентября 2011

Это DTRT?

(defun separate-sentences (&optional beg end)
  "ensure each sentence ends with a new line.
When no region specified, use current paragraph."
  (interactive (when (use-region-p)
                   (list (region-beginning) (region-end))))
  (unless (and beg end)
    (save-excursion
      (forward-paragraph -1)
      (setq beg (point))
      (forward-paragraph 1)
      (setq end (point))))
  (setq end (if (markerp end)
                end
              (set-marker (make-marker) end)))
  (save-excursion
    (goto-char beg)
    (while (re-search-forward (sentence-end) end t)
      (unless (or (looking-at-p "[ \t]*$")
                  (looking-back "^[ \t]*"))
        (insert "\n")))))

(defun fill-paragraph-sentence-groups (justify)
  "Groups of sentences filled together.  A sentence ending with newline marks end of group."
  (save-excursion
    (save-restriction
      (narrow-to-region (progn (forward-paragraph -1) (point))
                        (progn (forward-paragraph 1) (point)))
      (goto-char (point-min))
      (skip-chars-forward " \t\n")
      (while (not (or (looking-at-p paragraph-separate)
                      (eobp)))
        (fill-region (point)
                     (progn
                       (loop do (forward-sentence 1)
                             until (looking-at "[ \t]*$"))
                       (point))
                     justify)
        (unless (looking-back "^[ \t]*")
          (forward-line 1)))
      t)))

(defun fill-paragraph-sentence-individual (justify)
  "Each sentence in paragraph is put on new line."
  (save-excursion
    (separate-sentences)
    (fill-paragraph-sentence-groups justify)))

;; deployment option 1: add to major-mode hook

(add-hook 'text-mode-hook (lambda ()
                            (set (make-local-variable fill-paragraph-function) 'fill-paragraph-sentence-individual)))

;; deployment option 2: call my-fill-paragraph any where

(defun my-fill-paragraph (arg)
  (interactive "*P")
  (let ((fill-paragraph-function 'fill-paragraph-sentence-individual))
    (fill-paragraph arg)))

Две функции заполнения абзаца представлены выше.Одна группировка предложений, которые не заканчиваются на новой строке вместе.Еще одно разбиение каждого предложения на новую строку.

Я только показываю, как развернуть отдельное предложение, потому что именно этого хочет ОП.Следуйте модели, чтобы развернуть версию групп, если хотите.

1 голос
/ 26 сентября 2011

Как насчет paragraph-start искать любую строку, которая начинается с заглавной буквы:

"\f\\|[     ]*$\\|^[A-Z]"

Обратите внимание, что новая часть - \\^[A-Z]

Это должно работать для большинстваслучаев, вам нужно только следить за редкими случаями, когда у вас есть заглавное среднее предложение, и это предложение оказывается достаточно длинным, чтобы обрываться непосредственно перед этим словом в середине предложения.

РЕДАКТИРОВАТЬ: вы, вероятно,Также необходимо учитывать отступ:

"\f\\|[     ]*$\\|^[    ]*[A-Z]"

Пробел между квадратными скобками содержит пробел и символ табуляции.

РЕДАКТИРОВАТЬ: вам нужно отключить case-fold-search, чтобы это работало,в противном случае заглавные буквы и строчные буквы не различаются в совпадении!

РЕДАКТИРОВАТЬ: если вы хотите отключить поиск по регистру только для этой функции, привяжите следующее к M-q (что вы можете сделать локальноили глобально, как вы считаете нужным).

(defun my-fill-paragraph ()
  (interactive)
  (let ((case-fold-search nil))
    (fill-paragraph)))
0 голосов
/ 26 сентября 2011

Вы можете использовать fill-region, что неудивительно, что заполняет только текущий регион.Исходя из этого, вы можете определить функцию fill-sentence.Я предполагаю, что упрощенный способ обнаружения таких предложений заключается в следующем:

  • Если строка заканчивается на ., ? или !, это конецСтрока предложения.

  • Строка начинает предложение, если ее предшествующая строка либо пуста, либо строка конца предложения.

Это скорееОднако сложно заставить его работать правильно во всех случаях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...