Цифровой садик - приветственная

Цифровой садик - приветственная | Полный список всего, что тут есть | RSS | Подписаться через follow.it

17.08.2023

elisp

Язык емакса. Тут, наверное, мой «разговорник». Потому что до уровня «со словарём» я ещё явно не доросла. Ну, и «прописи первоклашки».

el-patch

В чём приятность, кроме того, что вообще умеет довольно ювелирно вписываться с изменениями - что можно проверить, не поменялось ли заменяемое. Начала использовать и вполне рада. 2022-01-12.

Чтобы даты получались не на русском, как оно у меня по умолчанию, а по стандарту

(let ((system-time-locale "C")) ; force dates to render as per RSS spec
     (format-time-string "%a, %d %b %Y %H:%M:%S %z" (org-static-blog-get-date post-filename)))

Потырено в org-static-blog, но там-то en_US.utf8, которое у меня не хотело работать, а вот так - норм, и там не везде, где надо, было.

Urlencode url

Вот так урл остаётся рабочим, но буковки в последней части заменяются по стандарту:

(url-encode-url "https://agnessa.pp.ru/texts/20210826174424-ссылки_о_текстовом.html")
https://agnessa.pp.ru/texts/20210826174424-%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8_%D0%BE_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2%D0%BE%D0%BC.html

Вот так получается то, что можно засовывать внутрь другой ссылки для каких-нибудь переадресаций или ещё чего подобного, потому что преобразуется всёёё :)

(url-hexify-string "https://agnessa.pp.ru/texts/20210826174424-ссылки_о_текстовом.html")
https%3A%2F%2Fagnessa.pp.ru%2Ftexts%2F20210826174424-%D1%81%D1%81%D1%8B%D0%BB%D0%BA%D0%B8_%D0%BE_%D1%82%D0%B5%D0%BA%D1%81%D1%82%D0%BE%D0%B2%D0%BE%D0%BC.html

А это обратно получить utf-8 из вот этого закодированного.

