Emacs имеет крутую курву обучения, но чем дальше, тем больше хочется делать в нем все, что можно и нельзя. В частности он обладает большим числом средств для навигации по файловой системе.
Я, например, использую Dired mode, ido, Org mode и закладки. Но существует проблема с открытием файлов во внешних приложениях: pdf в evince, avi в mplayer и т.д. Причем хочется задавать эти связи в одном месте. Emacs не был бы Emacs'ом, если бы не позволял сделать для этого какой-нибудь грязный хак =)
Ассоциации приложений с типами файлов мы зададим в виде списка пар, в которых первый элемент — это строка, разделенных пробелом расширений, а второй — команда для запуска приложения:
Из строки расширений сделаем регулярку:
Напишем функцию, которая получает путь к файлу,
Теперь надо заставить Emacs запускать нашу функцию, при попытке открыть файл. Документация говорит нам, что фунции типа find-file используют find-file-noselect.
Поэтому мы сохраним системную функцию
и переопределим ее, чтобы она пыталась открыть файл во внешней программе,
Для Org mode напишем маленькую функцию, чтобы при открытии ссылок
переход в другое окно был только для файлов, открываемых внутри Emacs
и будем использовать ее для всех типов файлов
Пока особых проблем с этим не возникало, хотя, например, не работает запуск внешних приложений через tramp, но оно вроде и надо.
Скачать код.
Любая критика и советы, как говорится, велкам.
Я, например, использую Dired mode, ido, Org mode и закладки. Но существует проблема с открытием файлов во внешних приложениях: pdf в evince, avi в mplayer и т.д. Причем хочется задавать эти связи в одном месте. Emacs не был бы Emacs'ом, если бы не позволял сделать для этого какой-нибудь грязный хак =)
Ассоциации приложений с типами файлов мы зададим в виде списка пар, в которых первый элемент — это строка, разделенных пробелом расширений, а второй — команда для запуска приложения:
(defvar command-list
'(("jpg jpeg png bmp" .
"gqview")
("pdf djvu ps" .
"evince")
("html htm" .
"firefox -new-tab")
("ogv mpg mpeg avi flv
VOB wmv mp4 mov mkv divx
ogm m4v asf rmvb" .
"mplayer -fs")
("doc odf odt rtf" .
"ooffice")))
Из строки расширений сделаем регулярку:
(defun build-re (str)
(let ((re "\\.\\(")
(ext-list (split-string str)))
(dotimes (n (- (length ext-list) 1))
(setq re (concat re (nth n ext-list) "$\\|")))
(setq re (concat re (car (last ext-list)) "$\\)$"))
re))
Напишем функцию, которая получает путь к файлу,
(defun try-open-external (filename)
(let ((success nil))
;; проходит по списку команд,
(dolist (command command-list)
(let ((cmd (cdr command))
;; делает ругулярное выражение из расширений,
(re (build-re (car command))))
;; пытается сопоставить с ним путь.
(when (string-match re filename)
;; В случае успеха запускает программу,
(shell-command-to-string (concat cmd
" "
(shell-quote-argument filename)
" &> /dev/null &"))
(setq success t))))
;; и говорит нашла ли она ассоциацию с файлом.
success))
Теперь надо заставить Emacs запускать нашу функцию, при попытке открыть файл. Документация говорит нам, что фунции типа find-file используют find-file-noselect.
Поэтому мы сохраним системную функцию
(fset 'old-find-file-noselect (symbol-function 'find-file-noselect))
и переопределим ее, чтобы она пыталась открыть файл во внешней программе,
(defun find-file-noselect (filename &optional nowarn rawfile wildcards)
(if (try-open-external filename)
nil
;; а в случае неудачи вызывала системную функцию.
(old-find-file-noselect filename nowarn rawfile wildcards)))
Для Org mode напишем маленькую функцию, чтобы при открытии ссылок
переход в другое окно был только для файлов, открываемых внутри Emacs
(defun my-org-find-file (file)
(when (not (try-open-external file))
(find-file-other-window file)))
и будем использовать ее для всех типов файлов
(org-file-apps (quote ((".*" my-org-find-file file))))
Пока особых проблем с этим не возникало, хотя, например, не работает запуск внешних приложений через tramp, но оно вроде и надо.
Скачать код.
Любая критика и советы, как говорится, велкам.