Редактирование программ – ЧАСТЬ 3

число, n     Первые n аргументов этой функции считаются отличительными аргументами, остальные рассматриваются как тело выражения. Строка в этом выражении отступается в соответствии с тем, является ли в ней первый аргумент отличительным или нет. Если аргумент является частью тела, то строка отступается на lisp-body-indent столбцов больше,  чем  открывающая  скобка, начинающая содержащее   ее выражение.  Если  аргумент является отличительным, и это первый или второй аргумент, то отступ делается на вдвое большее число дополнительных  столбцов. Если аргумент отличителен и не является первым или вторым, то для этой строки применяется стандартный шаблон.

символ, символ

символ должен быть именем функции; эта функция вызывается для вычисления отступа строки в пределах этого выражения. Функция получает два аргумента:

состояние Значение, возвращаемое  из  parse-partial-sexp  (это  примитив Лиспа для подсчета величины отступов и вложенностей), когда она делает разбор вплоть до начала этой строки.

позиция     Позиция, с которой начинается строка, в которой делается отступ.

Она должна возвращать либо число, которое равно количеству столбцов отсту-

па для этой строки, либо список, чей головной элемент является таким числом.

Отличие между  возвращением  числа и возвращением  списка заключается в том, что число говорит, что все следующие  строки того же уровня вложенности должны получать такой же  отступ, как эта строка; список говорит,  что следующие строки могут требовать отличные отступы.  Это важно, если отступы подсчитываются с помощью C-M-q; если значение — это число, то C-M-q не нуждается в пересчете отступа для следующих строк до конца списка.

22.5.4  Команды для отступов в Си

Вот команды для создания отступов в режиме C и родственных с ним:

C-c C-q      Обновляет отступ в текущем определении функции верхнего уровня или соби-

рает в одно целое объявление типа (c-indent-defun).

C-M-q        Обновляет отступ в каждой строке сбалансированного выражения, которое следует после точки (c-indent-exp).  Префиксный аргумент подавляет проверку ошибок и вывод предупреждений о недопустимом синтаксисе.

hTABi              Обновляет отступ в текущей строке и/или в некоторых случаях вставляет знак табуляции (c-indent-command).

Если c-tab-always-indent равна t, эта команда всегда обновляет отступ те-

кущей строки и не делает ничего больше. Это принимается по умолчанию.

Если эта переменная  равна nil,  данная команда обновляет отступ  текущей строки, только если точка находится с левого края или на отступе; в противном случае она вставляет табуляцию (или эквивалентное число пробелов, если indent-tabs-mode равна nil).

Любое другое значение (не nil или t) означает, что нужно всегда обновлять отступ строки, а также вставлять знак табуляции, если точка находится внутри комментария, строки или директивы препроцессора.

C-u hTABi     Обновляет отступ текущей строки в соответствии с ее синтаксисом; кроме того, жестко смещает все остальные  строки выражения, начинающегося на текущей строке. См. Раздел 22.5.2 [Многострочный отступ], с. 209.

Чтобы обновить отступ  всего текущего буфера, наберите  C-x h C-M-\.   Это сначала выделяет  весь буфер как область, а затем обновляет отступ в этой области.

Чтобы обновить отступ в текущем блоке, используйте C-M-u C-M-q. Эта команда пере-

мещает к началу блока и делает в нем отступ.

22.5.5  Настройка отступа в Си

Режим C и родственные режимы используют простой, но гибкий механизм для настройки  отступа.   Этот  механизм  работает в два этапа:  сначала строки классифицируются синтаксически в соответствии с их содержимым и контекстом; затем каждому виду синтаксических конструкций привязывается значение сдвига, который вы можете настроить.

22.5.5.1  Шаг 1 — синтаксический  анализ

На первом шаге механизм отступов в Си смотрит на строку перед той, в которой вы в данный момент делаете отступ, и определяет синтаксические  компоненты конструкции на этой строке.  Он строит список этих синтаксических компонентов, где каждый компонент содержит синтаксический символ и, иногда, позицию в буфере. Некоторые  синтаксические символы описывают грамматические элементы, например statement и substatement; другие описывают положения в составе грамматических элементов, например class-open и knr-argdecl.

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

Вот пример.  Предположим, что у нас есть следующий  код в буфере с режимом C++

(номера строк в действительности  не появляются в буфере):

1:  void  swap (int& a,  int& b)

2:  {

3:      int tmp = a;

4:      a = b;

5:      b = tmp;

6:  }

Если вы наберете C-c C-s (что запускает команду c-show-syntactic-information) на строке 4, будет показан результат работы механизма отступов для этой строки:

((statement  . 32))

Это указывает на то,  что  данная строка является оператором, и она имеет отступ относительно позиции 32 в буфере, то есть относительно ‘i’ в int на строке 3. Если вы переместите курсор к строке 3 и наберете C-c C-s, это покажет следующее:

((defun-block-intro . 28))

