;;; ;;; na-recentf.el: なんちゃって「最近使ったファイル」 ;;; ;;; [2002/01/17] OSHIRO Naoki. キー入力で検索できるようにした ;;; [2002/01/08] OSHIRO Naoki. ;;; ;; [~/.emacs の設定] ;; ;; (autoload 'na-recentf "na-recentf" nil t) ;; (mapcar '(lambda (keymap) ;; (define-key keymap "\C-r" 'na-recentf)) ;; (list minibuffer-local-map ;; minibuffer-local-ns-map ;; minibuffer-local-completion-map ;; minibuffer-local-must-match-map)) (defvar na-recentf-buffer "*na-recentf*" "「最近使ったファイル」の表示バッファ") (defvar na-recentf-window-height 20 "「最近使ったファイル」の表示高さ") (defvar na-recentf-map nil) ;; キーバインドの設定 (if na-recentf-map () (let ((map (make-keymap))) (let ((key ?!)) (while (<= key ?~) (define-key map (string key) 'na-recentf-input-char) (setq key (1+ key)))) (define-key map " " 'na-recentf-find-file) (define-key map "\C-q" 'na-recentf-quit) (define-key map "\C-?" 'na-recentf-backward-delete-char) (substitute-key-definition 'keyboard-quit 'na-recentf-quit map global-map) (substitute-key-definition 'newline 'na-recentf-find-file map global-map) (setq na-recentf-map map))) (defun na-recentf-input-char () "検索文字列の1対応追加" (interactive) (let ((str-pre (concat input-string (string last-command-char))) str (hist file-name-history)) (setq str (na-recentf-try-completion str-pre hist)) (if (not str) (progn (message "%s[NOT match]" str-pre) (sit-for 1) (message "%s" input-string)) (if str (setq input-string str)) (na-recentf-make-summary (na-recentf-update str))))) (defun na-recentf-backward-delete-char () "検索文字列の1対応削除" (interactive) (let ((str input-string) hist pre-hist) (setq pre-hist (na-recentf-update str)) (catch 'deleted (while str (if (string= str "") () (setq str (substring str 0 (1- (length str)))) (setq hist (na-recentf-update str))) (if (not (equal pre-hist hist)) (throw 'deleted t)) (setq pre-hist hist))) (na-recentf-make-summary hist) (setq input-string str))) (defun na-recentf-try-completion (str list) "指定文字列を含んでそれ以降の最大補完文字列を求める" (let (ch pre-ch idx l x) (catch 'completed (while t (setq l list) (setq pre-ch nil) (while l (setq x (car l)) (if (not (string-match str x)) () (setq idx (match-end 0)) (if (> idx (1- (length x))) (throw 'completed t)) (setq ch (substring x idx (1+ idx))) (if (and pre-ch (not (string= ch pre-ch))) (throw 'completed t)) (setq pre-ch ch)) (setq l (cdr l))) (if ch (setq str (concat str ch)) (throw 'completed t)))) (if (not ch) (setq str nil)) str)) (defun na-recentf-delete-duplicate (hist) "重複したファイルヒストリを削除" (let (l m x y res) (setq l (mapcar (lambda (x) (cons x (expand-file-name x))) hist)) (setq res nil) (while l (setq x (car l)) (setq m (cdr l)) (setq l (cons x (delq nil (mapcar (lambda (y) (if (string= (cdr x) (cdr y)) nil y) ) m)))) (setq l (cdr l)) (setq res (cons (car x) res))) (reverse res))) (defun na-recentf-update (str) "指定文字列に対応したファイルヒストリの更新" (let ((hist file-name-history)) (if (not str) () (setq hist (delq nil (mapcar (lambda (x) (if (string-match str x) x)) hist)))) hist)) (defun na-recentf-make-summary (hist) "ファイルヒストリの一覧表示" (if (not hist) () (setq hist (na-recentf-delete-duplicate hist)) (set-buffer (get-buffer-create na-recentf-buffer)) (pop-to-buffer na-recentf-buffer) (let ((h na-recentf-window-height)) (setq h (max (min h (1+ (length hist))) window-min-height)) (enlarge-window (- h (window-height)))) (setq buffer-read-only nil) (erase-buffer) (save-excursion (mapcar (lambda (x) (goto-char (point-min)) (insert (if (file-exists-p x) " " "?")) (insert (if (get-file-buffer x) "*" " ")) (insert (format "%s\n" x))) hist)) (goto-char (point-max)) (delete-char -1) (let (p) (forward-line (- 2 (window-height))) (beginning-of-line) (setq p (point)) (goto-char (point-max)) (beginning-of-line) (set-window-start (selected-window) p)) (set-buffer-modified-p nil) (setq buffer-read-only t))) (defun na-recentf () "「最近使ったファイル」をリスト表示し選択支援する SPC na-recentf-fild-file C-g na-recentf-quit" (interactive) (set-buffer (get-buffer-create na-recentf-buffer)) (kill-all-local-variables) (mapcar 'make-local-variable '(input-string)) (use-local-map na-recentf-map) (setq input-string nil) (setq major-mode 'na-recentf mode-name "na-recentf") (na-recentf-make-summary file-name-history)) (defun na-recentf-get-line () "現在行をファイル名として取得" (let (f (cb (current-buffer))) (save-excursion (set-buffer na-recentf-buffer) (setq f (buffer-substring (progn (beginning-of-line) (move-to-column 2) (point)) (progn (end-of-line) (point))))) (set-buffer cb) f)) (defun na-recentf-find-file () "現在行のファイル名をミニバッファへ入れる" (interactive) (let ((f (na-recentf-get-line))) (set-buffer (window-buffer (minibuffer-window))) (erase-buffer) (insert f) ;(exit-minibuffer) (kill-buffer (get-buffer na-recentf-buffer)) (select-window (minibuffer-window)) ;(find-file f) )) (defun na-recentf-quit () "終了" (interactive) (kill-buffer (get-buffer na-recentf-buffer)) (select-window (minibuffer-window))) (provide 'na-recentf) ;;; end of na-recentf here.