sr-speedbar.el 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. ;;; sr-speedbar.el --- Same frame speedbar
  2. ;; Author: Sebastian Rose <sebastian_rose@gmx.de>
  3. ;; Maintainer: Sebastian Rose <sebastian_rose@gmx.de>
  4. ;; Peter Lunicks <plunix@users.sourceforge.net>
  5. ;; Copyright (C) 2008, 2009, Sebastain Rose, all rights reserved.
  6. ;; Copyright (C) 2008, 2009, Andy Stewart, all rights reserved.
  7. ;; Copyright (C) 2009, Peter Lunicks, all rights reversed.
  8. ;; Created: 2008
  9. ;; Version: 0.1.9
  10. ;; Last-Updated: 2013-03-09 20:56:35
  11. ;; URL: http://www.emacswiki.org/emacs/download/sr-speedbar.el
  12. ;; Keywords: speedbar, sr-speedbar.el
  13. ;; Compatibility: GNU Emacs 22 ~ GNU Emacs 24
  14. ;;
  15. ;; Features that might be required by this library:
  16. ;;
  17. ;; `speedbar' `advice' `cl'
  18. ;;
  19. ;;; This file is NOT part of GNU Emacs
  20. ;;; License
  21. ;;
  22. ;; This program is free software; you can redistribute it and/or modify
  23. ;; it under the terms of the GNU General Public License as published by
  24. ;; the Free Software Foundation; either version 3, or (at your option)
  25. ;; any later version.
  26. ;; This program is distributed in the hope that it will be useful,
  27. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  29. ;; GNU General Public License for more details.
  30. ;; You should have received a copy of the GNU General Public License
  31. ;; along with this program; see the file COPYING. If not, write to
  32. ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  33. ;; Floor, Boston, MA 02110-1301, USA.
  34. ;;; Commentary:
  35. ;;
  36. ;; The sr-speedbar.el was created just because I could not believe what I
  37. ;; read on http://www.emacswiki.org/cgi-bin/wiki/Speedbar. They wrote there
  38. ;; that it is not possible to show the speedbar in the same frame. But, as
  39. ;; we all know, ecb had this already. So I started as some kind of joke :)
  40. ;; But when I found it useful and use it all the time.
  41. ;;
  42. ;; Now you type windows key with 's' (`s-s' in Emacs) will show the speedbar
  43. ;; in an extra window, same frame. You can customize the initial width of the
  44. ;; speedbar window further down for console/DOS and X/Win/MacOS separately.
  45. ;;
  46. ;; Below are commands you can use:
  47. ;;
  48. ;; `sr-speedbar-open' Open `sr-speedbar' window.
  49. ;; `sr-speedbar-close' Close `sr-speedbar' window.
  50. ;; `sr-speedbar-toggle' Toggle `sr-speedbar' window.
  51. ;; `sr-speedbar-select-window' Select `sr-speedbar' window.
  52. ;; `sr-speedbar-refresh-turn-on' Turn on refresh speedbar content.
  53. ;; `sr-speedbar-refresh-turn-off' Turn off refresh speedbar content.
  54. ;; `sr-speedbar-refresh-toggle' Toggle refresh speedbar content.
  55. ;;
  56. ;; Enjoy! ;)
  57. ;;
  58. ;;; Installation:
  59. ;;
  60. ;; Copy sr-speedbar.el to your load-path and add to your ~/.emacs
  61. ;;
  62. ;; (require 'sr-speedbar)
  63. ;; (global-set-key (kbd "s-s") 'sr-speedbar-toggle)
  64. ;;
  65. ;; ... or any key binding you like.
  66. ;;
  67. ;;; Customize:
  68. ;;
  69. ;; `sr-speedbar-width-x'
  70. ;; The `sr-speedbar' window width under WINDOW system.
  71. ;; `sr-speedbar-width-console'
  72. ;; The `sr-speedbar' window width under CONSOLE.
  73. ;; `sr-speedbar-max-width'
  74. ;; The max window width allowed remember.
  75. ;; `sr-speedbar-delete-windows'
  76. ;; Whether delete other window before showing up.
  77. ;; `sr-speedbar-skip-other-window-p'
  78. ;; Whether skip `sr-speedbar' window when use
  79. ;; command `other-window' select window in cyclic ordering of windows.
  80. ;; `sr-speedbar-auto-refresh'
  81. ;; Control status of refresh speedbar content.
  82. ;; `sr-speedbar-right-side'
  83. ;; Puts the speedbar on the right side if non-nil (else left).
  84. ;;
  85. ;; All above setup can customize by:
  86. ;; M-x customize-group RET sr-speedbar RET
  87. ;;
  88. ;;; Change log:
  89. ;;
  90. ;; * 09 March 2013:
  91. ;; * Tharre:
  92. ;; * Remove Emacs 21 compatibility code as it fails to compile on Emacs 24.
  93. ;;
  94. ;; * 20 July 2009:
  95. ;; * Peter Lunicks:
  96. ;; * Add new option `sr-speedbar-right-side' to control which
  97. ;; side of the frame the speedbar appears on.
  98. ;;
  99. ;; * 18 Feb 2009:
  100. ;; * Andy Stewart:
  101. ;; * Fix bug between ECB and `sr-speedbar-close'.
  102. ;;
  103. ;; * 29 Jan 2009:
  104. ;; * Andy Stewart:
  105. ;; * Fix doc.
  106. ;;
  107. ;; * 13 Jan 2009:
  108. ;; * Andy Stewart:
  109. ;; * Use `emacs-major-version' instead comment for Emacs 21 compatibility.
  110. ;; * Rewrite advice for `pop-to-buffer' to avoid `pop-to-buffer' not effect
  111. ;; when have many dedicated window in current frame.
  112. ;; * Rewrite advice for `delete-other-windows' to avoid use common variable
  113. ;; `delete-protected-window-list' and use `window-dedicated-p' instead.
  114. ;; Remove variable `delete-protected-window-list' and function
  115. ;; `sr-speedbar-dedicated-match-protected-window-p'.
  116. ;;
  117. ;; * 04 Jan 2009:
  118. ;; * Andy Stewart:
  119. ;; * Add new option `sr-speedbar-auto-refresh' control refresh content.
  120. ;; * Add new functions:
  121. ;; `sr-speedbar-refresh-turn-on',
  122. ;; `sr-speedbar-refresh-turn-off',
  123. ;; `sr-speedbar-refresh-toggle'.
  124. ;; * Fix doc.
  125. ;;
  126. ;; * 30 Dec 2008:
  127. ;; * Andy Stewart:
  128. ;; * Rewrite advice for `delete-other-windows' for fix the bug
  129. ;; with window configuration save and revert.
  130. ;; * Rewrite advice for `delete-window', now just remember window
  131. ;; width before deleted, and can use `delete-window' do same effect
  132. ;; as command `sr-speedbar-close'.
  133. ;; * Add new option `sr-speedbar-max-width'.
  134. ;; Remember window width before hide, except larger than value of
  135. ;; `sr-speedbar-max-width'.
  136. ;; * Add new variable `delete-protected-window-list', for protected
  137. ;; special window don't deleted.
  138. ;; This variable is common for any extension that use dedicated
  139. ;; window.
  140. ;; * Fix doc.
  141. ;;
  142. ;; * 29 Dec 2008:
  143. ;; * Andy Stewart:
  144. ;; * Pick-up and refactory code that use `buffer-live-p' or `window-live-p',
  145. ;; and replace with `sr-speedbar-buffer-exist-p' and
  146. ;; `sr-speedbar-window-exist-p'.
  147. ;; * Rename some function with prefix `sr-speedbar-' to avoid
  148. ;; conflict with other functions.
  149. ;; * Pick-up the code that handle advice for `other-window',
  150. ;; and replace with function `sr-speedbar-handle-other-window-advice'.
  151. ;; * Clean up code, make more clear.
  152. ;;
  153. ;; * 21 Dec 2008:
  154. ;; * Andy Stewart:
  155. ;; * Fix the bug `sr-speedbar-open' and `sr-speedbar-close'.
  156. ;; * Fix doc.
  157. ;;
  158. ;; * 20 Dec 2008
  159. ;; * Andy Stewart:
  160. ;; * Fix `ad-advised-definition-p' error.
  161. ;; * Fix doc.
  162. ;;
  163. ;; * 17 Dec 2008
  164. ;; * Andy Stewart:
  165. ;; * Add new option `sr-speedbar-skip-other-window-p' and new advice
  166. ;; for `other-window', make user skip select `sr-speedbar' window
  167. ;; when use command `other-window'.
  168. ;; * Fix the name of advice, make more clear.
  169. ;; * Fix the bug `sr-speedbar-select-window' when no live window exist.
  170. ;; * Fix doc.
  171. ;;
  172. ;; * 16 Dec 2008:
  173. ;; * Andy Stewart:
  174. ;; * Fix the bug of `sr-speedbar-refresh', use `default-directory'
  175. ;; get refresh directory instead through function in `dired'.
  176. ;; * Fix `window-live-p' bug, check window valid value before use
  177. ;; `window-live-p' test `sr-speedbar-window'.
  178. ;; * Fix `buffer-live-p' bug, check buffer valid value before use
  179. ;; `buffer-live-p' test `speedbar-buffer'.
  180. ;; * Add advice `pop-to-buffer' to make function `display-buffer'
  181. ;; can pop-up window when just have two windows (one is `sr-speedbar'
  182. ;; window) in current frame.
  183. ;; * Add group `sr-speedbar'.
  184. ;; More better customize interface through `customize-group'.
  185. ;;
  186. ;; * 28 Sep 2008:
  187. ;; * Andy Stewart:
  188. ;; * Fix a bug, when `sr-speedbar-toggle' many times, window width
  189. ;; will increment automatically.
  190. ;; * Use around advices replace, make code simple.
  191. ;; * Use `sr-speedbar-open' replace `sr-speedbar-no-separate-frame'.
  192. ;; * Clean up code.
  193. ;;
  194. ;; * 28 Sep 2008:
  195. ;; * Sebastian:
  196. ;; * set `sr-speedbar-delete-windows' to nil to avoid
  197. ;; the removal of other windows.
  198. ;;
  199. ;; * 26 Jun 2008:
  200. ;; * Sebastain:
  201. ;; * Added Andy Stewart's patch to refresh the speedbar's contents.
  202. ;; Thanks for this one!
  203. ;;
  204. ;; * Init:
  205. ;; * Sebastian:
  206. ;; * Added some lines to get it working:
  207. ;; * splitting the window and remember it,
  208. ;; * changing the way speedbar finds a file.
  209. ;; * File view of speedbar is now working all right.
  210. ;; * C-x 1 in other window deletes speedbar-window, just calling
  211. ;; M-x sr-speedbar-no-separate-frame again is fine now.
  212. ;; * Toggle speedbar works, width is save when toggling.
  213. ;; * Recalc speedbar width if window-width - speedbar-width <= 0
  214. ;; * Speedbar window is now dedicated to speedbar-buffer.
  215. ;;
  216. ;;; Acknowledgements:
  217. ;;
  218. ;; All emacsers ... :)
  219. ;;
  220. ;;; Bug
  221. ;;
  222. ;;
  223. ;;; TODO
  224. ;;
  225. ;;
  226. ;;
  227. ;;; Require
  228. (require 'speedbar)
  229. (require 'advice)
  230. (require 'cl)
  231. ;;; Code:
  232. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; User Customization ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  233. (defgroup sr-speedbar nil
  234. "Same frame speedbar."
  235. :group 'speedbar)
  236. (defcustom sr-speedbar-width-x 24
  237. "Initial width of `sr-speedbar-window' under window system."
  238. :type 'integer
  239. :group 'sr-speedbar)
  240. (defcustom sr-speedbar-width-console 24
  241. "Initial width of `sr-speedbar-window' on console."
  242. :type 'integer
  243. :group 'sr-speedbar)
  244. (defcustom sr-speedbar-max-width 50
  245. "The max width limit that window allowed.
  246. Default, if hide `sr-speedbar' window will remember
  247. window width, except the window width larger than
  248. this value."
  249. :type 'integer
  250. :group 'sr-speedbar)
  251. (defcustom sr-speedbar-auto-refresh t
  252. "Automatically refresh speedbar content when changed directory.
  253. Default is t."
  254. :type 'boolean
  255. :set (lambda (symbol value)
  256. (set symbol value))
  257. :group 'sr-speedbar)
  258. (defcustom sr-speedbar-right-side t
  259. "Show the speedbar to the right side of the current window.
  260. If nil, the speedbar will appear on the left.
  261. Default is t."
  262. :type 'boolean
  263. :set (lambda (symbol value)
  264. (set symbol value))
  265. :group 'sr-speedbar)
  266. (defcustom sr-speedbar-delete-windows nil
  267. "Allow the speedbar to delete other windows before showing up.
  268. If nil, speedbar will not touch your window configuration.
  269. Otherwise `delete-other-windows' will be called before showing
  270. the speedbar.
  271. Default is nil."
  272. :type 'boolean
  273. :group 'sr-speedbar)
  274. (defcustom sr-speedbar-skip-other-window-p nil
  275. "Whether skip `sr-speedbar' window with `other-window'.
  276. Default, can use `other-window' select window in cyclic
  277. ordering of windows. But sometimes we don't want select
  278. `sr-speedbar' window use `other-window'.
  279. Just want make `sr-speedbar' window as a view sidebar.
  280. So please turn on this option if you want skip
  281. `sr-speedbar' window with `other-window'.
  282. Default is nil."
  283. :type 'boolean
  284. :set (lambda (symbol value)
  285. (set symbol value)
  286. (when (ad-advised-definition-p 'other-window)
  287. (sr-speedbar-handle-other-window-advice value)))
  288. :group 'sr-speedbar)
  289. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Constant ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  290. (defconst sr-speedbar-version "0.1.4"
  291. "Current version.")
  292. (defconst sr-speedbar-buffer-name "*SPEEDBAR*"
  293. "The buffer name of sr-speedbar.")
  294. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  295. (defvar sr-speedbar-width nil
  296. "Initial width of speedbar-window.")
  297. (defvar sr-speedbar-window nil
  298. "Speedbar window.")
  299. (defvar sr-speedbar-last-refresh-dictionary nil
  300. "The last refresh dictionary record of 'sr-speedbar-refresh'.")
  301. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Interactive functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  302. ;;;###autoload
  303. (defun sr-speedbar-toggle ()
  304. "Toggle sr-speedbar window.
  305. Toggle visibility of sr-speedbar by resizing
  306. the `sr-speedbar-window' to a minimal width
  307. or the last width when visible.
  308. Use this function to create or toggle visibility
  309. of a speedbar-window. It will be created if necessary."
  310. (interactive)
  311. (if (sr-speedbar-exist-p)
  312. (sr-speedbar-close)
  313. (sr-speedbar-open)))
  314. ;;;###autoload
  315. (defun sr-speedbar-open ()
  316. "Create `sr-speedbar' window."
  317. (interactive)
  318. (if (not (sr-speedbar-exist-p))
  319. (let ((current-window (selected-window)))
  320. ;; Ensure only one window is there
  321. ;; when `sr-speedbar-delete-windows' is non-nil
  322. (if sr-speedbar-delete-windows
  323. (delete-other-windows))
  324. ;; Whether activate `other-window' advice
  325. ;; to skip `sr-speedbar' window when use `other-window'.
  326. (sr-speedbar-handle-other-window-advice sr-speedbar-skip-other-window-p)
  327. ;; Switch buffer
  328. (if (sr-speedbar-buffer-exist-p speedbar-buffer)
  329. (unless (sr-speedbar-window-exist-p sr-speedbar-window) ;if `sr-speedbar' window is not exist
  330. (sr-speedbar-get-window))
  331. (if (<= (sr-speedbar-current-window-take-width) sr-speedbar-width) ;if current window width is narrower than `sr-speedbar-width'
  332. (sr-speedbar-recalculate-width)) ;recalculate width of `sr-speedbar'
  333. (sr-speedbar-get-window) ;get `sr-speedbar' window that split current window
  334. (setq speedbar-buffer (get-buffer-create sr-speedbar-buffer-name)
  335. speedbar-frame (selected-frame)
  336. dframe-attached-frame (selected-frame)
  337. speedbar-select-frame-method 'attached
  338. speedbar-verbosity-level 0 ;don't say anything, i don't like ... :)
  339. speedbar-last-selected-file nil)
  340. (set-buffer speedbar-buffer)
  341. (buffer-disable-undo speedbar-buffer) ;make disable in speedbar buffer, otherwise will occur `undo-outer-limit' error
  342. (speedbar-mode)
  343. (speedbar-reconfigure-keymaps)
  344. (speedbar-update-contents)
  345. (speedbar-set-timer 1)
  346. ;; Add speedbar hook.
  347. (add-hook 'speedbar-before-visiting-file-hook 'sr-speedbar-before-visiting-file-hook t)
  348. (add-hook 'speedbar-before-visiting-tag-hook 'sr-speedbar-before-visiting-tag-hook t)
  349. (add-hook 'speedbar-visiting-file-hook 'sr-speedbar-visiting-file-hook t)
  350. (add-hook 'speedbar-visiting-tag-hook 'sr-speedbar-visiting-tag-hook t)
  351. ;; Add `kill-buffer-hook'.
  352. (add-hook 'kill-buffer-hook 'sr-speedbar-kill-buffer-hook) ;add `kill-buffer-hook'
  353. ;; Auto refresh speedbar content
  354. ;; if option `sr-speedbar-auto-refresh' is non-nil
  355. (sr-speedbar-handle-auto-refresh sr-speedbar-auto-refresh))
  356. (set-window-buffer sr-speedbar-window (get-buffer sr-speedbar-buffer-name))
  357. (set-window-dedicated-p sr-speedbar-window t) ;make `sr-speedbar-window' dedicated to speedbar-buffer.
  358. (select-window current-window))
  359. (message "`sr-speedbar' window has exist.")))
  360. (defun sr-speedbar-close ()
  361. "Close `sr-speedbar' window and save window width."
  362. (interactive)
  363. (if (sr-speedbar-exist-p)
  364. (let ((current-window (selected-window)))
  365. ;; Remember window width.
  366. (sr-speedbar-select-window)
  367. (sr-speedbar-remember-window-width)
  368. ;; Close window.
  369. (if (and (require 'ecb nil t)
  370. ecb-activated-window-configuration)
  371. ;; Toggle ECB window when ECB window activated.
  372. (progn
  373. (ecb-deactivate)
  374. (ecb-activate))
  375. ;; Otherwise delete dedicated window.
  376. (delete-window sr-speedbar-window)
  377. (if (sr-speedbar-window-exist-p current-window)
  378. (select-window current-window))))
  379. (message "`sr-speedbar' window is not exist.")))
  380. (defun sr-speedbar-select-window ()
  381. "Force the windows that contain `sr-speedbar'."
  382. (interactive)
  383. (if (sr-speedbar-exist-p)
  384. (select-window sr-speedbar-window)
  385. (message "`sr-speedbar' window is not exist.")))
  386. (defun sr-speedbar-refresh-turn-on ()
  387. "Turn on refresh content automatically."
  388. (interactive)
  389. (setq sr-speedbar-auto-refresh t)
  390. (sr-speedbar-handle-auto-refresh sr-speedbar-auto-refresh t))
  391. (defun sr-speedbar-refresh-turn-off ()
  392. "Turn off refresh content automatically."
  393. (interactive)
  394. (setq sr-speedbar-auto-refresh nil)
  395. (sr-speedbar-handle-auto-refresh sr-speedbar-auto-refresh t))
  396. (defun sr-speedbar-refresh-toggle ()
  397. "Toggle refresh content status."
  398. (interactive)
  399. (setq sr-speedbar-auto-refresh (not sr-speedbar-auto-refresh))
  400. (sr-speedbar-handle-auto-refresh sr-speedbar-auto-refresh t))
  401. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; utilise functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  402. (defun sr-speedbar-exist-p ()
  403. "Return `non-nil' if `sr-speedbar' is exist.
  404. Otherwise return nil."
  405. (and (sr-speedbar-buffer-exist-p speedbar-buffer)
  406. (sr-speedbar-window-exist-p sr-speedbar-window)))
  407. (defun sr-speedbar-window-p ()
  408. "Return `non-nil' if current window is `sr-speedbar' window.
  409. Otherwise return nil."
  410. (equal sr-speedbar-buffer-name (buffer-name (window-buffer))))
  411. (defun sr-speedbar-remember-window-width ()
  412. "Remember window width."
  413. (let ((win-width (sr-speedbar-current-window-take-width)))
  414. (if (and (sr-speedbar-window-p)
  415. (> win-width 1)
  416. (<= win-width sr-speedbar-max-width))
  417. (setq sr-speedbar-width win-width))))
  418. (defun sr-speedbar-recalculate-width ()
  419. "Calculate the speedbar width with respect of window system."
  420. (if (and window-system
  421. (not (string= "pc" window-system)))
  422. (setq sr-speedbar-width sr-speedbar-width-x)
  423. (setq sr-speedbar-width sr-speedbar-width-console)))
  424. (or sr-speedbar-width (sr-speedbar-recalculate-width)) ;initialization `sr-speedbar-width'
  425. (defun sr-speedbar-get-window ()
  426. "Get `sr-speedbar' window."
  427. (let ((current-window (selected-window))
  428. ;; Get split new window.
  429. (new-window (split-window
  430. (selected-window)
  431. (if sr-speedbar-right-side
  432. (- (sr-speedbar-current-window-take-width) sr-speedbar-width)
  433. sr-speedbar-width)
  434. t)))
  435. ;; Select split window.
  436. (setq sr-speedbar-window
  437. (if sr-speedbar-right-side
  438. ;; Select right window when `sr-speedbar-right-side' is enable.
  439. new-window
  440. ;; Otherwise select left widnow.
  441. current-window))))
  442. (defun sr-speedbar-before-visiting-file-hook ()
  443. "Function that hook `speedbar-before-visiting-file-hook'."
  444. (select-window (previous-window)))
  445. (defun sr-speedbar-before-visiting-tag-hook ()
  446. "Function that hook `speedbar-before-visiting-tag-hook'."
  447. (select-window (previous-window)))
  448. (defun sr-speedbar-visiting-file-hook ()
  449. "Function that hook `speedbar-visiting-file-hook'."
  450. (select-window (previous-window)))
  451. (defun sr-speedbar-visiting-tag-hook ()
  452. "Function that hook `speedbar-visiting-tag-hook'."
  453. (select-window (previous-window)))
  454. (defun sr-speedbar-kill-buffer-hook ()
  455. "Function that hook `kill-buffer-hook'."
  456. (when (eq (current-buffer) speedbar-buffer)
  457. (setq speedbar-frame nil
  458. dframe-attached-frame nil
  459. speedbar-buffer nil)
  460. (speedbar-set-timer nil)
  461. (remove-hook 'speedbar-before-visiting-file-hook 'sr-speedbar-before-visiting-file-hook)
  462. (remove-hook 'speedbar-before-visiting-tag-hook 'sr-speedbar-before-visiting-tag-hook)
  463. (remove-hook 'speedbar-visiting-file-hook 'sr-speedbar-visiting-file-hook)
  464. (remove-hook 'speedbar-visiting-tag-hook 'sr-speedbar-visiting-tag-hook)))
  465. (defun sr-speedbar-refresh ()
  466. "Refresh the context of speedbar."
  467. (when (and (not (equal default-directory sr-speedbar-last-refresh-dictionary)) ;if directory is change
  468. (not (sr-speedbar-window-p))) ;and is not in speedbar buffer
  469. (setq sr-speedbar-last-refresh-dictionary default-directory)
  470. (speedbar-refresh)))
  471. (defun sr-speedbar-handle-auto-refresh (activate &optional echo-show)
  472. "Automatically refresh speedbar content when changed directory.
  473. Do nothing if option ACTIVATE is nil.
  474. Will display message if ECHO-SHOW is non-nil."
  475. (if activate
  476. (progn
  477. (add-hook 'speedbar-timer-hook 'sr-speedbar-refresh)
  478. (if echo-show (message "Turn on speedbar content refresh automatically.")))
  479. (remove-hook 'speedbar-timer-hook 'sr-speedbar-refresh)
  480. (if echo-show (message "Turn off speedbar content refresh automatically."))))
  481. (defun sr-speedbar-current-window-take-width (&optional window)
  482. "Return the width that WINDOW take up.
  483. If WINDOW is nil, get current window."
  484. (let ((edges (window-edges window)))
  485. (- (nth 2 edges) (nth 0 edges))))
  486. (defun sr-speedbar-window-dedicated-only-one-p ()
  487. "Only have one non-dedicated window."
  488. (interactive)
  489. (let ((window-number 0)
  490. (dedicated-window-number 0))
  491. (walk-windows
  492. (lambda (w)
  493. (with-selected-window w
  494. (incf window-number)
  495. (if (window-dedicated-p w)
  496. (incf dedicated-window-number)))))
  497. (if (and (> dedicated-window-number 0)
  498. (= (- window-number dedicated-window-number) 1))
  499. t nil)))
  500. (defun sr-speedbar-window-exist-p (window)
  501. "Return `non-nil' if WINDOW is exist.
  502. Otherwise return nil."
  503. (and window (window-live-p window)))
  504. (defun sr-speedbar-buffer-exist-p (buffer)
  505. "Return `non-nil' if BUFFER is exist.
  506. Otherwise return nil."
  507. (and buffer (buffer-live-p buffer)))
  508. (defun sr-speedbar-handle-other-window-advice (activate)
  509. "Handle advice for function `other-window'.
  510. If ACTIVATE is `non-nil' enable advice `sr-speedbar-other-window-advice'.
  511. Otherwise disable it."
  512. (if activate
  513. (ad-enable-advice 'other-window 'after 'sr-speedbar-other-window-advice)
  514. (ad-disable-advice 'other-window 'after 'sr-speedbar-other-window-advice))
  515. (ad-activate 'other-window))
  516. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Advices ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  517. (defadvice delete-other-windows (around sr-speedbar-delete-other-window-advice activate)
  518. "This advice to make `sr-speedbar' window can't deleted by command `delete-other-windows'."
  519. (let ((sr-speedbar-active-p (sr-speedbar-window-exist-p sr-speedbar-window)))
  520. (if sr-speedbar-active-p
  521. (let ((current-window (selected-window)))
  522. (dolist (win (window-list))
  523. (when (and (window-live-p win)
  524. (not (eq current-window win))
  525. (not (window-dedicated-p win)))
  526. (delete-window win))))
  527. ad-do-it)))
  528. (defadvice delete-window (before sr-speedbar-delete-window-advice activate)
  529. "This advice to remember `sr-speedbar' window width before deleted.
  530. Use `delete-window' delete `sr-speedbar' window have same effect as `sr-speedbar-close'."
  531. ;; Remember window width before deleted.
  532. (sr-speedbar-remember-window-width))
  533. (defadvice pop-to-buffer (before sr-speedbar-pop-to-buffer-advice activate)
  534. "This advice is to fix `pop-to-buffer' problem with dedicated window.
  535. Default, function `display-buffer' can't display buffer in select window
  536. if current window is `dedicated'.
  537. So function `display-buffer' conflict with `sr-speedbar' window, because
  538. `sr-speedbar' window is `dedicated' window.
  539. That is to say, when current frame just have one `non-dedicated' window,
  540. any functions that use `display-buffer' can't split windows
  541. to display buffer, even option `pop-up-windows' is enable.
  542. And the example function that can occur above problem is `pop-to-buffer'."
  543. (when (and pop-up-windows ;`pop-up-windows' is enable
  544. (sr-speedbar-window-dedicated-only-one-p) ;just have one `non-dedicated' window
  545. (sr-speedbar-window-exist-p sr-speedbar-window)
  546. (not (sr-speedbar-window-p))) ;not in `sr-speedbar' window
  547. (split-window-vertically)
  548. (windmove-down)))
  549. (defadvice other-window (after sr-speedbar-other-window-advice)
  550. "Default, can use `other-window' select window in cyclic ordering of windows.
  551. But sometimes we don't want select `sr-speedbar' window use `other-window'.
  552. Just want make `sr-speedbar' window as a view sidebar.
  553. This advice can make `other-window' skip `sr-speedbar' window."
  554. (let ((count (or (ad-get-arg 0) 1)))
  555. (when (and (sr-speedbar-window-exist-p sr-speedbar-window)
  556. (eq sr-speedbar-window (selected-window)))
  557. (other-window count))))
  558. (provide 'sr-speedbar)
  559. ;;; sr-speedbar.el ends here
  560. ;;; LocalWords: sr Sebastain ecb Sep speedbar's Recalc dframe keymaps pc
  561. ;;; LocalWords: decicated uncomment