Это указывает на то, что строка int — это первый оператор в блоке,  и она имеет отступ относительно позиции 28, то есть фигурной скобки сразу после заголовка функции.

Вот еще один пример:

1:  int add (int val, int incr, int doit)

2:  {

3:      if (doit)

4:          {

5:             return (val + incr);

6:          }

7:      return (val);

8:  }

Если в строке 4 набрать C-c C-s, вы увидите вот что:

((substatement-open . 43))

Это говорит,  что  данная фигурная  скобка открывает блок подоператора.  Кстати, подоператор — это строка после операторов  if, else,  while,  do, switch,  for, try, catch, finally или synchronized.

Внутри команд для отступа в Си, после того как строка синтаксически проаналицирована, описание результатов анализа хранится в списке в переменной c-syntactic-context. Каждый  элемент этого списка — это синтаксический компонент: пара, содержащая синтаксический символ и (возможно) соответствующую ему позицию в буфере. В списке компонент может несколько элементов; как правило только один из них имеет позицию в буфере.

22.5.5.2  Шаг 2 — подсчет отступа

Механизма отступов в Си вычисляет величину отступа для текущей строки, используя список синтаксических компонентов, c-syntactic-context, полученный из синтаксического анализа. Каждый  компонент — это пара, которая содержит синтаксический символ и может содержать позицию в буфере.

Каждый  компонент дает вклад в окончательный отступ  строки двумя путями.   Во-

первых, синтаксический символ определяет элемент c-offsets-alist, это ассоциативный

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

Следующие примеры демонстрируют  работу механизма отступов в языке Си:

1:  void  swap (int& a,  int& b)

2:  {

3:      int tmp = a;

4:      a = b;

5:      b = tmp;

6:  }

Предположим, что точка находится на строке 3, и вы нажимаете hTABi, чтобы обновить в этой строке отступ. Как объяснялось выше (см. Раздел 22.5.5.1 [Синтаксический анализ], с. 211), синтаксическим компонетом этой строки будет:

((defun-block-intro . 28))

В данном случае при подсчете отступа сначала просматривается defun-block-intro в ассоциативном списке c-offsets-alist.   Предположим, что там найдено число 2; оно добавляется к общему (инициализированному  нулем), выдавая общей обновленный отступ в 2 пробела.

Следующий шаг — найти номер столбца для позиции 28 в буфере. Поскольку фигурная скобка в позиции 28 расположена в нулевом столбце, к общему числу добавляется 0. Так как  в этой строке  есть только один синтаксический компонет, общий отступ  для этой строки равен двум пробелам.

1:  int add (int val, int incr, int doit)

2:  {

3:      if (doit)

4:          {

5:             return(val + incr);

6:          }

7:      return(val);

8:  }

Если вы нажмете hTABв строке 4, повторяется такой же процесс, но с иными данными.

Список синтаксических компонентов для этой строки таков:

((substatement-open . 43))

Здесь первое, что делается для посчета отступа, — ищется символ substatement-open в c-offsets-alist.  Будем считать, что сдвиг для этого символа равен 2. В этом месте промежуточное  общее значение  равно 2 (0 + 2 = 2).   Затем к  нему добавляется  номер строки позиции 43 в буфере, где  стоит ‘i’  из if на строке  3.  Этот знак расположен во втором столбце на строке. Итого в сумме получается 4 пробела.

Если при анализе строки появляется синтаксический символ, который отсутствует в c-offsets-alist, он игнорируется; и это является ошибкой, если кроме того переменная c-strict-syntax-p отлична от nil.

22.5.5.3  Изменение стиля  отступов

Есть два способа  настроить стиль отступов для режимов, подобных режиму C. Вопервых, вы можете выбрать один из предопределенных стилей, каждый из которых задает сдвиги для всех синтаксических символов. Для большей гибкости вы можете  настоить обработку отдельных синтаксических символов. См. Раздел 22.5.5.4 [Синтаксические  символы], с. 214, перечень всех определенных  синтаксических символов.

M-x c-set-style hRETстиль hRETi

Выбирает предопределенный стиль стиль.  Чтобы получить перечень поддерживаемых стилей, наберите при вводе стиля знак ?; чтобы узнать, как выглядит тот  или иной стиль, выберите его и примените  для фрагмента кода на Си.

C-c C-o символ hRETсдвиг hRETi

Устанавливает сдвиг для синтаксического символа символ (c-set-offset).

Второй аргумент, сдвиг, указывает новую величину сдвига.

Размер отступа  для каждого  синтаксического символа управляется переменной  coffsets-alist. Ее значение — это ассоциативный список, и каждый элемент этого списка имеет форму  (синтаксическийсимвол . сдвиг).   Изменяя сдвиги для разных синтаксических символов,  вы можете  настраивать отступы в мельчайших подробностях. Чтобы изменить этот ассоциативный список, используйте c-set-offset (смотрите ниже).

Источник: Ричард Столмен, Руководство по GNU Emacs

Похожие посты:

Вы можете оставить комментарий, или ссылку на Ваш сайт.

Оставить комментарий