среда, 16 декабря 2009 г.

Генератор кнопок

В (S)XEmacs есть классный package, называется xpm-button.el. Он умеет на лету генерировать картинку с кнопкой. Всё вроде бы хорошо, но «красота» сгенерированных кнопок повергает в уныние. Решил написать достаточно гибкий генератор красивых кнопок используя Wand-mode. По мере написания генератора, добавлял необходимый функционал в Wand-mode. Вот что в итоге получилось:

(wand-button 150 32 "Wand Button"
             :bg "cornflowerblue" :fg "white"
             :round 8.0 :depth 1 :yoff 8 ; :type 'pressed
             :wand-font (make-wand-font :family "Zapfino"))

button1

(wand-button 100 20 "Wand Button"
             :bg "gray80" :fg "black" :round 10.0
             :contrast 0.5 :depth 2 ; :type 'pressed
             :wand-font (make-wand-font :family "Copperplate"))

button2

(wand-button 100 40 (encode-coding-string "привет" 'utf-8)
             :bg "palegreen" :fg "green" :round 0.0
             :depth 4 :yoff -2 ; :type 'pressed
             :wand-font (make-wand-font :family "Arial Black"
                                        :size 20))

button2

Интересно будет этот функционал внедрить в Emacs widgets, а то кнопки там сделаны через очень большую задницу.

ReST source Скачать оригинал

пятница, 27 ноября 2009 г.

Wand-mode - новые возможности

Wand-mode развивается, с тех пор как я сделал описание, было добавлено несколько интересных возможностей. Их я и опишу.

Имя файла в имени буфера

Откроем какую-нибудь картинку: C-x C-f lg-tree.jpg RET, получаем примерно следующее:

orig image

Замечаем, что в mode-line отображается имя буфера, которое теперь содержит имя оригинального файла. Удобно при переключении с помощью C-x C-b.

Новая операция: modulate

Фотка сама по себе классная, но природа выглядит как-то уныло, немного приукрасим, с помощью команды o modulate RET saturation RET 60 RET, получим результат:

sat inc 60 percents

60% increased saturation

Уже намного лучше.

Поддержка IPTC профиля

Хочется добавить информацию о том, что это там на фотке. Воспользуемся редактором IPTC профиля. Добавим IPTC теги с помощью p caption RET lg climbes trees RET и p keywords RET js-kit, corporative RET, получим:

caption and keywords added

Caption and Keywords added

Pixel color picker

Интересно какого цвета у меня трусы, кликнем на них и увидим:

pixel color picker

Pixel color picker

Видим координаты пикселя, по которому мы кликнули, его цвет и разложение по RGB. Удобно.

Глобальные операции

Иногда нужно просмотреть несколько картинок применяя конкретный набор операций, например увеличение. Для этого теперь есть команда фиксирования операций, по умолчанию висит на O, нажмём её и перейдём к следующей картинке в директории с помощью SPC:

global operations

Global operations applied

Видим список глобальных операций, а также замечаем, что они были автоматически применены к картинке. Однако для этой картинки увеличение saturation не подходит. Отменим с помощью undo (C-/):

operations canceled

Operations canceled

Чтобы сбросить глобальные операции нужно нажать C-u O.

Редактор свойств изображения

Иногда нужно подправить EXIF данные у изображения. Лично я не пользуюсь этой возможностью (мне хватает IPTC профиля), но есть один знакомый фотограф, который попросил эту функциональность в Wand-mode. Мне не сложно за пару пива. Вызвать редактор можно с помощью кнопки e. Он отфильтрует свойства согласно переменной Wand-mode-properties-pattern ("^exif:" по умолчанию).

Новая операция: grayscale

Существует множество методик преобразования картинки в чёрно-белую. Один из них, например, полностью удалить saturation с помощью o modulate RET saturation RET -100 RET, что часто приводит к желаемому результату. Всё же была добавлена возможность поменять colormap на grayscale — o grayscale RET

Новая операция: fit to size

Иногда нужно изменить размеры изображения, чтобы она влазила в определённый размер. Теперь это можно сделать с помощью o fit to size RET. Эта операция запросит ширину, высоту и сохраняя соотношение сторон изменит размер. Есть также пользовательская переменная Wand-mode-scaler, которая отвечает за то, какой преобразователь будет использован. Вы можете создавать свои собственные преобразователи с помощью Wand-make-scaler; неплохой настройкой может быть:

(setq Wand-mode-scaler (Wand-make-scaler :GaussianFilter 1))

Документация к Wand-mode-scaler и Wand-make-scaler содержит исчерпывающую информацию о преобразователях.

ReST source Скачать оригинал

четверг, 12 ноября 2009 г.

Судоку для (S)XEmacs

Не спалось как-то ночью и мягкой подруги не было под рукой. Решил поиграть во что-нибудь. Тетрис слишком активный, сокобан уже прошёл весь, World of Goo перегревает комп — решил погонять в судоку. Зашёл на websudoku.com и начал играть, всё бы хорошо, но это не в SXEmacs и недоступно offline. Решил написать sudoku.el для игры в судоку под SXEmacs. Поискал в инете и нашёл sudoku.el для (X)Emacs. Скачал, запустил и не обрадовался, посмотрел код — вообще расстроился. В итоге ночь провёл за переписыванием sudoku.el, чтобы удовлетворить свои нужды, а именно:

  • Удобный, красивый и информативный интерфейс
  • Возможность скачивания судок с websudoku.com и menneske.no
  • Возможность печати судок
  • Возможность редактирования судок
  • Возможность сохранения/загрузки судок
  • Наличие карандашей для сложных техник и экспериментов
  • Возможность решать только реально сложные задачи, т.е. авто-заполнение (полу)очевидных полей

Пример

Запускаем M-x sudoku RET:

sudoku-mode

Сразу видим кучу очевидных полей для заполнения, например, R5C5 (где курсор) и понятно дело лениво их все заполнять, поэтому нажимаем a, получаем:

autoinsert

Теперь действительно сложная задача, но сразу видно интересность значения 4, поэтому берём карандаш1p (от pencil) и применяем технику Nishio начиная с R8C9, получаем:

pencil
  1. R8C9 -> 4 (начало Nishio)
  2. R2C3 -> 4 (единственное место в C3 где может быть 4)
  3. R3C7 -> 4 (единственное место в R1 где может быть 4)
  4. в восьмом квадрате некуда ставить 4

то есть в R8C9 не может стоять 4. C-u p и отменяем карандаш. Теперь мы знаем, что 4 стоит в R2C9:

won

Хорошая судочка, пожалуй сыну подойдёт, распечатаем её нажав P, на бумаге это выглядит вот так:

printed

Скачать

Скачать можно с http://lgarc.narod.ru/xemacs/sudoku.el

Замечания, баги, фиксы присылайте на lg AT sxemacs.org


1В режиме карандаша авто-заполнение отключается

ReST source Скачать оригинал

среда, 30 сентября 2009 г.

Говорящий SXEmacs

Баловался тут давеча с разными способами более тесной интеграции SXEmacs с Mac OS. Сделал (а точнее стащил из GNU Emacs) интересную функцию, с помощью которой можно запускать различные сценарии AppleScript:

(defun do-applescript (&rest script-lines)
  (let ((script (mapconcat 'identity script-lines "\n"))
        start cmd return)
    (while (string-match "\n" script)
      (setq script (replace-match "\r" t t script)))
    (while (string-match "\"" script start)
      (setq start (+ 2 (match-beginning 0))
            script (replace-match "\\\"" t t script)))
    (setq cmd (concat "osascript -e \"\"\"" script "\"\"\""))
    (setq return (shell-command-to-string cmd))
    (concat "\"" return "\"")))

Применения этой процедуры очевидны. Например можно заставить Growl отображать сообщения SXEmacs:

(defun growl (title message)
  (do-applescript
   "tell application \"GrowlHelperApp\""
   (format "notify with name \"SXEmacs Notification\" title %S description %S application name \"SXEmacs\" image from location \"file:///opt/local/share/sxemacs-22.1.10/etc/sxemacs-icon.png\"" title message)
   "end tell"))

Но, что более интересно, можно научить SXEmacs разговаривать, используя VoiceOver!

(defvar lg-say-voices
  '((agnes . "Agnes") (albert . "Albert") (alex . "Alex")
    (badnews . "BadNews") (bahh . "Bahh") (bells . "Bells")
    (boing . "Boing") (bruce . "Bruce") (bubbles . "Bubbles")
    (cellos . "Cellos") (deranged . "Deranged") (fred . "Fred")
    (goodnews . "GoodNews") (hysterical . "Hysterical") (junior . "Junior")
    (kathy . "Kathy") (organ . "Organ") (princess . "Princess")
    (ralph . "Ralph") (trinoids . "Trinoids") (vicki . "Vicki")
    (victoria . "Victoria") (whisper . "Whisper") (zarvox . "Zarvox")))

(defun lg-say-the-text (text &optional voice)
  (let* ((sv (cdr (assq voice lg-say-voices)))
         (svoice (if sv (format " using %S" sv) ""))
         ;; " -> ' in order to avoid osascript confusion
         (nt (replace-in-string text "\"" "'")))
    (do-applescript (format "say %S%s" nt svoice))
    (growl "Text via VoiceOver" "Done!")))

(defun lg-say-region-or-buffer (arg)
  "Say contents of the buffer or region.
If prefix ARG is specified then use custom voice."
  (interactive "P")
  (let ((voice (and current-prefix-arg
                    (intern
                     (completing-read "Voice: "
                      (mapcar #'(lambda (v)
                                  (list (symbol-name (car v))))
                              lg-say-voices)
                      nil t))))
        (text (if (region-active-p)
                  (buffer-substring (region-beginning) (region-end))
                (buffer-substring))))
    (lg-say-the-text text voice)))

(define-key global-map (kbd "C-c s") 'lg-say-region-or-buffer)

Далее, можно например реализовать процедуру, которая будет читать тело письма в gnus:

(defun lg-gnus-say-article-body ()
  "Say body of the current gnus article."
  (interactive)
  (let ((atxt (with-current-buffer gnus-article-buffer
                (save-restriction
                  (article-goto-body)
                  (buffer-substring (point) (point-max))))))
    (lg-say-the-text atxt)))

Единственная проблема с данной реализацией это то, что SXEmacs блокирует во время выполнения сценария AppleScript. Нужно расширить процедуру do-applescript, чтобы она поддерживала параметр IN-BACKGROUND.

ReST source Скачать оригинал

суббота, 8 августа 2009 г.

MacOS clipboarding

В Mac OS есть отличное приложение — X11.app. Реальный и работающий X сервер. Оно позволило при переходе с FreeBSD на MacOS практически не менять среду разработки и использовать привычные, старые добрые X приложения, такие как xterm, Inkscape или SXEmacs. Единственный минус это отсутствие внятного межклипбордного взаимодействия между Cocoa приложениями и X приложениями, особенно бесило, что я не могу выделить что-то в SXEmacs и вставить в Firefox. Давеча нашёл способ как это можно сделать:

(when (eq system-type 'darwin)
  ;; Make C-w, M-y interact with Mac OS X clipboard
  (defun lg-paste-from-osx ()
    (shell-command-to-string "pbpaste"))
  (defun lg-paste-to-osx (text &optional push)
    (let* ((process-connection-type nil)
           (proc (start-process "pbcopy" nil "pbcopy")))
      (process-send-string proc text)
      (process-send-eof proc)))
  (setq interprogram-paste-function 'lg-paste-from-osx)
  (setq interprogram-cut-function 'lg-paste-to-osx))

Теперь, после C-w или M-w в SXEmacs, я могу делать C-v в Cocoa приложениях, а выделив что-то в Cocoa приложениях и скопировав, я могу вставлять в SXEmacs с помощью C-y.

ReST source Скачать оригинал