Spec-Zone.ru › Elisp

Двунаправленный вывод

Emacs может отображать текст, написанный на таких сценариях, как арабский, персидский и иврит, чёткий порядок отображения горизонтального текста которых справа налево. Кроме того, фрагменты латинского письма и цифр, встроенные в текст справа налево, отображаются слева направо, а сегменты сценария справа налево, встроенные в текст слева направо (например, арабский или иврит в комментариях или строках в исходном коде программы), отображаются справа налево. Такие смешанные фрагменты текста слева направо и справа налево называются двунаправленным текстом. В этом разделе описываются возможности и параметры редактирования и отображения двунаправленного текста.

Текст хранится в буферах Emacs и строках в логическом (или читательском) порядке, то есть в порядке, в котором человек читал бы каждый символ. В текстах справа налево и двунаправленных текстах порядок отображения символов на экране (называемый визуальным порядком) не совпадает с логическим порядком; позиции символов на экране не возрастают монотонно с позицией в строке или буфере. При выполнении этой переупорядочивания двунаправленных текстов Emacs следует Алгоритму Unicode двунаправленного отображения (также известному как UBA), который описан в Приложении №9 к стандарту Unicode (https://www.unicode.org/reports/tr9/). Emacs предоставляет реализацию класса «Полная двунаправленность» для UBA, соответствующую требованиям стандарта Unicode v9.0. Обратите внимание, однако, что способ, которым Emacs отображает продолжения строк, когда направление текста противоположно направлению основного абзаца, отличается от UBA, который требует выполнения переноса строк перед переупорядочиванием текста для отображения.

Переменная: bidi-display-reordering

Если значение этой локальной переменной буфера не nil (значение по умолчанию), Emacs выполняет переупорядочивание для отображения. Переупорядочивание влияет на текст буфера, а также на строки отображения и строки наложений из текстовых и свойств наложений в буфере (см. Свойства наложений и Свойство отображения). Если значение равно nil, Emacs не выполняет переупорядочивание двунаправленного текста в буфере.

Значение по умолчанию bidi-display-reordering управляет переупорядочиванием строк, которые не поступают напрямую из буфера, включая текст, отображаемый в строках режима (см. Формат строки режима) и строках заголовков (см. Строки заголовков).

Emacs никогда не переупорядочивает текст буфера с однобайтовой кодировкой, даже если bidi-display-reordering имеет значение, отличное от nil в буфере. Это происходит потому, что буферы с однобайтовой кодировкой содержат исходные байты, а не символы, и поэтому им не хватает свойств направленности, необходимых для переупорядочивания. Следовательно, для проверки того, будет ли текст в буфере переупорядочен для отображения, недостаточно проверить значение только bidi-display-reordering. Правильная проверка выглядит так:

 (if (and enable-multibyte-characters
          bidi-display-reordering)
     ;; Buffer is being reordered for display
   )

Однако строки отображения и наложения с однобайтовой кодировкой переупорядочиваются, если их родительский буфер переупорядочен. Это происходит потому, что обычные строки ASCII хранятся в Emacs как однобайтовые строки. Если однобайтовая строка отображения или наложения содержит не- ASCII символы, эти символы считаются имеющими направление слева направо.

Текст, покрытый display текстовыми свойствами, наложениями со свойствами display, значение которых является строкой, и любыми другими свойствами, заменяющими текст буфера, обрабатывается как единый блок при переупорядочивании для отображения. То есть весь фрагмент текста, покрытый этими свойствами, переупорядочивается вместе. Более того, двунаправленные свойства символов в таком фрагменте текста игнорируются, и Emacs переупорядочивает их так, как если бы они были заменены одним символом U+FFFC, известным как символ замены объекта. Это означает, что размещение свойства отображения над частью текста может изменить способ переупорядочивания окружающего текста для отображения. Чтобы предотвратить этот неожиданный эффект, всегда помещайте такие свойства на текст, чья направленность идентична направленности окружающего текста.

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

Точное определение начала и конца абзацев для реализации Emacs UBA определяется следующими двумя локальными переменными буфера (обратите внимание, что paragraph-start и paragraph-separate на это не влияют). По умолчанию обе эти переменные равны nil, и абзацы ограничены пустыми строками, то есть строками, состоящими только из нуля или более пробельных символов, за которыми следует перевод строки.

Переменная: bidi-paragraph-start-re

Если значение не nil, значение этой переменной должно быть регулярным выражением, которое соответствует строке, начинающей или разделяющей два абзаца. Регулярное выражение всегда сопоставляется после перевода строки, поэтому лучше его закрепить, то есть начать с "^".

Переменная: bidi-paragraph-separate-re

Если значение не nil, значение этой переменной должно быть регулярным выражением, которое соответствует строке, разделяющей два абзаца. Регулярное выражение всегда сопоставляется после перевода строки, поэтому лучше его закрепить, то есть начать с "^".

Если вы измените любую из этих двух переменных, вам обычно следует изменить обе, чтобы убедиться, что они последовательно описывают абзацы. Например, чтобы каждая новая строка начинала новый абзац для целей переупорядочивания bidi, установите обе переменные в "^".

По умолчанию Emacs определяет основное направление каждого абзаца, посмотрев на текст в его начале. Точный метод определения основного направления определяется UBA; короче говоря, первый символ в абзаце, имеющий явную направленность, определяет основное направление абзаца. Однако иногда буферу может потребоваться принудительно установить определенное основное направление для своих абзацев. Например, буферы, содержащие исходный код программы, должны принудительно устанавливать отображение всех абзацев слева направо. Вы можете использовать следующую переменную для этого:

Пользовательский параметр: bidi-paragraph-direction

Если значение этой локальной переменной буфера равно символу right-to-left или left-to-right, все абзацы в буфере предполагаются имеющими указанное направление. Любое другое значение эквивалентно значению nil (значение по умолчанию), которое означает определение основного направления каждого абзаца из его содержимого.

Режимы для исходного кода программы должны установить это значение в left-to-right. Режим Prog делает это по умолчанию, поэтому режимы, полученные из режима Prog, не должны устанавливать это явно (см. Основные основные режимы).

Функция: current-bidi-paragraph-direction &optional buffer

Эта функция возвращает направление абзаца в точке в указанном буфере. Возвращаемое значение — символ, либо left-to-right или right-to-left. Если buffer опущен или nil, он по умолчанию устанавливается на текущий буфер. Если локальное значение буфера переменной bidi-paragraph-direction не равно nil, возвращаемое значение будет идентичным этому значению; в противном случае возвращаемое значение отражает направление абзаца, динамически определённое Emacs. Для буферов, чьё значение переменной bidi-display-reordering равно nil, а также для буферов с однобайтовой кодировкой, эта функция всегда возвращает left-to-right.

Иногда требуется переместить точку в строгом визуальном порядке, либо влево, либо вправо от её текущей позиции на экране. Emacs предоставляет примитив для этого.

Функция: move-point-visually direction

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

Функция возвращает новую позицию буфера в качестве своего значения.

Двунаправленное переупорядочивание может иметь неожиданные и нежелательные эффекты, когда две строки с двунаправленным содержимым соприкасаются в буфере или иным образом программно конкатенируются в строку текста. Типичный проблемный случай — когда буфер состоит из последовательностей текстовых полей, разделённых пробелами или знаками препинания, как в режиме Buffer Menu или режиме Rmail Summary. Поскольку знаки препинания, используемые в качестве разделителей, имеют слабую направленность, они принимают направленность окружающего текста. В результате числовое поле, следующее за полем с двунаправленным содержимым, может отображаться слева от предыдущего поля, нарушая ожидаемую компоновку. Существует несколько способов избежать этой проблемы:

  • - Добавьте специальный символ U+200E ОТМЕТКА СЛЕВА НАПРАВО или LRM в конец каждого поля, которое может содержать двунаправленный текст, или добавьте его в начало следующего поля. Функция bidi-string-mark-left-to-right, описанная ниже, пригодится для этой цели. (В абзаце справа налево используйте U+200F ОТМЕТКА СПРАВА НАЛЕВО или RLM.) Это одно из решений, рекомендуемых UBA.
  • - Включите символ табуляции в разделитель поля. Символ табуляции выполняет роль разделителя сегмента при переупорядочивании двунаправленных текстов, вызывая отдельное переупорядочивание текста с обеих сторон.
  • - Разделите поля с помощью свойства display или наложения со значением свойства в формате (space . PROPS) (см. Указанное пространство). Emacs рассматривает это указание отображения как разделитель абзацев и переупорядочивает текст с каждой стороны отдельно.
Функция: bidi-string-mark-left-to-right строка

Эта функция возвращает свой аргумент строка, возможно, изменённый, так, что результат можно безопасно конкатенировать с другой строкой или примыкать к другой строке в буфере, не нарушая относительной компоновки этой строки и следующей за ней на экране. Если строка, возвращаемая этой функцией, отображается как часть абзаца слева направо, она всегда будет отображаться слева от текста, который следует за ней. Функция работает, исследуя символы своего аргумента, и если любой из этих символов может вызвать переупорядочение на экране, функция добавляет к строке символ LRM. Добавляемый символ LRM делается невидимым, присваивая ему свойство invisible со значением t (см. Невидимый текст).

Алгоритм переупорядочения использует двунаправленные свойства символов, хранящиеся как их свойство bidi-class (см. Свойства символов). Программы Lisp могут изменять эти свойства, вызывая функцию put-char-code-property. Однако для этого требуется глубокое понимание UBA, и поэтому это не рекомендуется. Любые изменения двунаправленных свойств символа имеют глобальное влияние: они влияют на все фреймы и окна Emacs.

Аналогично, свойство mirroring используется для отображения соответствующего зеркального символа в переупорядоченном тексте. Программы Lisp могут влиять на зеркальное отображение, изменяя это свойство. Опять же, такие изменения влияют на все отображения Emacs.

Двунаправленные свойства символов могут быть переопределены, вставив в текст специальные управляющие символы направления, ПЕРЕВОД СЛЕВА НАПРАВО (LRO) и ПЕРЕВОД С ПРАВА НАЛЕВО (RLO). Любые символы между RLO и последующим символом новой строки или символом управления ПЕРЕЗАДАНИЕ НАПРАВЛЕНИЯ (PDF), whichever comes first, будут отображаться как если бы они были сильными символами справа налево, то есть они будут перевернуты при отображении. Аналогично, любые символы между LRO и PDF или новой строкой будут отображаться как если бы они были сильными символами слева направо и не будут перевернуты, даже если они являются сильными символами справа налево.

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

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

Функция: bidi-find-overridden-directionality from to &optional object

Эта функция просматривает текст указанного объекта между позициями from (включительно) и to (исключительно) и возвращает первую позицию, где она находит сильный символ слева направо, чьи свойства направления были принудительно установлены для отображения символа справа налево, или сильный символ справа налево, который был принудительно отображён слева направо. Если такие символы не найдены в указанной области текста, она возвращает nil.

Необязательный аргумент объект указывает, какой текст искать, и по умолчанию равен текущему буферу. Если объект не nil, он может быть другим буфером, или строкой, или окном. Если это строка, функция ищет в этой строке. Если это окно, функция ищет в буфере, отображаемом в этом окне. Если буфер, текст которого вы хотите изучить, отображается в каком-то окне, рекомендуется указать его по этому окну, а не передавать буфер функции. Это потому, что указание функции окна позволяет ей правильно учитывать наложения, специфичные для окна, которые могут изменить результат функции, если какой-то текст в буфере покрыт наложениями.

Когда текст, содержащий смешанные символы справа налево и слева направо и двунаправленные управляющие символы, копируется в другое место, он может изменить свой визуальный вид, а также может повлиять на визуальный вид окружающего текста в пункте назначения. Это происходит потому, что переупорядочение двунаправленного текста, заданного UBA, имеет нетривиальные контекстно-зависимые эффекты как на скопированный текст, так и на текст в пункте назначения, который будет его окружать.

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

Функция: buffer-substring-with-bidi-context start end &optional no-properties

Эта функция работает аналогично buffer-substring (см. Содержимое буфера), но она добавляет в начало и конец скопированного текста двунаправленные управляющие символы, необходимые для сохранения визуального вида текста при его вставке в другое место. Необязательный аргумент no-properties, если он не nil, означает удаление свойств текста из копии текста.

Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Bidirectional-Display.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API