tymmym's blog
21 нояб. 2011 г.
11 нояб. 2011 г.
Введение в функциональное реактивное программирование с помощью reactive-banana
Функциональное реактивное программирование (ФРП) - это метод моделирования реактивного (т.е. зависящего от времени и внешних воздействий) поведения в чистых функциональных языках. ФРП позволяет моделировать системы, реагирующие на изменяющиеся входные воздействия, в простом декларативном стиле[1].
Цель данного поста показать, как можно писать GUI на Haskell в декларативном стиле. С помощью библиотеки reactive-banana мы напишем простой счётчик, который будет управляться двумя кнопками.
29 июн. 2009 г.
StumpWM + Jabber.el
Захотел получать оповещения о приходе в Jabber.el сообщений.Для этого сначала добавил в Jabber.el возможность отправки сообщений в StumpWM.
Результат:
Полученный результат меня до конца не устроил:
- оповещения приходится удалять вручную;
- оповещения захламляют и без того перегруженную mode-line.
Пришлось внести небольшие изменения в модуль notifications, чтобы добиться желаемого:
- добавлена возможность удаления оповещений по таймауту;
- оповещения выводятся как стандартные сообщения StumpWM.
После выполнения функции notifications-start-messages при получении сообщений получаем следующее:
- Создал в директории с Jabber.el файл jabber-stumpwm.el следующего содержания:
(eval-when-compile (require 'jabber-alert))
Данный файл - копия jabber-ratpoison.el с небольшими изменениями для StumpWM. Для отправки оповещения используется STUMPwm Interactive SHell, которой в качестве аргументов передаем имя фукции оповещения и сообщение.
(defun jabber-stumpwm-message (msg)
"Show MSG in StumpWM"
;; Possible errors include not finding the stumpish (STUMPwm Interactive SHell).
(condition-case e
(let ((process-connection-type))
(call-process "stumpish" nil 0 nil "notifications-add" msg))
(error nil)))
(define-jabber-alert stumpwm "Show a message through the StumpWM window manager"
'jabber-stumpwm-message) - Добавил (require 'jabber-stumpwm) в секцию External notifiers в файле jabber.el.
(load-module "notifications")А к строке *screen-mode-line-format* добавляем %N.
(define-key *root-map* (kbd "N") '*notifications-map*)
Результат:
Полученный результат меня до конца не устроил:
- оповещения приходится удалять вручную;
- оповещения захламляют и без того перегруженную mode-line.
Пришлось внести небольшие изменения в модуль notifications, чтобы добиться желаемого:
- добавлена возможность удаления оповещений по таймауту;
- оповещения выводятся как стандартные сообщения StumpWM.
*** notifications.lisp.old 2009-06-30 15:02:31.851810478 +0400
--- notifications.lisp 2009-06-30 15:34:10.667560769 +0400
***************
*** 75,90 ****
--- 75,107 ----
(defvar notifications nil
"A list of notification strings.")
+ (defvar *notification-time* 20
+ "This variable controls how many seconds the notification will be
+ stored in the list of notifications. Don't use timer for
+ notification if the value is nil.")
+
+ (defvar *message-timeout* 1
+ "This variable controls how many seconds elapse between each update
+ of the message.")
+
+ (defvar *message-timer* nil
+ "The timer that updates the message.")
+
(defcommand notifications-add (str)
((:rest "Notification: "))
"Add a notification string.
If a notification is already included, it will be moved to the front instead of
added anew."
+ (when *notification-time*
+ (run-notification-timer))
(when (not (string= (car notifications) str))
(when (member str notifications :test #'string=)
(setf notifications (delete str notifications :test #'string=)))
(push str notifications)))
+ (defun run-notification-timer ()
+ (run-with-timer *notification-time* nil #'notifications-delete-last))
+
(defcommand notifications-reset ()
()
"Clear all notifications."
***************
*** 105,110 ****
--- 122,142 ----
"Delete the first notification."
(setf notifications (nreverse (cdr (nreverse notifications)))))
+ (defcommand notifications-start-messages ()
+ ()
+ "Start showing messages with notifications."
+ (setf *message-timer*
+ (run-with-timer 0
+ *message-timeout*
+ (lambda ()
+ (when notifications
+ (message-no-timeout (format nil "~{~a~^~%~}" notifications)))))))
+
+ (defcommand notifications-stop-messages ()
+ ()
+ "Stop showing messages with notifications."
+ (cancel-timer *message-timer*))
+
(defun notifications-as-string (&rest r)
(declare (ignore r))
(if notifications
***************
*** 126,131 ****
--- 158,165 ----
(define-key m (kbd "d") "notifications-delete-first")
(define-key m (kbd "D") "notifications-delete-last")
(define-key m (kbd "s") "notifications-show")
+ (define-key m (kbd "m") "notifications-start-messages")
+ (define-key m (kbd "M") "notifications-stop-messages")
m))
;; Local Variables:
После выполнения функции notifications-start-messages при получении сообщений получаем следующее:
15 мая 2009 г.
StumpWM
Установил и начал настраивать под себя StumpWM - фреймовый оконный менеджер, написанный на Common Lisp. Чтобы ознакомиться с некоторыми его возможностями, можно посмотреть видео ролик.
Установка
Зависимости:
Чтобы asdf видел пакеты, установленные с помощью, clbuild добавим следующую строку в ~/.sbclrc:
Устанавливаем последнюю версию StumpWM из репозитория:
В текущей директории появился файл stumpwm, который нужно указать в ~/.xinitrc:
Настройка
При запуске StumpWM использует файл ~/.stumpwmrc. Например, поместив следущие инструкции в ~/.stumpwmrc мы определим функцию, которая вызывается при нажатии C-t f. Она запускает Firefox, если он ещё не был запущен, в противном случае - переходит к ранее запущенному.
В качестве примера можно использовать файл sample-stumpwmrc.lisp, можно посмотреть на файлы .stumpwmrc других пользователей, также много инересного можно узнать из stumpwm.info.
Полностью поменять поведение StumpWM можно уже в процессе работы. Для этого можно:
Использование SLIME для настройки StumpWM
Установим SLIME и создадим сивольную ссылку на stumpwm.asd для clbuild:
Для запуска SLIME необходимо добавить в .emacs следующие строки, полученные при выполнении команды $ ./clbuild slime-configuration:
Создадим файл startstump для запуска StumpWM и swank:
Таким образом теперь для запуска не используетсся собранный с помощью make файл stumpwm, что исключает необходимость повторных сборок при обновлении stumpwm.
Изменим ~/.xinitrc:
clbuild запускает реализацию Common Lisp и загружает созданный нами файл.
Выполнив startx и открыв emacs, можно выполнить команду M-x slime-connect и использовать REPL для внесения измененний. Например, следующие команды сделают стандартную mode-line более информативной:
Установка
Зависимости:
- реализация Common Lisp (поддерживаются clisp и SBCL)
- clx
- cl-ppcre
- autoconf
- texinfo
$ darcs get http://common-lisp.net/project/clbuild/clbuild
$ cd clbuild
clbuild$ chmod +x clbuild
clbuild$ ./clbuild install clx cl-ppcre
Чтобы asdf видел пакеты, установленные с помощью, clbuild добавим следующую строку в ~/.sbclrc:
(push #p"/path/to/clbuild/systems/" asdf:*central-registry*)
Устанавливаем последнюю версию StumpWM из репозитория:
$ git clone git://git.savannah.nongnu.org/stumpwm.git
$ cd stumpwm
stumpwm$ autoconf
stumpwm$ ./configure && make
В текущей директории появился файл stumpwm, который нужно указать в ~/.xinitrc:
$ echo "exec /path/to/stumpwm" > ~/.xinitrc
$ startx
Настройка
При запуске StumpWM использует файл ~/.stumpwmrc. Например, поместив следущие инструкции в ~/.stumpwmrc мы определим функцию, которая вызывается при нажатии C-t f. Она запускает Firefox, если он ещё не был запущен, в противном случае - переходит к ранее запущенному.
(defcommand firefox () ()
"Start/Switchto Firefox."
(run-or-raise "firefox" '(:class "Firefox")))
(define-key *root-map* (kbd "f") "firefox")
В качестве примера можно использовать файл sample-stumpwmrc.lisp, можно посмотреть на файлы .stumpwmrc других пользователей, также много инересного можно узнать из stumpwm.info.
Полностью поменять поведение StumpWM можно уже в процессе работы. Для этого можно:
- внести изменения в ~/.stumpwmrc и выполнить команду С-t ; loadrc
- использовать emacs и stumpwm-mode.el
- использовать stumpish (STUMPwm Interactive SHell)
- использовать SLIME
Использование SLIME для настройки StumpWM
Установим SLIME и создадим сивольную ссылку на stumpwm.asd для clbuild:
$ cd /path/to/clbuild
clbuild$ ./clbuild install slime
clbuild$ ln -s /path/to/stumpwm.asd systems/stumpwm.asd
Для запуска SLIME необходимо добавить в .emacs следующие строки, полученные при выполнении команды $ ./clbuild slime-configuration:
(setq load-path (cons "/path/to/clbuild/source/slime" load-path))
(setq load-path (cons "/path/to/clbuild/source/slime/contrib" load-path))
(setq slime-backend "/path/to/clbuild/.swank-loader.lisp")
(setq inhibit-splash-screen t)
(load "/path/to/clbuild/source/slime/slime")
(setq inferior-lisp-program"/path/to/clbuild/clbuild --implementation sbcl lisp")
(setq slime-use-autodoc-mode nil)
(slime-setup '(slime-fancy slime-tramp slime-asdf))
(slime-require :swank-listener-hooks)
Создадим файл startstump для запуска StumpWM и swank:
;; -*-lisp-*-
(require :stumpwm)
(require :swank)
(swank-loader::setup)
(swank:create-server :dont-close t)
(stumpwm:stumpwm)
Таким образом теперь для запуска не используетсся собранный с помощью make файл stumpwm, что исключает необходимость повторных сборок при обновлении stumpwm.
Изменим ~/.xinitrc:
exec /path/to/clbuild/clbuild lisp --load /path/to/startstump
clbuild запускает реализацию Common Lisp и загружает созданный нами файл.
Выполнив startx и открыв emacs, можно выполнить команду M-x slime-connect и использовать REPL для внесения измененний. Например, следующие команды сделают стандартную mode-line более информативной:
; SLIME 2009-05-16
CL-USER> (in-package :stumpwm)
STUMPWM> (load-module "battery-portable")
T
STUMPWM> (load-module "cpu")
T
STUMPWM> (load-module "mem")
T
STUMPWM> (load-module "net")
T
STUMPWM> (setf stumpwm:*screen-mode-line-format*
(list "%n | "
'(:eval (run-shell-command "date +'%a %d %b %H:%M:%S' | tr -d [:cntrl:]" t))
" | %l| %c| %M| %B | %W"))
("%n | "
(:EVAL (RUN-SHELL-COMMAND "date +'%a %d %b %H:%M:%S' | tr -d [:cntrl:]" T))
" | %l| %c| %M| %B | %W")
STUMPWM> (mode-line)
NIL
Подписаться на:
Сообщения (Atom)