(decode-coding-string (url-unhex-string "%D0%BC%D1%83%D0%BB%D1%8C%D1%82%D0%B8%D0%BC%D0%B5%D0%B4%D0%B8%D0%B0/%D1%81%D0%B8%D0%BD%D1%82%D0%B5%D0%B7") 'utf-8)

shell-command

http://ergoemacs.org/emacs/elisp_call_shell_command.html shell-command - Call a shell command, wait for it to finish.

shell-command-to-string - Call a shell command, wait for it to finish, get its output.

(shell-command "ls")
(shell-command-to-string "ls")

Про имена файлов

Hook - отключаемо уцепиться за событие

Function: add-hook hook function &optional depth local Пример включает чисто "add-hook hook function".

(add-hook 'text-mode-hook 'my-text-hook-function)

Если функция уже есть в хуке, повторного добавления не будет.

Убрать добавленное:

(remove-hook 'text-mode-hook 'my-text-hook-function)

This function removes function from the hook variable hook. It compares function with elements of hook using equal, so it works for both symbols and lambda expressions. Но э, не надо тут lambda, это ж неудобно!

Advice - вежливо переопределять

(advice-add 'исходная-функция :override  #'моя-функция)

Способ переопределить нечто у себя.

Плюсов сразу два:

  • у себя. То есть, вот в моём случае - автор там что-то пишет в своём пакете, обновлять, может, будет. Так можно мирно обновляться, и пока в этом конкретном месте ничего существенного не меняется, всё будет работать без дополнительных действий.
  • по сравнению с определением непосредственно поверх, advice правильнее тем, что его можно ещё и удалить без перезагрузки всего.
(advice-remove 'исходная-функция #'моя-функция)

https://www.gnu.org/software/emacs/manual/html_node/elisp/Advising-Functions.html

Ещё стоит отметить, что override - это самый, наверное, простой и тупой способ. А их много: https://www.gnu.org/software/emacs/manual/html_node/elisp/Advice-Combinators.html

Некогдашний короткий конспект «самого нужного»

C-j - посчитать елисп-код в scratch-буфере "почти без последствий"

C-x C-e - выполнить елисп код из произвольного места, с полноценным влиянием на емакс

'(this list has (a list inside of it)) Список может содержать числа, символы и строки.

The single apostrophe, `'', that I put in front of some of the example lists in preceding sections is called a "quote"; when it precedes a list, it tells Lisp to do nothing with the list, other than take it as it is written. But if there is no quote preceding a list, the first item of the list is special: it is a command for the computer to obey. (In Lisp, these commands are called functions.)

The list `(+ 2 2)' shown above did not have a quote in front of it, so Lisp understands that the `+' is an instruction to do something with the rest of the list: add the numbers that follow.

Добавить в список, установить значение переменной   info

(add-to-list 'listname 'value) 

Добавили в список. Добавляет один элемент.

(setq variable-name new-value)

Установили значения переменной

literate-elisp

https://github.com/jingtaozf/literate-elisp - позволяет работать с елиспом в орг-моде, даже не особо тангля.

(defun test ()
 (message "this is a test from org file.~%"))

Then you can load this org file like this:

(load "~/projects/literate-elisp/literate-elisp.el")
(literate-elisp-load "test.org")

Now the Emacs Lisp function test is ready to use, and you can jump to the definition of test in the org file by using Emacs library find-func directly without tangling them to an Emacs Lisp file(.el).

If you want to load an org file with a Emacs command, please press “Alt-X” and type literate-elisp-load-file.

If you want to load an org file in batch mode, please use function literate-elisp-batch-load.

a new code block header argument load

Source blocks in a literate program can serve a variety of purposes—implementation, examples, testing, and so on—so we define a load Org code block header argument to decide whether to read them or not, which accepts the following values -

yes The code block should be loaded normally. This is the default when the header argument load is not provided.

(defun a-function-to-load ()
 (message "this function will be loaded by literate-elisp.~%"))

no The code block should be ignored by the Emacs Lisp reader.

(defun a-function-to-ignore ()
 (message "this function will be ingored by literate-elisp.~%"))

test The code block should be loaded only when the variable literate-elisp-test-p is true.

(defun a-function-to-test ()
 (message "this function will be loaded by literate-elisp only if literate-elisp-test-p is true.~%"))

the name of a variable or function The code block is loaded if the value of the variable or the return value of the function is non-nil.

elisp-intro + понемногу что мне надобилось в придачу

списки и атомы

Список - это атомы и списки в скобках. Атомы - символы (слова и некоторые символы), числа, строки (нечто в двойных кавычках). Несколько пробелов и/или переносов строки - эквивалентны одному пробелу.

Выполнение списка

Когда перед списком стоит апостроф, это сигнал для Лиспа ничего не делать со списком, а взять его как есть. Но если перед списком нет апостофа, то первый символ в списке имеет особое значение — это команда, которую компьютер должен выполнить.

'(+ 2 3)
(+ 2 3)
(это список перед которым не стоит апостроф)

В минибуффере выдаёт: "progn: Symbol’s function definition is void: это"

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

(+ 2 (+ 3 3))

Если внутренних списков нет, то интерпретатор вычисляет выражения слева направо, от одного выражения к другому.

вычисление символического выражения обычно заставляет интерпретатор Лиспа возвратить какое-нибудь значение и, возможно, выполнить побочное действие; или прервать выполнение, отобразив соответствующее сообщение об ошибке.

Переменные

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

Если вы попытаетесь вычислить символ, с которым не связано никакое значение, то вы получите сообщение об ошибке.

Функции

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

Например, функция concat связывает вместе, или объединяет две или более строк, чтобы получить одну строку. Ее аргументы строки. Конкатенация двух символьных строк abc, def выдаст в результате строку abcdef. Это можно проверить вычислив следующее:

(concat "abc" "def")

Аргументами функции substring являются и строки, и числа. Эта функция возвращает часть строки, подстроку своего первого аргумента. Функция требует три аргумента. Первый аргумент — строка символов, второй и третий аргументы — это числа, которые отмечают начало и конец строки. Числа — это количество символов (включая пробелы и знаки пунктуации) от начала строки.

(substring "Четыре черненьких чумазеньких чертенка." 7 29)

Вы можете считать функцию substring "разделителем атома" поскольку она извлекает часть из по-другому неделимого атома. Однако substring способна выделить подстроку только из строки, а с другого рода атомами, такими как символы или числа, она не работает.

Аргументом может быть и символ, который возвращает значение, когда его вычислят. Например, когда мы вычисляем символ fill-column, то он возвращает число. Это число может использоваться в сложении.

(+ 2 fill-column)

(ага, у меня безумное fill-column.)

функция message

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

(message "Это сообщение появится в эхо-области!")

Ну, вот, не обязательно только в эхо-области. У меня в эхо-области появилось "Code block evaluation complete." Правда, и то сообщение тож. Перед ним.

если в строке найдется символ `%s', то функция message не будет печатать его, а вместо этого просмотрит аргументы, которые следуют за строкой. Она вычислит второй аргумент и напечатает его значение на месте `%s'.

(message "Имя этого буфера: %s." (buffer-name))

значение в виде десятичного числа, вы должны вместо `%s' использовать `%d'. Например, чтобы напечатать в эхо-области значение fill-column, вычислите следующее:

(message "Значение переменной fill-column: %d." fill-column)

Если в строке больше чем одна `%s', то значение первого аргумента после строки печатается на месте первого появления `%s', а значение второго аргумента — на месте второго появления `%s', и так далее. Например, если вы вычислите следующее:

(message "Ничего себе, в офисе %d %s!"
         (- fill-column 14) "розовых слонов")
(message "Он увидел %d %s"
         (- fill-column 34)
         (concat "рыжих " "прыгающих "
                 (substring
                  "Шустрые, лисицы весело прыгали." 9 14)))

В этом примере у функции message три аргумента — строка, "Он увидел %d %s", выражение (- fill-column 32), и выражение, которое начинается с функции concat. Значение, которое возвращается после вычисления (- fill-column 32), вставляется на место `%d', а значение от вычисления списка, где первый элемент concat, вставляется на место `%s'.

Присвоить переменной значение

set

(set 'цветы  '(роза фиалка маргаритка лютик))

Побочный эффект - теперь емакс знает, что это

цветы
'цветы

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

setq

Сочетание set с первым аргументом, перед которым стоит апостроф, встречается так часто, что была введена особая форма setq. Эта особая форма действует точно также, как и set, но перед первым аргументом не надо ставить апостроф, так как он не вычисляется. Также добавлена еще одна полезная возможность — setq разрешает вам назначить одновременно значения нескольким переменным в одном выражении.

(set 'плотоядные '(лев тигр леопард))
(setq деревья '(сосна ель дуб клен) 
      травоядные '(газель антилопа зебра))

Счётчик

(setq counter 0)                ; Назовем это инициализацией.
(setq counter (+ counter 1))    ; Здесь увеличиваем счетчик.
counter                         ; А это счетчик.

Определение функции

 (defun имя-функции (аргументы...)
"необязательная-документация..."
(interactive как-получить-аргументы)     ; необязательно
тело...)

Как первый пример мы рассмотрим определение функции, которая умножает свой аргумент на 7. (Это пример не интерактивной функции. See section Making a Function Interactive, для получения дополнительной информации).

(defun умножить-на-семь (number)
  "Умножить NUMBER на семь."
  (* 7 number))
(умножить-на-семь 3)
(defun умножить-на-семь (number)       ; Интерактивная версия.
  "Умножить NUMBER на семь."
  (interactive "p") ; передаёт в функцию префикс
  (message "Итог %d" (* 7 number)))

В Emacs более 20 символов, предопределенных для использования с interactive. Почти во всех случаях, та или другая из этих опций позволит вам передать интерактивно в функцию всю необходимую информацию. (See section `Code Characters for interactive' in The GNU Emacs Lisp Reference Manual.)

Например, символ `r' заставляет Emacs передать начало и конец области (текущие значения точки и метки) в функцию как два различных аргумента. Его используют следующим образом:

(interactive "r")

Другой символ `B' — указание для Emacs запросить от вас имя буфера, которое будет передано в функцию. В этом случае Emacs отобразит в мини-буфере подсказку, используя строку, которая следует за `B', например, "BДобавить к буферу: ". Emacs не только отобразит подсказку в мини-буфере, но также позволит воспользоваться функцией автодополнения, что здорово помогает (просто наберите первые несколько символов и нажмите TAB).

Функция, которая требует два и более аргумента, может получить информацию для каждого из них, добавляя к строке за interactive различные части. Когда вы сделаете это, информация передается в каждый аргумент в том же самом порядке как они описаны в списке аргументов interactive. В строке каждая часть отделяется друг от друга `\n' — символом новой строки. Например, если за interactive будет следовать строка "BДобавить к буферу: \nr", то это заставит интерпретатор Лиспа передать в функцию значения точки и метки, а также запросить у вас имя буфера (в целом три аргумента).

let

(let список_переменных тело…)

Переменные «понятны» только в рамках тела.

Если список переменных состоит из двухэлементных списков, как это часто и случается, то шаблон для выражения let будет таким:

(let ((переменная значение) (переменная значение) …) тело…)

if

(if (> 5 4) ; if-part (message "5 больше чем 4!")) ; then-part

(if (> 4 5) ; if-часть (message "5 больше чем 4!") ; then-часть (message "4 не больше чем 5!")) ; else-часть

(defun тип-животного (характеристика)
"Напечатать сообщение в эхо-области. В зависимости от ХАРАКТЕРИСТИКИ.
   Если ХАРАКТЕРИСТИКА `свирепость', тогда напечатать предупреждение."
(if (equal характеристика 'свирепость)
    (message "Это тигр!")))  
(тип-животного 'пушистость)
(тип-животного 'свирепость)

cond

(cond (test-expression1 then-expression1)
      (test-expression2 then-expression2)
      (t else-expression))

save-excursion

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

(save-excursion
  тело...)

В программах на Emacs Лиспе выражение save-excursion часто помещают в тело выражения let. Это выглядит следующим образом:

(let список-переменных
  (save-excursion
    тело...))

Macro: save-mark-and-excursion body…

This macro is like save-excursion, but also saves and restores the mark location and mark-active. This macro does what save-excursion did before Emacs 25.1.
(https://www.gnu.org/software/emacs/manual/html_node/elisp/Excursions.html)

surround region

https://www.emacswiki.org/emacs/SurroundRegion

(defun surround (begin end open close)
  "Put OPEN at START and CLOSE at END of the region.
If you omit CLOSE, it will reuse OPEN."
  (interactive  "r\nsStart: \nsEnd: ")
  (when (string= close "")
    (setq close open))
  (save-excursion
    (goto-char end)
    (insert close)
    (goto-char begin)
    (insert open)))

https://tech.tonyballantyne.com/emacs/3-interactive-functions-that-work-on-regions/

(defun myMark-elisp-region (rStart rEnd)
  "Mark region as Elisp source code for org mode export."
  (interactive "r")
  (save-excursion
    (goto-char rEnd) (insert "\n#+END_SRC\n")
    (goto-char rStart) (insert "#+BEGIN_SRC emacs-lisp -n\n"))
)

«Note the use of the save-excursion function to return the point to where it was before the function was run. Note also the way the above function is laid out. An interesting exercise is to reverse the order of lines 5 and 6. See if you can figure out why the function doesn’t work as you might expect.»

А ещё есть save-restriction и narrow для работы с выделенной областью

It narrows to a region, uses save-restriction to remember how things were before the narrowing and then uses two regex searches to find first double quotes and then single quotes, replacing both with plain quotes.

 (defun strip-smart-quotes (rStart rEnd)
   "Replace smart quotes with plain quotes in text"
   (interactive "r")
   (save-restriction
   (narrow-to-region rStart rEnd)
   (goto-char (point-min))
   (while (re-search-forward "[“”]" nil t) (replace-match "\"" nil t))
   (goto-char (point-min))
   (while (re-search-forward "[‘’]" nil t) (replace-match "'" nil t))
))
А так можно применить к выделенной области или всему буферу, если область не выделена
(defun region-or-buffer ()
  "Strip smart quotes from region, or whole buffer if region not set"
  (interactive)
  (save-excursion
    (save-restriction
      (when (use-region-p) (narrow-to-region (region-beginning) (region-end)))
      (goto-char (point-min))
      (while (re-search-forward "[“”]" nil t) (replace-match "\"" nil t))
      (goto-char (point-min))
      (while (re-search-forward "[‘’]" nil t) (replace-match "'" nil t))
  )))

Если у вас есть мысли, комментарии, предложения или отклики по поводу этой страницы или этого цифрового сада в целом, напишите мне сообщение на agnessa@agnessa.pp.ru. Мне ооочень интересно!

Задонатить.


An IndieWeb Webring 🕸💍