buffer-sets.el 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. ;;; buffer-sets.el --- Sets of Buffers for Buffer Management
  2. ;; Copyright (C) 2016 Samuel Flint
  3. ;; Author: Samuel W. Flint <swflint@flintfam.org>
  4. ;; Version: 2.0
  5. ;; Package-Requires: ((cl-lib "0.5"))
  6. ;; Keywords: buffer-management
  7. ;; URL: http://github.com/swflint/buffer-sets
  8. ;;; Commentary:
  9. ;;
  10. ;;; Code:
  11. (require 'cl-lib)
  12. (cl-defstruct buffer-set
  13. name
  14. files
  15. select
  16. on-apply
  17. on-apply-source
  18. on-remove
  19. on-remove-source)
  20. (defvar *buffer-sets* nil
  21. "List of all defined buffer sets.")
  22. (defvar *buffer-sets-applied* nil
  23. "List of applied buffer-sets.")
  24. (defvar *buffer-set-definitions* nil
  25. "List of all buffer set definitions.")
  26. (defvar *buffer-set-buffers* nil
  27. "List of buffers in loaded buffer sets.")
  28. (defcustom buffer-set-file "~/.emacs.d/buffer-set-definitions.el"
  29. "The file to store buffer set definitions in."
  30. :type 'file :group 'editing)
  31. (defun buffer-sets-load-definitions-file ()
  32. "Load buffer set definitions file."
  33. (load buffer-set-file t t)
  34. (message "Loaded Buffer Set Definitions."))
  35. (defun buffer-sets-applied-p (set)
  36. "Returns true if SET is applied."
  37. (member set *buffer-sets-applied*))
  38. (defun buffer-set--get-buffer-set-definition (set-name)
  39. (car (cl-remove-if-not (lambda (set)
  40. (eq set-name (buffer-set-name set))) *buffer-set-definitions*)))
  41. (defun buffer-set--generate-buffers-list (set-name)
  42. (intern (format "*buffer-set-%s--buffers*" set-name)))
  43. (cl-defmacro define-buffer-set (name &key files select on-apply on-remove)
  44. "Define a buffer set named NAME, taking FILES, RUN-ON-APPLY, RUN-ON-REMOVE and BUFFER-TO-SELECT as keyword arguments."
  45. `(progn
  46. (cl-pushnew ',name *buffer-sets*)
  47. (cl-pushnew (make-buffer-set :name ',name
  48. :files ',files
  49. :select ,select
  50. :on-apply-source ',on-apply
  51. :on-remove-source ',on-remove
  52. :on-apply (lambda () ,@on-apply)
  53. :on-remove (lambda () ,@on-remove))
  54. *buffer-set-definitions*
  55. :key #'buffer-set-name)
  56. (defvar ,(buffer-set--generate-buffers-list name) nil)
  57. ',name))
  58. (defun buffer-sets-load-set (name)
  59. (interactive (list (intern (completing-read "Set Name: "
  60. (cl-remove-if #'(lambda (set) (member set *buffer-sets-applied*)) *buffer-sets*)
  61. nil t))))
  62. (let ((set-definition (buffer-set--get-buffer-set-definition name)))
  63. (if (not (buffer-set-p set-definition))
  64. (error "Set Undefined: %s" name)
  65. (let ((files (buffer-set-files set-definition))
  66. (select (buffer-set-select set-definition))
  67. (on-apply (buffer-set-on-apply set-definition))
  68. (buffers-list (buffer-set--generate-buffers-list name)))
  69. (setf (symbol-value buffers-list) (mapcar #'find-file files))
  70. (funcall on-apply)
  71. (when (stringp select)
  72. (switch-to-buffer select))
  73. (add-to-list '*buffer-sets-applied* name)
  74. (message "Applied buffer set %s." name)))))
  75. (defalias 'load-buffer-set 'buffer-sets-load-set)
  76. (defun buffer-sets-unload-buffer-set (name)
  77. "Unload Buffer Set named NAME."
  78. (interactive (list (intern (completing-read "Buffer Set Name: " *buffer-sets-applied*))))
  79. (let ((set-definition (buffer-set--get-buffer-set-definition name)))
  80. (if (not (buffer-set-p set-definition))
  81. (error "Set Undefined: %s" name)
  82. (let ((buffers-list (buffer-set--generate-buffers-list name))
  83. (on-remove (buffer-set-on-remove set-definition)))
  84. (mapc (lambda (buffer)
  85. (when (buffer-live-p buffer)
  86. (with-current-buffer buffer
  87. (save-buffer)
  88. (kill-buffer buffer))))
  89. (symbol-value buffers-list))
  90. (funcall on-remove)
  91. (setf (symbol-value buffers-list) nil)
  92. (setq *buffer-sets-applied* (delq name *buffer-sets-applied*))
  93. (message "Removed Buffer Set: %s" name)))))
  94. (defun buffer-sets-list ()
  95. "Produce a list of defined buffer sets."
  96. (interactive)
  97. (when (buffer-live-p "*Buffer Sets*")
  98. (kill-buffer "*Buffer Sets*"))
  99. (with-help-window "*Buffer Sets*"
  100. (with-current-buffer "*Buffer Sets*"
  101. (insert "Defined Buffer Sets:\n\n")
  102. (dolist (set *buffer-sets*)
  103. (if (not (buffer-sets-applied-p set))
  104. (insert (format " - %s\n" set))
  105. (insert (format " - %s (Applied)\n" set)))
  106. (dolist (buffer (symbol-value (buffer-set--generate-buffers-list set)))
  107. (if (null (get-buffer-window-list buffer nil t))
  108. (insert (format " - %s\n" (buffer-name buffer)))
  109. (insert (format " - %s (visible)\n" (buffer-name buffer)))))))))
  110. (defun buffer-sets-unload-all-buffer-sets ()
  111. "Unload all loaded buffer sets."
  112. (interactive)
  113. (dolist (buffer-set *buffer-sets-applied*)
  114. (buffer-sets-unload-buffer-set buffer-set)))
  115. (defun buffer-sets-create-set (name)
  116. "Create a new set."
  117. (interactive "SNew Set Name: ")
  118. (when (not (member name *buffer-sets*))
  119. (cl-pushnew name *buffer-sets*)
  120. (setf (symbol-value (buffer-set--generate-buffers-list name)) nil)
  121. (cl-pushnew (make-buffer-set :name name
  122. :on-apply (lambda () nil)
  123. :on-remove (lambda () nil)) *buffer-set-definitions*)))
  124. (defun buffer-sets-add-file-to-set (name file)
  125. "Add a file to the set."
  126. (interactive (list
  127. (intern (completing-read "Set: " *buffer-sets* nil t))
  128. (read-file-name "File Name: ")))
  129. (let ((set (buffer-set--get-buffer-set-definition name)))
  130. (setf (buffer-set-files set) (append (buffer-set-files set) (list file)))))
  131. (defun buffer-sets-add-directory-to-set (name directory)
  132. (interactive (list
  133. (intern (completing-read "Set: " *buffer-sets* nil t))
  134. (read-directory-name "Directory: ")))
  135. (let ((set (buffer-set--get-buffer-set-definition name)))
  136. (setf (buffer-set-files set) (append (buffer-set-files set) (list directory)))))
  137. (defun buffer-sets-add-buffer-to-set (name buffer)
  138. "Add a buffer to the given set."
  139. (interactive (list
  140. (intern (completing-read "Set: " *buffer-sets* nil t))
  141. (get-buffer (read-buffer "Buffer: " (current-buffer)))))
  142. (let ((set (buffer-set--get-buffer-set-definition name))
  143. (file (buffer-file-name buffer)))
  144. (setf (buffer-set-files set) (append (buffer-set-files set) (list file)))))
  145. ;; (defun buffer-sets-edit-load-actions (set)
  146. ;; "Edit the actions to be preformed on buffer set load."
  147. ;; (interactive (list (completing-read "Set: " *buffer-sets* nil t))))
  148. ;; (defun buffer-sets-edit-remove-actions (set)
  149. ;; "Edit the actions to be preformed on buffer set removal."
  150. ;; (interactive (list (completing-read "Set: " *buffer-sets* nil t))))
  151. (defun buffer-sets-set-buffer-to-select (set)
  152. "Set the buffer to automatically select."
  153. (interactive (list (intern (completing-read "Set: " *buffer-sets* nil t))))
  154. (let* ((set (buffer-set--get-buffer-set-definition set))
  155. (files (buffer-set-files set)))
  156. (setf (buffer-set-select set)
  157. (completing-read "File: " files nil t))))
  158. (defun buffer-sets-remove-file (set)
  159. (interactive (list (intern (completing-read "Set: " *buffer-sets* nil t))))
  160. (let ((set (buffer-set--get-buffer-set-definition set)))
  161. (setf (buffer-set-files set)
  162. (delq (completing-read "File: " (buffer-set-files set) nil t)
  163. (buffer-set-files set)))))
  164. (defun buffer-sets-save (the-set)
  165. "Save defined buffer sets."
  166. (interactive)
  167. (insert (format "%S\n\n" (let ((name (buffer-set-name the-set))
  168. (files (buffer-set-files the-set))
  169. (select (buffer-set-select the-set))
  170. (on-apply (buffer-set-on-apply-source the-set))
  171. (on-remove (buffer-set-on-remove-source the-set)))
  172. `(define-buffer-set ,name
  173. :files ,files
  174. :select ,select
  175. :on-apply ,on-apply
  176. :on-remove ,on-remove)))))
  177. (defun buffer-sets-save-definitions ()
  178. (with-current-buffer (find-file buffer-set-file)
  179. (kill-region (buffer-end -1) (buffer-end 1))
  180. (mapc #'buffer-sets-save (reverse *buffer-set-definitions*))
  181. (save-buffer)
  182. (kill-buffer))
  183. (message "Saved Buffer Set Definitions."))
  184. (defvar buffer-sets-map (make-keymap)
  185. "Keymap for buffer-set commands.")
  186. (define-key buffer-sets-map (kbd "l") #'buffer-sets-load-set)
  187. (define-key buffer-sets-map (kbd "L") #'buffer-sets-list)
  188. (define-key buffer-sets-map (kbd "u") #'buffer-sets-unload-buffer-set)
  189. (define-key buffer-sets-map (kbd "U") #'buffer-sets-unload-all-buffer-sets)
  190. (define-key buffer-sets-map (kbd "c") #'buffer-sets-create-set)
  191. (define-key buffer-sets-map (kbd "f") #'buffer-sets-add-file-to-set)
  192. (define-key buffer-sets-map (kbd "b") #'buffer-sets-add-buffer-to-set)
  193. (define-key buffer-sets-map (kbd "d") #'buffer-sets-add-directory-to-set)
  194. (define-key buffer-sets-map (kbd "R") #'buffer-sets-remove-file)
  195. (define-key buffer-sets-map (kbd "s") #'buffer-sets-set-buffer-to-select)
  196. ;; (define-key buffer-sets-map (kbd "a") #'buffer-sets-edit-load-actions)
  197. ;; (define-key buffer-sets-map (kbd "r") #'buffer-sets-edit-remove-actions)
  198. (define-minor-mode buffer-sets-mode
  199. "A mode for managing sets of buffers."
  200. :lighter " BSM" :global t :variable buffer-sets-mode-p
  201. (if buffer-sets-mode-p
  202. (progn
  203. (buffer-sets-load-definitions-file)
  204. (define-key ctl-x-map (kbd "L") buffer-sets-map)
  205. (add-hook 'kill-emacs-hook #'buffer-sets-unload-all-buffer-sets)
  206. (add-hook 'kill-emacs-hook #'buffer-sets-save-definitions))
  207. (progn
  208. (buffer-sets-save-definitions)
  209. (define-key ctl-x-map (kbd "L") nil)
  210. (remove-hook 'kill-emacs-hook #'buffer-sets-unload-all-buffer-sets)
  211. (remove-hook 'kill-emacs-hook #'buffer-sets-save-definitions))))
  212. (provide 'buffer-sets)
  213. ;;; buffer-sets.el ends here