Spec-Zone.ru › Elisp

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

Если выполнение операции может занять некоторое время, следует сообщать пользователю о ходе её выполнения. Так пользователь сможет оценить оставшееся время и ясно увидеть, что Emacs занят работой, а не завис. Удобный способ сделать это — использовать индикатор выполнения.

Вот работающий пример, который не делает ничего полезного:

(let ((progress-reporter
       (make-progress-reporter "Collecting mana for Emacs..."
                               0  500)))
  (dotimes (k 500)
    (sit-for 0.01)
    (progress-reporter-update progress-reporter k))
  (progress-reporter-done progress-reporter))
Функция: make-progress-reporter message &optional min-value max-value current-value min-change min-time context

Эта функция создаёт и возвращает объект индикатора выполнения, который используется в качестве аргумента для других перечисленных ниже функций. Идея состоит в том, чтобы предварительно вычислить как можно больше данных и тем самым сделать отображение хода выполнения очень быстрым.

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

Аргументы min-value и max-value должны быть числами, обозначающими начальное и конечное состояния операции. Например, для операции сканирования буфера им следует присвоить результаты point-min и point-max соответственно. Значение max-value должно быть больше значения min-value.

В качестве альтернативы можно задать для min-value и max-value значение nil. В этом случае индикатор выполнения не сообщает проценты выполнения процесса, а отображает «вертушку», которая поворачивается на одно деление при каждом обновлении индикатора.

Если min-value и max-value являются числами, аргументу current-value можно задать числовое значение, указывающее начальный ход выполнения; если аргумент опущен, по умолчанию используется min-value.

Аргументы min-change и min-time управляют частотой обновления области эха. Индикатор выполнения будет ждать, пока операция не продвинется ещё как минимум на min-change процентов, прежде чем вывести следующее сообщение; по умолчанию это один процент. min-time задаёт минимальное время в секундах между последовательными выводами; по умолчанию это 0.2 секунды. (В некоторых операционных системах точность обработки долей секунды индикатором выполнения может различаться.)

Если context — символ async, это означает, что обновления будут происходить асинхронно. Серверные части могут использовать эту информацию, чтобы обновления хода выполнения не мешали другим данным. Например, серверная часть, отображающая ход выполнения в области эха, не будет показывать асинхронные обновления, когда область эха занята.

Эта функция вызывает progress-reporter-update, поэтому первое сообщение выводится немедленно.

Функция: progress-reporter-update reporter &optional value update-text

Эта функция выполняет основную работу по отображению хода выполнения операции. Она выводит сообщение из reporter, за которым следует процент выполнения, определяемый значением value. Если процент равен нулю или достаточно близок к нему согласно аргументам min-change и min-time, он не выводится.

reporter должен быть результатом вызова make-progress-reporter. value задаёт текущее состояние операции и должно находиться в диапазоне от min-value до max-value включительно, переданных в make-progress-reporter. Например, при сканировании буфера value должно быть результатом вызова point.

Необязательный аргумент update-text — это строка, которая выводится после основного сообщения и текста о ходе выполнения из reporter. Обычно её используют для указания текущего «шага» длительного процесса, чтобы пользователь знал, на каком этапе он находится. Если reporter нечисловой, то value должно быть nil либо строкой, которая будет использоваться вместо update-text.

Эта функция учитывает значения min-change и min-time, переданные в make-progress-reporter, поэтому не выводит новое сообщение при каждом вызове. Благодаря этому она работает очень быстро, и обычно не следует пытаться сократить число её вызовов: связанные с этим накладные расходы, скорее всего, сведут на нет ваши усилия.

Функция: progress-reporter-force-update reporter &optional value new-message update-text

Эта функция похожа на progress-reporter-update, за исключением того, что безусловно выводит сообщение в области эха.

reporter, value и update-text имеют то же значение, что и в progress-reporter-update. Необязательный аргумент new-message позволяет изменить сообщение reporter. Поскольку эта функция всегда обновляет область эха, такое изменение будет немедленно показано пользователю.

Функция: progress-reporter-done reporter

Эту функцию следует вызывать по завершении операции. Она выводит сообщение из reporter, за которым следует слово «done» в области эха.

Эту функцию следует вызывать всегда, а не полагаться на то, что progress-reporter-update выведет «100%». Во-первых, это может никогда не произойти — существует множество веских причин, по которым это может случиться. Во-вторых, «done» яснее сообщает о завершении.

Макрос: dotimes-with-progress-reporter (var count [result]) reporter-or-message body…

Этот удобный макрос работает так же, как dotimes, но также отображает ход выполнения цикла с помощью описанных выше функций. Он позволяет сократить объём вводимого кода. Аргумент reporter-or-message может быть строкой или объектом индикатора выполнения.

Пример в начале этого подраздела можно переписать с помощью этого макроса следующим образом:

(dotimes-with-progress-reporter
    (k 500)
    "Collecting some mana for Emacs..."
  (sit-for 0.01))

Использование объекта индикатора в качестве аргумента reporter-or-message полезно, если нужно указать необязательные аргументы для make-progress-reporter. Например, предыдущий пример можно записать так:

(dotimes-with-progress-reporter
    (k 500)
    (make-progress-reporter "Collecting some mana for Emacs..." 0 500 0 1 1.5)
  (sit-for 0.01))
Макрос: dolist-with-progress-reporter (var list [result]) reporter-or-message body…

Это ещё один удобный макрос, который работает так же, как dolist, но также отображает ход выполнения цикла с помощью описанных выше функций. Как и в dotimes-with-progress-reporter, reporter-or-message может быть индикатором выполнения или строкой. Предыдущий пример можно переписать с помощью этого макроса следующим образом:

(dolist-with-progress-reporter
    (k (number-sequence 0 500))
    "Collecting some mana for Emacs..."
  (sit-for 0.01))
Макрос: with-delayed-message (timeout message) body…

Иногда неясно, займёт ли выполнение операции много времени, а иногда реализация индикатора выполнения может быть неудобной. В таких ситуациях можно использовать этот макрос.

(with-delayed-message (2 (format "Gathering data for %s" entry))
  (setq data (gather-data entry)))

В этом примере сообщение будет показано, если выполнение тела займёт больше двух секунд. Если оно займёт меньше времени, сообщение не будет показано. В обоих случаях тело выполняется обычным образом, а возвращаемым значением макроса является значение последнего элемента тела.

Элемент message вычисляется до body и всегда вычисляется независимо от того, отображается сообщение или нет.

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

Spec-Zone.ru

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