Help

Автор Рязанцев, 8 июля 2024, 10:26

0 Пользователи и 1 гость просматривают эту тему.

Рязанцев

 Всех приветствую. Окажите помощь, мучаюсь с текстовом документом формата .odt. Пытаюсь через найти и заменить найти в конце строки (внутри абзаца) так называемые весящие предлоги (а,в,на,по,где и т.д.) и снести их на следующую строку, короче говоря заменить \s на \n но стала проблема что не могу найти конец строки (\s.{1,3}\s) и заменить надо только первый \s. Подскажите решение.

mikekaganski

Это невозможно. Конец строки - это не часть текста, и её нельзя найти поиском.

Вы можете заменить пробелы после всех этих предлогов на неразрывные пробелы.
С уважением,
Михаил Каганский

Рязанцев

Но тогда он по всему тексту их скинет

Рязанцев

А макрос такую проблему решить не может?

gabix

#4
Нет. Ещё раз: конец строки (если это не разрыв строки) — не часть текста, он определяется динамически. То есть, это не объект, который можно передать макросу на обработку.

Можно, конечно, попытаться поизвращаться следующим образом: прикинуть, сколько в конкретном документе (то есть при заданной гарнитуре/кегле/разрядке) символов (включая пробелы) вмещается в среднем в строку (скажем, 60), и попытаться провести поиск/замену только тех предлогов, перед которыми 60 - (1 + длина предлога) символов, но тут тоже избирательность будет крайне низкой.

gabix

Да, вспомнилось, что встречал как-то макрос, который по строкам разбивал абзац, то есть каждую строку делал отдельным абзацем. В таком случае найти предлоги на концах строк = новых абзацев будет просто. К сожалению, найти его у себя не могу.

mikekaganski

Цитата: Рязанцев от  8 июля 2024, 10:33Но тогда он по всему тексту их скинет
А нужно по части? Замените в выделенном фрагменте.
Цитата: Рязанцев от  8 июля 2024, 10:34А макрос такую проблему решить не может
Вы собираетесь разрывать абзац в каждом таком месте? Это же приведёт к куче других проблем. Например, в случае выровненных абзацев придётся делать последнюю строку абзаца тоже выровненной для таких разрывов, возникнут предупреждения проверки грамматики и т.п.

Да, макрос может это сделать. У видимого курсора есть знание о разбиении на строки.
С уважением,
Михаил Каганский

gabix

Так потом можно абзацы можно собрать снова, с этим хорошо справляется OOoFBTools.

mikekaganski

Зачем снова собрать? Идея - перенести предлог на следующую строку. Собрав снова, предлог вернётся назад.
С уважением,
Михаил Каганский

gabix

Я плохо выразил свою идею. Вот что можно:

1) разбить абзацы построчно;
2) найти предлоги на концах этих абзацев, подставить после них неразрывный пробел;
3) собрать абзацы;
4) заменить в них неразрывный пробел + пробел (этот пробел появится после сборки) на один неразрывный пробел.

И я не говорю, что это здорово, но как вариант.

mikekaganski

А, тогда можно без разрыва абзаца: искать конец строки, искать висящий предлог, вставлять неразрывный пробел.
С уважением,
Михаил Каганский

Рязанцев

Честно я не профессионал в этом, как это прописать

Рязанцев

Я так понимаю что неразрывный пробел должен стоять после предлога в данном случае

economist

Книгоиздатели по висящим предлогам не парятся (или за отдельную плату, которая редко кому нравится).
Руб. за сто, что Питоньяк
Любит водку и коньяк!
Потому что мне, без оных, -
Не понять его никак...

mikekaganski

#14
sub unhangPrep
  vcursor = ThisComponent.CurrentController.ViewCursor
  text = vcursor.Text
  vcursor.jumpToFirstPage()
  classification = CreateUNOService("com.sun.star.i18n.CharacterClassification")
  iterator = CreateUNOService("com.sun.star.i18n.BreakIterator")
  toolkit = CreateUNOService("com.sun.star.awt.Toolkit")

  do
    vcursor.gotoEndOfLine(false)
    tcursor = text.createTextCursorByRange(vcursor.Start)
    do
      if not tcursor.goLeft(1, true) then exit do
    loop while (Left(tcursor.String, 1) = " ")
    if (Len(tcursor.String) and Left(tcursor.String, 1) <> " ") then tcursor.goRight(1, true)
    if (Len(tcursor.String)) then
      wcursor = text.createTextCursorByRange(tcursor.Start)
      ' XWordCursor.gotoStartOfWord uses com.sun.star.i18n.WordType.DICTIONARY_WORD,
      ' so may jump over things like "№", or may select a "word" like ".".
      ' Thus we simply get four previous characters, and use break iterator manually.
      wcursor.goLeft(1, true)
      locale = wcursor.CharLocale
      wcursor.goLeft(3, true)
      word = wcursor.String
      if (Len(word)) then
        ctype = classification.getType(Right(word, 1), 0)
        if (ctype <> com.sun.star.i18n.UnicodeType.DASH_PUNCTUATION and _
            ctype <> com.sun.star.i18n.UnicodeType.INITIAL_PUNCTUATION and _
            ctype <> com.sun.star.i18n.UnicodeType.FINAL_PUNCTUATION and _
            ctype <> com.sun.star.i18n.UnicodeType.CONNECTOR_PUNCTUATION and _
            ctype <> com.sun.star.i18n.UnicodeType.OTHER_PUNCTUATION and _
            ctype <> com.sun.star.i18n.UnicodeType.START_PUNCTUATION and _
            ctype <> com.sun.star.i18n.UnicodeType.END_PUNCTUATION) then
          wordBounds = iterator.getWordBoundary(word, Len(word), locale, com.sun.star.i18n.WordType.ANYWORD_IGNOREWHITESPACES, false)
          wordLen = wordBounds.endPos - wordBounds.startPos
          if (wordBounds.endPos = Len(word) and wordLen > 0 and wordLen <= 3) then
            tcursor.String = Chr(&hA0)
            toolkit.processEventsToIdle() ' allow re-layout
          end if
        end if
      end if
    end if
    do while (vcursor.goRight(1, false))
      if (not vcursor.isAtEndOfLine()) then exit do
    loop
  loop while (not vcursor.isAtEndOfLine())
end sub
С уважением,
Михаил Каганский