- PVSM.RU - https://www.pvsm.ru -
Часто приходится видеть, как новички пробуют Common Lisp и потом жалуются, что с ним невозможно нормально работать. Как правило, это происходит из-за того, что они не понимают как настроить себе процесс, обеспечивающий тот самый "быстрый отклик" от среды разработки, когда ты поменял функцию, скомпилировал её и изменения тут же начали использоваться внутри уже "бегущей" прогрммы без её перезапуска.
Понять, как это выглядит, можно посмотрев какой-нибудь ролик на youtube, где демонстрируется интерактивная разработка на Common Lisp.
Сегодня я хочу показать, как настроить себе dev окружение для такой разработки. В 2018 году это стало совсем просто, благодаря постоянно улучшающемуся тулингу.
Заранее прошу прощения за то, что следующие ролики записаны в Asciinema, а Habrahabr его не поддерживает. Кликайте на скриншоты консоли, чтобы посмотреть ролики.
Для начала, надо установить SBCL [1], Roswell [2] и Emacs [3]. Рассказывать я буду на примере установки всего в OSX, и буду рад если в комментариях вы поделитесь своим опытом на Windows и Linux. Тогда я смогу дополнить статью примерами для всех трех платформ.
SBCL это одна из многочисленных реализаций Common Lisp. Из опенсорсных - самая быстрая. При желании, на SBCL можно запускать код по скорости сопоставимый с кодом на C++, но при этом имея все плюшки от быстрой интерактивной разработки.
Roswell, это утилита, для установки и запуска Common Lisp программ. В том числе она умеет запускать преднастроенный Emacs, а так же собирать программы в бинарники.
Emacs вы наверняка знаете - такая операционная система, в которой есть и редактор кода. Можно писать на Common Lisp и в любом другом редакторе, но на сегодняшний день у Emacs лучшая интеграция и поддержка смантического редактирования кода. С ним вам не придётся считать скобочки, он всё делает за вас.
brew install roswell emacs
После того, как brew пошуршит диском и поставит всё нужное, просто запустите в терминале:
ros run
Эта команда автоматически поставит вам последнюю версию SBCL и стартует Lisp repl, куда можно вводить код:
Но это не дело, разрабатываться так нелья. Поэтому давайте настроим Emacs для полноценной разработки:
ros emacs
Команда запустит Emacs в консоли и настроит Quicklisp — пакетный менеджер для Common Lisp.
Но прежде чем мы продолжим, давайте настроим терминал, emacs и OSX так, чтобы они хорошо работали вместе.
Делаем так, чтобы CapsLock работал как Control. В Emacs без этого — никуда:
Затем отключить в шоткатах MissionControl все комбинации, связанные с использованием Control и стрелок:
Затем поставить iTerm2 и переключить в настройках профиля поведение Alt с Normal на Esc+:
После чего, создать файлик с минимальным конфигом для Emacs, ~/.emacs.d/init.el
:
(package-initialize)
(require 'package)
(add-to-list 'package-archives
'("MELPA" . "http://melpa.milkbox.net/packages/") t)
(defun install-package (package)
(unless (package-installed-p package)
(package-refresh-contents)
(package-install package)))
(install-package 'paredit)
(install-package 'expand-region)
(defun setup-lisp-mode ()
(require 'paredit)
(paredit-mode)
(define-key paredit-mode-map (kbd "C-w") 'paredit-backward-kill-word))
(add-hook 'lisp-mode-hook
'setup-lisp-mode)
(add-hook 'emacs-lisp-mode-hook
'setup-lisp-mode)
;; используем C-w для удаления слова с опечаткой и последующего набора его заново
;; вместо kill-region
(global-set-key (kbd "C-w") 'backward-kill-word)
;; вместо кучи команд начинающихся с kmacro-
(global-set-key (kbd "C-x C-k") 'kill-region)
;; вместо indent-new-comment-line
(global-set-key (kbd "M-j")
(lambda ()
(interactive)
(join-line -1)))
;; поиск и замена
(global-set-key (kbd "C-c r s") 'replace-string)
(global-set-key (kbd "C-c r r") 'replace-regexp)
;; по этому сочетанию emacs начинает выделять формы
;; и дальше можно просто нажимать =, чтобы расширить
;; выделение на родительскую форму.
(global-set-key (kbd "C-c =") 'er/expand-region)
;; это сочетание удобно использовать с предыдущим,
;; чтобы быстро выделить и закомментировать кусок кода
(global-set-key (kbd "C-c c") 'comment-or-uncomment-region)
(global-set-key (kbd "C-c C-\") 'goto-last-change)
(setq custom-file "~/.emacs.d/customizations.el")
(when (file-exists-p custom-file)
(load custom-file))
После чего, снова запускаем ros emacs, жмём Alt-X
и вводим команду slime
. В результате получаем командную строку для ввода лисповых команд:
Но мы не будем вводить команды в репл, лучше сразу приступим к разработки микросервиса. Если нужно только API, то проще всего использовать Ningle [5]. Если нужен более продвинутый фреймворк, типа джанги, то можно попробовать Radiance [6] или Caveman2 [7]. Но сейчас не будем делать ничего сложного, а замутим простую HTTP апишечку.
Откройте в Emacs файл server.lisp
(C-x C-f server.lisp
) и начинайте писать код. Примерно так:
В итоге, у вас внутри инстанса окажется запущен вебсервер, в который на ходу можно добавлять роуты и переопределять вьюхи.
Вот весь код, для ленивых:
;; Micro-framework for building API
(ql:quickload :ningle)
;; Now ningle is installed and we need to install a clack which is analog of WSGI
;; stack from Python
;; I've pressed C-c C-c to eval this form
(ql:quickload :clack)
;; To parse json:
(ql:quickload :jonathan)
(defvar *app* (make-instance 'ningle:<app>))
(setf (ningle:route *app* "/")
;; in case, if you need to parse or serialize JSON,
;; use Jonthan library.
(jonathan:to-json '(:foo 100500)))
(defvar *server* nil
"This variable will store currently running server instance.")
(defun start ()
(if *server*
(format t "Server already started")
(setf *server*
(clack:clackup *app*))))
(defun stop ()
(if *server*
(clack:stop *server*)
(format t "Server is not running")))
В Лиспе конструкции, которые внутри скобочек, называются “формами”. Формы, которые на верхнем и не вложены ни в какие другие, называются top-level. Такие формы можно компилировать нажав сочетание C-c C-c
, когда курсор находится внутри такой формы. Если вы перебиндили CapsLock
на Сontrol
, то это сочетание очень удобно нажимать.
После того, как форма скомпилирована новая версия функции сразу же вступает в силу и перезапуск сервера не требуется. Так очень удобно отлаживаться и фиксить баги. Кроме того, можно настроить автоматический прогон тестов сразу после компиляции части кода, но это уже совсем другая история.
Если вам интересны ещё какие-то темы, пишите в комментариях, постараюсь сделать посты и про них.
Автор: Александр Артёменко
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/tutorial/281722
Ссылки в тексте:
[1] SBCL: http://www.sbcl.org/
[2] Roswell: https://github.com/roswell/roswell
[3] Emacs: https://www.gnu.org/software/emacs/
[4] Image: https://asciinema.org/a/142424
[5] Ningle: http://8arrow.org/ningle/
[6] Radiance: https://shirakumo.github.io/radiance/
[7] Caveman2: http://8arrow.org/caveman/
[8] Image: https://asciinema.org/a/142437
[9] Источник: https://habr.com/post/413061/?utm_source=habrahabr&utm_medium=rss&utm_campaign=413061
Нажмите здесь для печати.