[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
В этой главе, мы закрепим знания, полученные в предыдущих главах,
изучив несколько более сложных функций. Функция copy-to-buffer
иллюстрирует использование в одном определении двух выражений
save-excursion
, а функция insert-buffer
показывает
использование * в выражении interactive
, использование
or
и важную разницу между именем и объектом, к которому имя
относится.
5.1 Определение copy-to-buffer
С set-buffer
,get-buffer-create
.5.2 Определение insert-buffer
Только-чтение, и функция or
.5.3 Полное определение beginning-of-buffer
Использование goto-char
,point-min
, иpush-mark
.
5.4 Обзор 5.5 Упражнения с &optional
аргументом
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
copy-to-buffer
После изучения принципа работы append-to-buffer
, легко понять и
copy-to-buffer
. Эта функция копирует текст в буфер, но вместо
того чтобы добавить его во второй буфер, она заменяет предыдущий текст
в том буфере. Код для функции copy-to-buffer
почти такой же,
как и код для append-to-buffer
, отличаясь только использованием
erase-buffer
и второй формы save-excursion
.
(See section The Definition of append-to-buffer
,
для описания append-to-buffer
.)
Тело copy-to-buffer
выглядит следующим образом
... (interactive "BCopy to buffer: \nr") (let ((oldbuf (current-buffer))) (save-excursion (set-buffer (get-buffer-create buffer)) (erase-buffer) (save-excursion (insert-buffer-substring oldbuf start end))))) |
Все это очень похоже на то, что мы видели в append-to-buffer
,
только после того, как мы переключились в новый буфер куда и
собираемся копировать текст, исходные тексты этих двух функции
расходятся --- в функции copy-to-buffer
уничтожается
первоначальное содержание буфера. (Обычно это называют замещением
--- чтобы заместить текст, Emacs стирает предыдущий текст и затем
вставляет новый). После того, как стерто прежнее содержание буфера,
второй раз используется save-excursion
и вставляется новый
текст.
Почему же save-excursion
используется дважды? Давайте
внимательно посмотрим что же делает эта функция.
Схематично, тело copy-to-buffer
выглядит следующим образом:
(let (связать- |
Первое использование save-excursion
вернет Emacs в буфер из
которого мы копируем текст. Это ясно, и точно такой же код
использовался в append-to-buffer
. Зачем же использовать эту
функцию второй раз? Причина этого заключается в том, что
insert-buffer-substring
всегда оставляет точку в конце
вставленного региона текста. Второе использование
save-excursion
заставляет Emacs оставить точку в начале
вставленного текста. В большинстве случаев, пользователи предпочитают
обнаружить точку в начале вставленного текста. (Конечно, функция
copy-to-buffer
вернет пользователя в первоначальный буфер когда
завершит свою работу --- но если пользователь потом
переключится в тот буфер, то точка будет в начале текста. То есть
второе использование save-excursion
применяется для удобства).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
insert-buffer
insert-buffer
--- еще одна функция связанная с буферами.
Эта команда копирует другой буфер в текущий буфер. Это обратное
действие, если сравнивать с append-to-buffer
и
copy-to-buffer
, поскольку они копируют регион текста из
текущего буфера в другой буфер.
Кроме того, код этой функции иллюстрирует использование
interactive
с буфером который может быть
только-для-чтения и важную разницу между именем объекта и самим
объектом. Вот и исходный текст этой функции:
(defun insert-buffer (buffer) "Вставить после точки содержимое BUFFER. Поставить метку после вставленного текста. BUFFER может быть буфером или именем буфера." (interactive "*bInsert buffer: ") (or (bufferp buffer) (setq buffer (get-buffer buffer))) (let (start end newmark) (save-excursion (save-excursion (set-buffer buffer) (setq start (point-min) end (point-max))) (insert-buffer-substring buffer start end) (setq newmark (point))) (push-mark newmark))) |
Как из другими определениями функции, вы можете использовать шаблон, для того, чтобы посмотреть на костяк этой функции:
(defun insert-buffer (buffer) "документация..." (interactive "*bInsert buffer: ") тело...) |
5.2.1 Интерактивное выражение в insert-buffer
Когда буфер только-для-чтения. 5.2.2 Тело функции insert-buffer
5.2.3 insert-buffer
сif
вместоor
Используем if
вместоor
.5.2.4 or
в теле функции5.2.5 Выражение let
вinsert-buffer
Два выражения save-excursion
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
insert-buffer
В insert-buffer
, аргумент к объявлению interactive
состоит из двух частей, звездочки `*', и строки `bInsert
buffer: '.
Буфер только-для-чтения `b' в интерактивном выражении
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Звездочка используется в тех ситуациях, когда буфер открыт в режиме
только-для-чтения --- то есть, это буфер, который нельзя
изменять. Если insert-buffer
вызвали из буфера только для
чтения, то в эхо-области появится сообщение об ошибке и терминал
издаст звуковой сигнал или мигнет --- вам не разрешено изменять
текущий буфер. За звездочкой не должен следовать символ новой строки,
отделяющий ее от аргумента.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Следующий аргумент в интерактивном объявлении начинается с буквы
`b' в нижнем регистре. (Здесь есть отличие от текста функции
append-to-buffer
, в котором используется `B' в верхнем
регистре. See section The Definition of append-to-buffer
.) Строчная буква `b' сообщает
интерпретатору Лиспа, что аргументом для этой функции должен быть
существующий буфер или его имя. (Прописная буква `B' разрешает
отсутствие буфера). Emacs запросит у вас имя буфера, предложив вам
буфер по умолчанию, с возможностью дополнения. Если буфер не
существует, то вы получите сообщение, которое гласит "No match" (Нет
соответствия); и ваш терминал может издать звуковой сигнал.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
insert-buffer
Тело insert-buffer
содержит две основные части ---
выражение or
и выражение let
. Задача выражения or
убедится в том, что аргумент buffer
связан с существующим
буфером, а не является только именем буфера. Тело выражения let
содержит код, который копирует другой буфер в текущий буфер.
Схематично, что эти два выражения входят в состав функции
insert-buffer
следующим образом:
(defun insert-buffer (buffer)
"документация..."
(interactive "*bInsert buffer: ")
(or ...
...
(let (список-переменных)
тело- |
Чтобы понять как выражение or
проверяет что аргумент
buffer
связан с буфером, а не просто является именем буфера,
нам вначале необходимо изучить функцию or
.
До этого давайте, перепишем эту часть функции используя выражение
if
таким образом, чтобы вы могли увидеть что происходит в
известном вам изложении.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
insert-buffer
с if
вместо or
Необходимо убедиться, что значение buffer
--- это
существующий буфер а не просто имя буфера. Если это просто имя, то
тогда надо получить связанный с ним буфер.
Представьте что вы находитесь на конференции, где один из швейцаров ходит держа табличку с вашим именем и ищет вас; таким образом швейцар "связан" с вашим именем, а не с вами; но когда он найдет вас и возьмет за руку, то он станет связан уже с вами.
На Лиспе, вы можете описать эту ситуацию следующим образом:
(if (not (не-нашел-гостя)) (найти-и-взять-его-за-руку)) |
Иногда вы хотите проделать аналогичную штуку с буфером --- если у нас нет самого буфер, то мы хотим получить его.
Используя предикат bufferp
, который проверяет является ли
буфером ли его аргумент или он является только его именем, мы можем
записать следующее:
(if (not (bufferp buffer)) ; if-часть (setq buffer (get-buffer buffer))) ; then-часть |
Здесь, проверка-истина-ложь в выражении if
--- это
(not (bufferp buffer))
; а then-часть --- выражение
(setq buffer (get-buffer buffer))
.
В проверке, функция bufferp
возвращает истину если его
аргумент --- буфер, и ложь, если его аргумент --- это имя
буфера. (Последний символ в имени функции bufferp
--- это
символ `p'; как мы видели ранее, такое использование `p'
подчеркивает, что эта функция является предикатом, что означает, что
она проверяет, обладает ли ее аргумент каким-либо
свойством. See section Using the Wrong Type Object as an Argument.)
Перед выражением (bufferp buffer
, расположена функция
not
, так что проверка-истина-ложь выглядит следующим образом:
(not (bufferp buffer)) |
Функция not
возвращает истину, если ее аргумент имеет значение
ложь, и ложь, если ее аргумент истина. Так, что если (bufferp
buffer)
возвращает истину, то выражение not
вернет ложь и
наоборот --- то, что "не истина" это ложь, а то, что "не ложь"
это истина.
С помощью этого теста выражение if
, работает следующим
образом --- если значение переменной buffer
на самом деле
буфер, а не только его имя, то тогда проверка-истина-ложь возвращает
ложь и then-часть выражения if
не вычисляется. Это правильно,
поскольку нам и не надо ничего делать, если переменная buffer
на самом деле связана с буфером.
С другой стороны, когда значение buffer
--- это не сам
буфер, а только его имя, то проверка-истина-ложь возвращает истину, и
тогда вычисляется then-часть всего выражения if
. В этом случае
then-часть --- это (setq buffer (get-buffer buffer))
. Это
выражения с помощью функции get-buffer
возвращает фактический
буфер, который задан именем. Затем setq
связывает переменную
buffer
со значением самого буфера, замещая таким образом
предыдущее значение (которое было именем буфера).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
or
в теле функции
Цель выражения or
в insert-buffer
, убедиться, что аргумент
buffer
связан с буфером, а не с именем оного. В предыдущем
разделе мы рассмотрели, как это задачу можно выполнить с помощью
выражения if
. Однако в insert-buffer
, на самом деле
используется or
. Для этого нам необходимо познакомиться с этой
функцией.
У функции or
может быть любое количество аргументов. Она
вычисляет каждый аргумент по очереди и возвращает значение первого из
них который вернул не nil
. Также и это главная характеристика
функции or
, после этого она не вычисляет другие аргументы, если
какой-то вернул значение не-nil
.
Выражение or
в функции insert-buffer
выглядит следующим
образом:
(or (bufferp buffer) (setq buffer (get-buffer buffer))) |
Первый аргумент в or
это выражение (bufferp buffer)
. Это
выражение возвращает истину (то есть не-nil
) если переменная
buffer
на самом деле связана с буфером, а не с именем буфера. В
общем выражении or
в таком случае все выражение or
возвращает истину и не вычисляет свое следующее выражение---так и надо,
ведь нам уже не надо ничего делать если значение buffer
сам буфер.
С другой стороны, если значения (bufferp buffer)
это
nil
, то есть если значением переменной buffer
было имя
буфера, то интерпретатор Лиспа вычислит следующий элемент в выражении
or
. Это выражение (setq buffer (get-buffer buffer))
.
Это выражение вернет значение не-nil
, а значение к которому
сейчас связана переменная buffer
, то есть сам буфер, а не его
имя.
В результате всего этого символ buffer
всегда будет связан с
буфером, даже если до этого он был связан с его именем. Все это
необходимо, поскольку функция set-buffer
, которая используется
на следующей строке, работает только с буфером, а не с его именем.
Кстати, с помощью or
, ситуацию со швейцаром можно записать
следующим образом:
(or (не-нашел-гостя) (найти-и-взять-его-за-руку)) |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
let
в insert-buffer
После того, как мы убедились, что переменная buffer
связана с
буфером, а не с его именем, в insert-buffer
вычисляется
выражение let
. В нем задаются три локальные переменные:
start
, end
и newmark
и им присваивается
первоначальное значение nil
. Эти переменные используются в теле
выражения let
и временно маскируют переменные с такими же
именами, но определенные вне этой функции.
Тело let
содержит два выражения save-excursion
.
Вначале, мы рассмотрим в деталях внутренней выражение
save-excursion
. Оно выглядит следующим образом:
(save-excursion (set-buffer buffer) (setq start (point-min) end (point-max))) |
Выражение (set-buffer buffer)
переключает внимание Emacs от
текущего буфера к тому из которого будет копироваться текст. В этом
буфере, переменные start
и end
связываются с началом и
концом этого буфера с помощью команд point-min
и
point-max
. Отметим использование функции setq
, которая
назначает значение сразу двум переменным. Первому аргументу
setq
присваивается значение второго аргумента, а третьему
аргументу --- значение четвертого.
После вычисление тела внутреннего выражения save-excursion
,
Emacs восстанавливает первоначальный буфер, но при этом значения
start
и end
остаются теми же, то есть они содержат точки
начала и конца буфера.
Внешнее выражение save-excursion
выглядит следующим образом:
(save-excursion (внутреннее-expression- |
Функция insert-buffer-substring
копирует текст в текущий
буфер из области ограниченной точками start
и end
буфера buffer
. Поскольку между точками start
и
end
находиться весь второй буфер, то он и будет скопирован в
ваш текущий буфер. Затем значение точки, которая будет в конце
вставленного текста записывается в переменную newmark
.
После вычисления тела внутреннего save-excursion
, точка и метка
восстанавливаются к их первоначальным значениям.
Однако это довольно удобно расположить метку в конце вставленного
недавно текста, а точку в начале. В переменной newmark
записан
конец вставленного текста. В последней строке выражения let
, с
помощью выражения (push-mark newmark)
метка устанавливается на
это место. (Предыдущая метка все еще доступна --- она занесена в
кольцо меток и вы можете вернуться к ней с помощью сочетания клавиш
C-u C-SPC). В тоже время, точка расположена в начале
вставленного текста, располагаясь там же, где она была до вызова
функции insert-buffer
.
Все выражение let
выглядит следующим образом:
(let (start end newmark) (save-excursion (save-excursion (set-buffer buffer) (setq start (point-min) end (point-max))) (insert-buffer-substring buffer start end) (setq newmark (point))) (push-mark newmark)) |
Как и в функции append-to-buffer
, в функции
insert-buffer
, используются let
, save-excursion
,
и set-buffer
. Кроме этого, в этой функции проиллюстрирован еще
один способ использования функции or
. Все эти функции являются
строительными блоками, которые мы будем использовать снова и снова.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
beginning-of-buffer
Мы уже рассмотрели основную идею функции beginning-of-buffer
.
(See section A Simplified beginning-of-buffer
Definition.) Сейчас давайте опишем ее
полностью.
Мы уже упоминали, что когда функция beginning-of-buffer
запускается с одним аргументом, то она перемещает курсор в начало
буфера, оставляя метку на предыдущем положении курсора. Однако, если
эту команду запустить с числовым аргументом от одного до десяти, то
тогда эта функция будет рассматривать это число, как долю к общей
длине буфера, измеренной в десятых долях, и переместит курсор в ту
часть буфера, которая соответствует заданному значению. То есть вы
можете или вызвать функцию с помощью M-<, что переместит курсор
к началу буфера, или с помощью C-u 7 M-<, что переместит курсор
к точке находящейся в 70% процентов от начала буфера. Если число
больше чем десять, тогда курсор будет перемещен в конец буфера.
Функцию beginning-of-buffer
можно вызывать с аргументом или без
него. То есть аргумент является необязательным.
5.3.1 Необязательные аргументы 5.3.2 beginning-of-buffer
с аргументомПример с необязательным аргументом. 5.3.3 Полный текст beginning-of-buffer
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Если не сказать заранее, то интерпретатор будет ожидать, что функцию в определении которой был задан аргумент, будут вызывать с аргументом. Если ее вызвать без аргументов, тогда вы получите сообщение об ошибке которое гласит `Wrong number of arguments'.
Однако в Лиспе существует возможность задать необязательные
аргументы --- для этого используется ключевое слово
&optional
. (`&' перед `optional' --- это часть
ключевого слова). В определении функции, если за словом
&optional
, следует аргумент, то тогда при вызове функции ей
необязательно передавать какие-либо аргументы.
Следовательно первая строка в определении функции
beginnig-of-buffer
, выглядит следующим образом:
(defun beginning-of-buffer (&optional arg) |
Схематично, вся функция выглядит следующим образом:
(defun beginning-of-buffer (&optional arg) "документация..." (interactive "P") (push-mark) (goto-char (если-есть-аргумент рассчитать-куда-переместить-курсор иначе-переместить-курсор-в (point-min)))) |
Эта функция похожа на simplified-beginning-of-buffer
, за
исключением того, что выражение interactive
идет с аргументом
"P"
и за выражением if-then-else, где вычисляется куда
переместить курсор, если задан аргумент, идет функция
goto-char
.
"P"
в выражении interactive
заставляет Emacs передать в
функцию префикс-аргумент, если он был задан. Префикс-аргумент можно
задать или с помощью клавиши META, за которой будет следовать
число, или нажав C-u, и затем набрав какое-нибудь число (если вы
не задали число, то по умолчанию, C-u назначает ему 4).
Проверка-истина-ложь в выражение if
очень проста --- это
просто аргумент arg
. Если с arg
связано значение
не-nil
, то есть функцию beginning-of-buffer
вызвали с
аргументом, то тогда проверка-истина-ложь возвращает истину и
вычисляется then-часть выражения if
. С другой стороны, если
функцию beginning-of-buffer
вызвали без аргумента, то тогда
значением arg
будет nil
, и будет вычислена else-часть
выражения if
. Else-часть это просто point-min
, в этом
случае полностью выражение для goto-char
будет выглядеть
следующим образом (goto-char (point-min))
, что мы и видели в
упрощенной версии beginning-of-buffer
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
beginning-of-buffer
с аргументом
Если beginning-of-buffer
вызван с аргументом, то тогда
вычисляется выражение, в котором рассчитывается значение, которое
будет передано функции goto-char
. На первый взгляд это
выражение кажется довольно сложным. Там много арифметики и есть
вложенное if
. Выглядит оно следующим образом:
(if (> (buffer-size) 10000) ;; Чтобы избежать переполнения в буферах больших размеров! (* (prefix-numeric-value arg) (/ (buffer-size) 10)) (/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10)) |
Как и другие сложные выражение, это выражение можно понять, если представить логику работы в виде шаблона; в нашем случае шаблона для выражения if-then-else. В схематичной форме, выражение выглядит следующим образом:
(if (буфер-большой разделить-размер-буфера-на-10-и-умножить-на-arg иначе-посчитать-по-другому |
Проверка-истина-ложь в выражении if
, проверяет размер буфера.
Это вызвано тем, что в 18 версии Emacs Лисп в вычислениях используются
числа не больше, чем восемь миллионов или около того (больше вроде и
не надо), и может получиться большее число, если буфер очень
большой. Для этого существует термин `переполнение', если число
больше, чем самое большое.
То есть перед нами два случая: если буфер большой и если не очень.
Что происходит в больших буферах Что происходит в маленьких буферах
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
В функции beginning-of-buffer
, внутреннее выражение if
,
проверяет больше ли размер буфера, чем 10,000 символов. Для этого
используются функции >
и buffer-size
. Эта строка
выглядит следующим образом:
(if (> (buffer-size) 10000) |
Если буфер больше, то тогда выполняется then-часть всего выражения
if
. Она выглядит следующим образом (после надлежащего
форматирования):
(* (prefix-numeric-value arg) (/ (buffer-size) 10)) |
Это просто операция умножения с двумя аргументами.
Первый аргумент --- это (prefix-numeric-value arg)
. Когда
interactive
задан аргумент "P"
, то в функцию передается
так называемый "сырой префикс-аргумент", а не число. (Это число в
списке). Для функции *
требуется числовое значение и
prefih-numeric-value
переводит "сырой префикс-аргумент" в
число.
Второй аргумент --- это (/ (buffer-size) 10)
. Это выражение
делит численное значение длины буфер на десять. В результате мы
получаем число, которое говорит нам сколько символов содержится в
одной десятой нашего буфера. (В Лиспе, /
используют для
деления, а *
для умножения).
Схематично все выражение для умножения можно представить следующим образом:
(* численное-значение-префикс-аргумента число-символов-в-одной-десятой-буфера) |
Например, если префикс-аргумент равен `7', то после умножения числа символов в одной десятой на 7 мы получим число которому соответствует точка на расстоянии в 70% от начала буфера.
Таким образом, если буфер большой, то все выражение для
goto-char
будет выглядеть следующим образом:
(goto-char (* (prefix-numeric-value arg) (/ (buffer-size) 10))) |
Это переместит курсор куда мы хотим.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Если буфер содержит меньше чем 10,000 символов, то вычисление будет немножко другим. Вам может показаться, что это излишнее усложнение, поскольку и первый способ вполне себе хорош. Однако в небольших буферах первый способ не совсем точно перемещает курсор --- второй метод делает лучше.
Код выглядит следующим образом:
(/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10)) |
Это выражение легче понять, если мы будем видеть каким образом функции вложены друг в друга. Для этого лучше отформатировать это выражение следующим образом:
(/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10)) |
Сейчас хорошо видно, что самое внутреннее выражение это
(prefix-numeric-value arg)
, где необработанный префикс-аргумент
переводиться в численную форму. В следующем выражении полученое число
умножается на размер буфера:
(* (buffer-size) (prefix-numeric-value arg) |
В результате получится число, которое может быть меньше чем размер буфера --- в семь раз если аргумент был 7. Затем к результату будет добавлено десять и в конце это большое число поделят на десять --- так мы и получим значение которое на один символ больше чем процентная позиция в буфере.
Конечное число будет передано в функцию goto-char
и в
результате курсор будет перемещен в нужное место.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
beginning-of-buffer
А вот и полный текст функции beginning-of-buffer
:
(defun beginning-of-buffer (&optional arg) "Переместить точку в начало буфера; оставив метку в предыдущей позиции курсора. С арг N, переместить точку в N/10 от начала буфера. Не используете эту функцию в своих программах! \(goto-char (point-min)) быстрее и не устанавливает метку." (interactive "P") (push-mark) (goto-char (if arg (if (> (buffer-size) 10000) ;; Avoid overflow for large buffer sizes! (* (prefix-numeric-value arg) (/ (buffer-size) 10)) (/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10)) (point-min))) (if arg (forward-line 1))) |
Кроме двух нюансов мы уже все обсудили. Во первых надо обсудить строку документации, и во вторых надо рассмотреть последнюю строку функции.
В строке документации, есть ссылка на выражение:
\(goto-char (point-min)) |
Перед открывающей скобкой этого выражения стоит `\'. Это сообщает интерпретатору Лиспа, что выражение так и должно присутствовать в документации, и вычислять его не надо.
В последней строке функции beginning-of-buffer
производиться
перемещение курсора в начало строки, если команда была запущена с
аргументом:
(if arg (forward-line 1))) |
Этот код переместит курсор в начало строки, которая находиться на соответствующем расстоянии от начала буфера. Это неплохо, поскольку это значит, что курсор всегда будет расположен по крайней мере в указанной части пути через буфер, что является утонченностью, но не необходимостью, но которая вызовет возмущение, в случае отсутствия.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
Кратко повторим темы, которые мы изучили в этой главе.
or
nil
; если же все вернули nil
,
то результат всего выражения также будет nil
. Короче говоря,
эта функция возвращает первое истинное значение своих аргументов; она
возвращает истину если один, или любой другой аргумент истинен.
and
nil
, то возвращает nil
; если нет, то возвращает
значение своего последнего аргумента. Короче говоря, возвращает
истину, только если все аргументы истинны.
&optional
prefix-numeric-value
(interactive "P")
в численное значение.
forward-line
forward-line
не смогла продвинуться.
erase-buffer
bufferp
t
если аргумент является буфером; в противном случае
возвращает nil
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
&optional
аргументом
Напишите интерактивную функцию с необязательным аргументом, которая
проверяет является ли ее аргумент числом, меньше оно или больше оно чем
значение переменно fill-column
, и сообщает результат в виде
сообщения в мини-буфере. Однако, если аргумент не передан, то в
качестве значения по умолчанию должно использоваться число 56.
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |