PageRenderTime 65ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/local-elisp/historyf/historyf.el

https://github.com/lugecy/dot-emacs
Emacs Lisp | 411 lines | 316 code | 33 blank | 62 comment | 0 complexity | 1d2c69f7ad3922768549dcf9c36afc2a MD5 | raw file
  1. ;;; historyf.el --- file history library like browser
  2. ;; -*- Mode: Emacs-Lisp -*-
  3. ;; Copyright (C) 2010 by 101000code/101000LAB
  4. ;; This program is free software; you can redistribute it and/or modify
  5. ;; it under the terms of the GNU General Public License as published by
  6. ;; the Free Software Foundation; either version 2 of the License, or
  7. ;; (at your option) any later version.
  8. ;; This program is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;; GNU General Public License for more details.
  12. ;; You should have received a copy of the GNU General Public License
  13. ;; along with this program; if not, write to the Free Software
  14. ;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15. ;; Version: 0.0.7
  16. ;; Author: k1LoW (Kenichirou Oyama), <k1lowxb [at] gmail [dot] com> <k1low [at] 101000lab [dot] org>
  17. ;; URL: http://code.101000lab.org
  18. ;;; Install
  19. ;; Put this file into load-path'ed directory, and byte compile it if
  20. ;; desired. And put the following expression into your ~/.emacs.
  21. ;;
  22. ;; (require 'historyf)
  23. ;;
  24. ;;; Commentary:
  25. ;;; Commands:
  26. ;;
  27. ;; Below are complete command list:
  28. ;;
  29. ;; `historyf-back'
  30. ;; Back file history.
  31. ;; `historyf-back-same-mode-history'
  32. ;; Back same mode file history.
  33. ;; `historyf-forward'
  34. ;; Forward file history.
  35. ;; `historyf-forward-same-mode-history'
  36. ;; Forward same mode file history.
  37. ;; `historyf-clear-history'
  38. ;; Clear file history.
  39. ;;
  40. ;;; Customizable Options:
  41. ;;
  42. ;; Below are customizable option list:
  43. ;;
  44. ;; `historyf-major-modes'
  45. ;; Target major-mode.
  46. ;; default = (quote (emacs-lisp-mode lisp-interaction-mode c-mode cc-mode c++-mode ...))
  47. ;; `historyf-minor-modes'
  48. ;; Target minor-mode.
  49. ;; default = (quote (cake))
  50. ;; `historyf-limit'
  51. ;; File history limit.
  52. ;; default = 100
  53. ;;; TODO
  54. ;; Add more testcase
  55. ;;; Code:
  56. (eval-when-compile
  57. (require 'cl))
  58. (defgroup historyf nil
  59. "File history like browser"
  60. :group 'lisp
  61. :prefix "historyf-")
  62. (defvar historyf-history nil
  63. "File history.")
  64. (defcustom historyf-major-modes
  65. '(emacs-lisp-mode
  66. lisp-interaction-mode
  67. c-mode cc-mode c++-mode java-mode
  68. perl-mode cperl-mode python-mode ruby-mode
  69. ecmascript-mode javascript-mode js2-mode php-mode css-mode
  70. makefile-mode sh-mode fortran-mode f90-mode ada-mode
  71. xml-mode sgml-mode)
  72. "Target major-mode."
  73. :type 'list
  74. :group 'historyf)
  75. (defcustom historyf-minor-modes
  76. '(cake yarm li3 titanium)
  77. "Target minor-mode."
  78. :type 'list
  79. :group 'historyf)
  80. (defcustom historyf-limit 100
  81. "File history limit."
  82. :type 'inter
  83. :group 'historyf)
  84. (defvar historyf-mark nil)
  85. (defvar historyf-forward-temp nil)
  86. (defadvice switch-to-buffer (before historyf-switch-to-buffer activate)
  87. (historyf-push-history))
  88. (defun historyf-push-history ()
  89. "Push file history."
  90. (let ((active-modes (historyf-active-mode-list))
  91. (file (buffer-file-name)))
  92. (when (and active-modes file)
  93. (historyf-clear-head)
  94. (unless (equal (expand-file-name file) (cdar historyf-history))
  95. (push (random) active-modes)
  96. (push (cons active-modes (expand-file-name (buffer-file-name))) historyf-history)
  97. (unless (< (length historyf-history) historyf-limit)
  98. (setq historyf-history (subseq historyf-history 0 (1- historyf-limit))))))))
  99. (defun historyf-make-history ()
  100. "Make file history."
  101. (let ((active-modes (historyf-active-mode-list))
  102. (file (buffer-file-name)))
  103. (unless (not active-modes)
  104. (push (random) active-modes)
  105. (cons active-modes (expand-file-name (buffer-file-name))))))
  106. ;; (historyf-make-history)
  107. (defun historyf-clear-head ()
  108. "Clear head history."
  109. (when historyf-mark
  110. (setq historyf-history (cdr (memq historyf-mark historyf-history))))
  111. (setq historyf-mark nil
  112. historyf-forward-temp nil))
  113. (defun historyf-find-file (file)
  114. "Find file."
  115. (message (concat "switch to " file))
  116. (find-file file))
  117. (defun historyf-back (&optional mode-list)
  118. "Back file history."
  119. (interactive)
  120. (let ((temp-hist))
  121. (ad-disable-advice 'switch-to-buffer 'before 'historyf-switch-to-buffer)
  122. (ad-activate 'switch-to-buffer)
  123. (if (not mode-list)
  124. ;; no mode-list
  125. (if historyf-mark
  126. (setq temp-hist (cadr (memq historyf-mark historyf-history)))
  127. (setq temp-hist (car historyf-history)))
  128. ;; else
  129. (setq hist (if historyf-mark
  130. (cdr (memq historyf-mark historyf-history))
  131. historyf-history))
  132. (mapc (lambda (h)
  133. (if (and (intersection (car h) mode-list)
  134. (not temp-hist))
  135. (setq temp-hist h)))
  136. hist))
  137. (when temp-hist
  138. (unless historyf-forward-temp
  139. (setq historyf-forward-temp (historyf-make-history)))
  140. (historyf-find-file (cdr temp-hist))
  141. (setq historyf-mark temp-hist))
  142. (ad-enable-advice 'switch-to-buffer 'before 'historyf-switch-to-buffer)
  143. (ad-activate 'switch-to-buffer)))
  144. (defun historyf-back-same-mode-history ()
  145. "Back same mode file history."
  146. (interactive)
  147. (let ((active-modes (historyf-active-mode-list)))
  148. (historyf-back active-modes)))
  149. (defun historyf-forward (&optional mode-list)
  150. "Forward file history."
  151. (interactive)
  152. (let* ((temp-hist)
  153. (history-head (unless (not historyf-mark)
  154. (subseq historyf-history 0 (position historyf-mark historyf-history)))))
  155. (ad-disable-advice 'switch-to-buffer 'before 'historyf-switch-to-buffer)
  156. (ad-activate 'switch-to-buffer)
  157. (if (not mode-list)
  158. ;; no mode-list
  159. (when historyf-mark
  160. (if history-head
  161. (historyf-find-file (cdar (reverse history-head)))
  162. (when historyf-forward-temp
  163. (historyf-find-file (cdr historyf-forward-temp))
  164. (setq historyf-forward-temp nil)))
  165. (setq historyf-mark (car (reverse history-head))))
  166. ;; else
  167. (unless (not historyf-mark)
  168. (if history-head
  169. (progn
  170. (mapc (lambda (h)
  171. (if (and (intersection (car h) mode-list)
  172. (not temp-hist))
  173. (setq temp-hist h)))
  174. (reverse history-head))
  175. (if (not temp-hist)
  176. (unless (not (and historyf-forward-temp
  177. (intersection (car historyf-forward-temp) mode-list)))
  178. (historyf-find-file (cdr historyf-forward-temp))
  179. (setq historyf-forward-temp nil)
  180. (setq historyf-mark nil))
  181. (historyf-find-file (cdr temp-hist))
  182. (setq historyf-mark temp-hist)))
  183. (unless (not (and historyf-forward-temp
  184. (intersection (car historyf-forward-temp) mode-list)))
  185. (historyf-find-file (cdr historyf-forward-temp))
  186. (setq historyf-forward-temp nil)
  187. (setq historyf-mark nil)))))
  188. (ad-enable-advice 'switch-to-buffer 'before 'historyf-switch-to-buffer)
  189. (ad-activate 'switch-to-buffer)))
  190. (defun historyf-forward-same-mode-history ()
  191. "Forward same mode file history."
  192. (interactive)
  193. (let ((active-modes (historyf-active-mode-list)))
  194. (historyf-forward active-modes)))
  195. (defun historyf-clear-history ()
  196. "Clear file history."
  197. (interactive)
  198. (setq historyf-history nil)
  199. (setq historyf-mark nil)
  200. (setq historyf-forward-temp nil))
  201. (defun historyf-active-mode-list ()
  202. "Active mode list."
  203. (let ((active-major-mode (historyf-active-major-mode))
  204. (active-minor-modes (historyf-active-minor-mode-list))
  205. (active-modes))
  206. (if active-major-mode
  207. (push active-major-mode active-modes))
  208. (if active-minor-modes
  209. (setq active-modes (union active-minor-modes active-modes)))
  210. active-modes))
  211. (defun historyf-active-major-mode ()
  212. "Active major-mode."
  213. (if (and (buffer-file-name)
  214. (memq major-mode historyf-major-modes))
  215. major-mode
  216. nil))
  217. (defun historyf-active-minor-mode-list ()
  218. "Active minor-mode list."
  219. (let ((active-minor-modes))
  220. (mapc (lambda (mode) (condition-case nil
  221. (if (and (symbolp mode) (symbol-value mode))
  222. (add-to-list 'active-minor-modes mode))
  223. (error nil) ))
  224. minor-mode-list)
  225. (if (and (buffer-file-name)
  226. (intersection active-minor-modes historyf-minor-modes))
  227. (intersection active-minor-modes historyf-minor-modes)
  228. nil)))
  229. ;; Tests
  230. (dont-compile
  231. (when (fboundp 'expectations)
  232. (expectations
  233. (desc "init")
  234. (expect t
  235. (setq historyf-test-dir (expand-file-name (concat default-directory "t/")))
  236. t)
  237. (expect 'emacs-lisp-mode
  238. (find-file (concat historyf-test-dir "test.el"))
  239. major-mode)
  240. (expect nil
  241. (historyf-clear-history)
  242. historyf-history)
  243. (desc "push file history test")
  244. (expect 0
  245. (length historyf-history))
  246. (expect nil
  247. (cdar (car historyf-history)))
  248. (expect nil
  249. historyf-forward-temp)
  250. (expect 'emacs-lisp-mode
  251. (find-file (concat historyf-test-dir "test2.el"))
  252. major-mode)
  253. (expect 1
  254. (length historyf-history))
  255. (expect '(emacs-lisp-mode)
  256. (cdar (car historyf-history)))
  257. (expect (concat historyf-test-dir "test.el")
  258. (cdr (car historyf-history)))
  259. (expect 'c-mode
  260. (find-file (concat historyf-test-dir "test3.c"))
  261. major-mode)
  262. (expect 2
  263. (length historyf-history))
  264. (expect '(emacs-lisp-mode)
  265. (cdar (car historyf-history)))
  266. (expect 'emacs-lisp-mode
  267. (find-file (concat historyf-test-dir "test4.el"))
  268. major-mode)
  269. (expect 3
  270. (length historyf-history))
  271. (expect '(c-mode)
  272. (cdar (car historyf-history)))
  273. (desc "back file history test")
  274. (expect (concat historyf-test-dir "test3.c")
  275. (historyf-back)
  276. (expand-file-name (buffer-file-name)))
  277. (expect 3
  278. (length historyf-history))
  279. (expect (concat historyf-test-dir "test4.el")
  280. (cdr historyf-forward-temp))
  281. (expect (concat historyf-test-dir "test2.el")
  282. (historyf-back)
  283. (expand-file-name (buffer-file-name)))
  284. (expect 3
  285. (length historyf-history))
  286. (expect (concat historyf-test-dir "test4.el")
  287. (cdr historyf-forward-temp))
  288. (expect (concat historyf-test-dir "test.el")
  289. (historyf-back)
  290. (expand-file-name (buffer-file-name)))
  291. (expect 3
  292. (length historyf-history))
  293. (expect (concat historyf-test-dir "test4.el")
  294. (cdr historyf-forward-temp))
  295. (expect (concat historyf-test-dir "test.el")
  296. (historyf-back)
  297. (expand-file-name (buffer-file-name)))
  298. (expect 3
  299. (length historyf-history))
  300. (expect (concat historyf-test-dir "test4.el")
  301. (cdr historyf-forward-temp))
  302. (desc "forward file history test")
  303. (expect (concat historyf-test-dir "test2.el")
  304. (historyf-forward)
  305. (expand-file-name (buffer-file-name)))
  306. (expect 3
  307. (length historyf-history))
  308. (expect (concat historyf-test-dir "test4.el")
  309. (cdr historyf-forward-temp))
  310. (expect (concat historyf-test-dir "test3.c")
  311. (historyf-forward)
  312. (expand-file-name (buffer-file-name)))
  313. (expect 3
  314. (length historyf-history))
  315. (expect (concat historyf-test-dir "test4.el")
  316. (cdr historyf-forward-temp))
  317. (expect (concat historyf-test-dir "test4.el")
  318. (historyf-forward)
  319. (expand-file-name (buffer-file-name)))
  320. (expect 3
  321. (length historyf-history))
  322. (expect nil
  323. (cdr historyf-forward-temp))
  324. (desc "back same mode file history test")
  325. (expect (concat historyf-test-dir "test2.el")
  326. (historyf-back-same-mode-history)
  327. (expand-file-name (buffer-file-name)))
  328. (expect 3
  329. (length historyf-history))
  330. (expect (concat historyf-test-dir "test4.el")
  331. (cdr historyf-forward-temp))
  332. (expect (concat historyf-test-dir "test.el")
  333. (historyf-back-same-mode-history)
  334. (expand-file-name (buffer-file-name)))
  335. (expect 3
  336. (length historyf-history))
  337. (expect (concat historyf-test-dir "test4.el")
  338. (cdr historyf-forward-temp))
  339. (desc "forward same mode file history test")
  340. (expect (concat historyf-test-dir "test2.el")
  341. (historyf-forward-same-mode-history)
  342. (expand-file-name (buffer-file-name)))
  343. (expect 3
  344. (length historyf-history))
  345. (expect (concat historyf-test-dir "test4.el")
  346. (cdr historyf-forward-temp))
  347. (expect (concat historyf-test-dir "test4.el")
  348. (historyf-forward-same-mode-history)
  349. (expand-file-name (buffer-file-name)))
  350. (expect 3
  351. (length historyf-history))
  352. (expect nil
  353. (cdr historyf-forward-temp))
  354. (desc "back -> forward test")
  355. (expect (concat historyf-test-dir "test4.el")
  356. (expand-file-name (buffer-file-name)))
  357. (expect (concat historyf-test-dir "test3.c")
  358. (historyf-back)
  359. (expand-file-name (buffer-file-name)))
  360. (expect 3
  361. (find-file (concat historyf-test-dir "test1.el"))
  362. (length historyf-history))
  363. (expect nil
  364. historyf-mark)
  365. (expect nil
  366. historyf-forward-temp)
  367. (expect (concat historyf-test-dir "test1.el")
  368. (historyf-forward)
  369. (expand-file-name (buffer-file-name)))
  370. (expect (concat historyf-test-dir "test3.c")
  371. (historyf-back)
  372. (expand-file-name (buffer-file-name)))
  373. (expect (concat historyf-test-dir "test1.el")
  374. (historyf-forward)
  375. (expand-file-name (buffer-file-name)))
  376. )))
  377. (provide 'historyf)
  378. ;;; historyf.el ends here