Lispの勉強も兼ねて、自分で実装してみました。
プログラムは記事の最後に載せます。
機能
実装済みの機能は以下のとおりです。
- 現在表示しているバッファをブックマークとして登録する
- ブックマークの一覧を表示する
- ブックマークの一覧からファイルを開く
- ブックマークを削除する
使用方法
まず、プログラムを読み込みます。専用のパッケージを定義したので、合わせてuse-packageします。
(require "bookmark") (use-package "bookmark")
次に、キーバインドの設定をします。今のところ公開している関数は次の2つです。
- bookmark-add-current-buffer: 表示しているバッファをブックマークする
- bookmark-list-bookmarks: ブックマークの一覧を表示する
(global-set-key '(#\C-c #\a #\b) 'bookmark-add-current-buffer) (global-set-key '(#\C-c #\l #\b) 'bookmark-list-bookmarks)
bookmark-add-current-bufferを呼ぶと、現在のバッファをブックマークします。その際、ブックマーク名を入力できます。
bookmark-list-bookmarksを呼ぶと、ブックマーク一覧を表示します。一覧からファイルの表示と、ブックマークの削除ができます。ブックマークしたファイルの表示は[f]キーを押下し、ブックマークの削除は[d]キーです。
ブックマーク一覧を実装するときは、xyzzy付属のbuf-menu.lが参考になりました。
よろしければ使ってみてください。
; bookmark.l v0.0.1 (provide "bookmark") (defpackage "bookmark" (:use "lisp" "editor")) (export '(bookmark-add-current-buffer bookmark-list-bookmarks)) (defvar *bookmark-file* "~/.bookmark") (defvar *bookmarks* nil) (defvar *bookmark-menu-mode-hook* nil) (defstruct bookmark name path) (defun bookmark-add-current-buffer (&optional name) "現在のバッファをブックマークへ追加する。" (interactive "sBookmark Name: ") (add-bookmark (make-bookmark :name name :path (get-buffer-file-name))) (save-bookmarks *bookmarks* *bookmark-file*)) (defun add-bookmark (bookmark) "bookmarkを*bookmarks*へ追加する。" (push bookmark *bookmarks*)) (defun delete-bookmark (bookmark) "*bookmarks*からbookmarkを取り除いたリストを返す。" (let ((name (bookmark-name bookmark)) (path (bookmark-path bookmark))) (delete-if (lambda (bm) (and (equal name (bookmark-name bm)) (equal path (bookmark-path bm)))) *bookmarks*))) (defun open-bookmark (bookmark) "bookmarkからpathを取得し、バッファを開く。" (find-file (bookmark-path bookmark))) (defun save-bookmarks (bookmarks bookmark-file) "bookmarksをbookmark-fileへ出力する" (with-open-file (s bookmark-file :direction :output :if-exists :overwrite :if-does-not-exist :create) (dolist (bookmark bookmarks) (save-bookmark bookmark s)))) (defun save-bookmark (bookmark output-stream) "output-streamへbookmarkを出力する" (format output-stream "~A?~A~%" (bookmark-name bookmark) (bookmark-path bookmark))) (defun load-bookmarks (bookmark-file) "bookmark-fileを読み込み、構造体bookmarkのリストを返す。" (let ((bookmarks nil) (line nil)) (with-open-file (file-stream bookmark-file :direction :input :if-does-not-exist nil) (while (and file-stream (setq line (read-line file-stream nil))) (push (load-bookmark line) bookmarks))) bookmarks)) (defun load-bookmark (line) "lineを解析し、構造体bookmarkを返す。" (let ((separator-position (position #\? line :from-end t))) (if separator-position (make-bookmark :name (subseq line 0 separator-position) :path (subseq line (1+ separator-position)))))) (defun bookmark-menu-mode () (interactive) (kill-all-local-variables) (setq buffer-mode 'bookmark-menu-mode) (setq mode-name "Bookmark") (use-keymap *bookmark-menu-mode-map*) (setq buffer-read-only t) (set-buffer-fold-width nil) (make-local-variable 'kept-undo-information) (setq kept-undo-information nil) (make-local-variable 'need-not-save) (setq need-not-save t) (make-local-variable 'auto-save) (setq auto-save nil) (make-local-variable 'revert-buffer-function) (setq revert-buffer-function #'bookmark-list-bookmarks) (run-hooks '*bookmark-menu-mode-hook*)) (defun bookmark-menu-open-bookmark () (interactive) (open-bookmark (elt *bookmarks* (1- (current-line-number))))) (defun bookmark-menu-delete-bookmark () (interactive) (setq *bookmarks* (delete-bookmark (elt *bookmarks* (1- (current-line-number))))) (save-bookmarks *bookmarks* *bookmark-file*) (revert-buffer)) (defun bookmark-menu-delete-buffer () (interactive) (delete-buffer (selected-buffer))) (defvar *bookmark-menu-mode-map* nil) (unless *bookmark-menu-mode-map* (setq *bookmark-menu-mode-map* (make-sparse-keymap)) (define-key *bookmark-menu-mode-map* #\f 'bookmark-menu-open-bookmark) (define-key *bookmark-menu-mode-map* #\d 'bookmark-menu-delete-bookmark) (define-key *bookmark-menu-mode-map* #\q 'bookmark-menu-delete-buffer)) (defun bookmark-list-bookmarks () "*bookmarks*を*Bookmarks*へ出力し、bookmark-menu-modeを起動する。" (interactive "p") (setq *bookmarks* (load-bookmarks *bookmark-file*)) (with-output-to-temp-buffer ("*Bookmarks*") (dolist (bookmark *bookmarks*) (format t "~A ~A~%" (bookmark-name bookmark) (bookmark-path bookmark)))) (bookmark-menu-mode))
0 件のコメント:
コメントを投稿