ちょっとしたメモをとるのに便利かもしれないside-pocket-file.elというものを作った。

code readingとかしている時に、関数の挙動を調べたい時がある

そんな時に使うと便利だと思う。*1

foo.elを編集していて

C-c C-c でfoo.tmp.elが開かれる。
もう一度,C-c C-c でfoo.elに戻る。
foo.tmp.elに何か調べたいこととかメモをとったり実行してみたりすると便利。

code

(require 'cl)

;;;;
;; how to use
;; (require 'side-pocket-file)
;; (global-set-key "\C-c\C-c" 'sp-toggle-file)

;; C-c C-c, toggle [<file>.<ext> <-> <file>.tmp.<ext>]
	;;e.g. test.txt <-> test.tmp.txt

;;;;
;; you can make your own file name maker function
;; in .emacs
;; (sp-set-new-name-maker (sp-tiny-name-maker "-foo") (sp-tiny-normalize-maker "-foo"))
;; C-c C-c, toggle  [bar.el <-> bar-foo.el]

(defvar sp-files-alist nil)
(defvar sp-maker-function 'sp-default-name-maker)
(defvar sp-nomalize-function 'sp-default-normalize)

(defun decompose-file-path (path) ;;util
  (let ((ext (file-name-extension path))
	(basename (file-name-nondirectory path)))
    (if ext
	(values (file-name-directory path)
		(substring basename 0 (1- (string-match ext basename)))
		(concat "." (file-name-extension path)))
      (values (file-name-directory path) basename ""))))

(defun sp-default-name-maker (path)
  (multiple-value-bind (dir file ext) (decompose-file-path path)
    (concat dir file ".tmp" ext)))

(defun sp-default-normalize (path)
  (multiple-value-bind (dir file ext) (decompose-file-path path)
    (concat dir (replace-regexp-in-string ".tmp" "" file) ext)))

(defun sp-get-file (file) ;;elispは(car nil) => nilなのでこれで大丈夫
  (cadr (assoc file sp-files-alist)))

(defun sp-insert-to-alist (file)
  (let ((sp-file (sp-make-side-pocket-file-name file)))
    (push (list file sp-file) sp-files-alist)
    (push (list sp-file file) sp-files-alist)))

(defun sp-make-side-pocket-file-name (file)
  (funcall sp-maker-function file))

(defun sp-toggle-file () (interactive)
  (let* ((path (buffer-file-name))
	 (assoc-file (sp-get-file path)))
    (cond ((null path) (message (format "%s is not file buffer." (buffer-name))))
	  (assoc-file (find-file assoc-file))
	  (t (sp-find-file-with-create path)))))

(defun sp-name-normalize (path)
  (funcall sp-nomalize-function path))

(defun sp-find-file-with-create (path)
  (sp-insert-to-alist (sp-name-normalize path))
  (find-file (sp-get-file path)))

(defalias 'toggle-tmp-or-real-file 'sp-toggle-file)

;;;;;;;
;;util when you make your side-pocket file name maker.

(defmacro sp-tiny-name-maker (tag)
  `(function 
   (lambda (path)
     (multiple-value-bind (dir file ext) (decompose-file-path path)
       (concat dir file ,tag ext)))))

(defmacro sp-tiny-normalize-maker (tag)
  `(function
    (lambda (path)
      (multiple-value-bind (dir file ext) (decompose-file-path path)
	(concat dir (replace-regexp-in-string ,tag "" file) ext)))))


(defmacro sp-set-new-name-maker (maker-action normalize-action)
  `(progn (setq sp-files-alist nil)
	  (setq sp-maker-function ,maker-action)
	  (setq sp-nomalize-function ,normalize-action)))

;; (sp-set-new-name-maker (sp-tiny-name-maker ".tmp")
;; 		       (sp-tiny-normalize-maker ".tmp"))
;; then [bar.el <-> bar-foo.el]

(provide 'side-pocket-file)

自分で名前の書き換え規則とか作れるようにしなければもっと簡単に書けるんだよなー。

*1:*scratch*に書くと後で消えてしまうし