;;; eb --- Episode Browser development functions for Emacs ;;; Commentary: ;;; Code: (defgroup eb nil "Episode Browser development package." :prefix "eb-") ;;;###autoload (defun eb-quit-or-bury () "Quit window or bury buffer." (interactive) (if (window-parameter (selected-window) 'quit-restore) (quit-window) (bury-buffer))) ;;;###autoload (defun eb-exhume-buffer () "Switch to last buffer in the buffer list." (interactive) (switch-to-buffer (last-buffer))) (defvar-local eb--list-buffers nil) (defvar-local eb--bookmarks nil) ;;;###autoload (defun eb-list-buffers (&optional arg all) "List project buffers. By default, only file buffers are shown." (interactive "P") (require 'projectile) (if eb--list-buffers (quit-window) (let ((buffer (list-buffers-noselect (not arg) (when (and (not all) (projectile-project-p)) (if arg (projectile-project-buffers) (mapcan (lambda (b) (and (buffer-file-name b) (list b))) (projectile-project-buffers))))))) (display-buffer-in-direction buffer '((direction . up))) (select-window (get-buffer-window buffer)) (with-current-buffer buffer (setq eb--list-buffers t))))) ;;;###autoload (defun eb-list-buffers-all (&optional arg) "List all buffers. By default, only file buffers are shown." (interactive "P") (eb-list-buffers nil t)) (define-advice Buffer-menu-mouse-select (:around (f event) eb-list-buffers) (if eb--list-buffers (progn (select-window (posn-window (event-end event))) (let ((buffer (tabulated-list-get-id (posn-point (event-end event))))) (display-buffer buffer t) (quit-window))) (funcall f event))) ;;;###autoload (defun eb-bookmarks () "Show bookmarks." (interactive) (require 'bookmark) (if eb--bookmarks (quit-window) (bookmark-maybe-load-default-file) (let ((buffer (get-buffer-create bookmark-bmenu-buffer))) (display-buffer-in-direction buffer '((direction . up))) (select-window (get-buffer-window buffer)) (with-current-buffer buffer (bookmark-bmenu-mode) (bookmark-bmenu--revert) (bookmark-bmenu-list) (setq eb--bookmarks t))))) (define-advice bookmark-bmenu-this-window (:around (f) eb-bookmarks) (if eb--bookmarks (progn (let ((window (selected-window))) (bookmark-bmenu-other-window) (quit-window nil window))) (funcall f))) (define-advice bookmark-bmenu-other-window-with-mouse (:around (f event) eb-list-buffers) (funcall f event) (when eb--bookmarks (quit-window nil (posn-window (event-end event))))) ;;;###autoload (defun eb-dired (&optional dir) "Open the root of the current project in `dired'." (interactive) (require 'projectile) (when eb--list-buffers (quit-window)) (setq dir (or dir (projectile-project-root))) (if (and (eq major-mode 'dired-mode) (equal default-directory dir)) (bury-buffer) (dired dir))) ;;;###autoload (defun eb-dired-here () "Open the current working directory in `dired'." (interactive) (eb-dired default-directory)) ;;;###autoload (defun eb-grep () "Grep project." (interactive) (require 'projectile) (if (projectile-project-p) (call-interactively #'projectile-grep) (call-interactively #'grep))) (defcustom eb-system "vs2019" "Build system." :group 'eb :type '(radio (const "mingw") (const "vs2019"))) (defcustom eb-config "Debug" "Build configuration type." :group 'eb :type '(radio (const "Debug") (const "Release"))) (defcustom eb-cwd "b" "Working directory for executable." :group 'eb :type 'directory) ;;;###autoload (defun eb-run () "Launch built executable, displaying its output in a buffer." (interactive) (require 'projectile) (let ((buf (get-buffer-create "*eb-run*")) (exe (concat (projectile-project-root) "/b/" eb-system "/" (if (not (string-equal eb-system "mingw")) (concat eb-config "/") "") "EpisodeBrowser.exe")) (default-directory eb-cwd)) (with-current-buffer buf (compilation-mode)) (start-process "EpisodeBrowser" buf exe) (when (and (eq major-mode 'compilation-mode) (window-parameter (selected-window) 'quit-restore)) (quit-window)) (display-buffer buf))) ;;;###autoload (defun eb-compile () "Compile project without prompt. Use `eb-system'." (interactive) (require 'projectile) (when (and (eq major-mode 'compilation-mode) (window-parameter (selected-window) 'quit-restore)) (quit-window)) (if (projectile-project-p) (let ((compilation-read-command nil) (command (concat "make SYSTEM=" eb-system " CONFIG=" eb-config))) (projectile--run-project-cmd command nil :show-prompt nil :prompt-prefix "Compile command: " :save-buffers t :use-comint-mode projectile-compile-use-comint-mode)) (call-interactively #'compile)) (with-current-buffer "*compilation*" (when (eql (point) (point-min)) (goto-char (point-max))))) ;;;###autoload (defun eb-check () "Toggle `flycheck-list-errors'." (interactive) (require 'flycheck) (catch 'found (dolist (win (window-list)) (with-selected-window win (when (eq major-mode 'flycheck-error-list-mode) (bury-buffer (window-buffer win)) (delete-window win) (throw 'found t)))) (funcall #'flycheck-list-errors))) ;;;###autoload (defun eb-vc () "Open version control for project." (interactive) (require 'projectile) (when eb--list-buffers (quit-window)) (projectile-vc (or (projectile-project-root) default-directory))) ;;;###autoload (defun eb-customize () "Customize group `eb'." (interactive) (customize-group 'eb)) (defvar-local eb-tool-bar-mode--old-map nil) ;;;###autoload (define-minor-mode eb-tool-bar-mode "Episode Browser development tool bar." :lighter " EB" (if eb-tool-bar-mode (progn (setq eb-tool-bar-mode--old-map tool-bar-map) (when (require 'back-button nil t) (back-button-mode 1)) (let ((map (make-sparse-keymap))) ;; Windows, buffers and files. (tool-bar-local-item "cancel" #'eb-quit-or-bury 'quit-or-bury map :label "Bury" :help "Bury buffer or window") (define-key map [(shift quit-or-bury)] #'eb-exhume-buffer) (define-key map [(control quit-or-bury)] #'delete-other-windows) (tool-bar-local-item "index" #'eb-list-buffers 'list-buffers map :label "Buffers" :help "Show project buffers") (define-key map [(shift list-buffers)] #'eb-list-buffers-all) (tool-bar-local-item "diropen" #'eb-dired 'dired map :label "Root" :help "Browse project root") (define-key map [(shift dired)] #'eb-dired-here) (tool-bar-local-item "next-page" #'eb-bookmarks 'bookmarks map :label "Bookmarks" :help "Show bookmarks") (tool-bar-local-item "search-replace" #'eb-grep 'grep map :label "Grep" :help "Grep project") ;; Compilation and version control. (define-key-after map [separator-1] menu-bar-separator) (tool-bar-local-item "newsticker/next-item" #'eb-run 'run map :label "Run" :help "Run executable") (tool-bar-local-item "refresh" #'eb-compile 'compile map :label "Compile" :help "Compile project") (tool-bar-local-item "spell" #'eb-check 'check map :label "Check" :help "Check warnings and errors") (define-key map [(shift check)] #'flycheck-buffer) (define-key map [(control check)] #'flycheck-mode) (tool-bar-local-item "mail/inbox" #'eb-vc 'vc map :label "Version Control" :help "Open project version control") ;; Mark control. (when (require 'back-button nil t) (define-key-after map [separator-2] menu-bar-separator) (tool-bar-local-item "left-arrow" #'back-button-global-backward 'previous-mark map :label "Previous Mark" :help "Go to previous mark") (define-key map [(shift previous-mark)] #'back-button-local-backward) (tool-bar-local-item "mpc/add" #'back-button-push-mark-local-and-global 'push-mark map :label "Push Mark" :help "Push mark") (define-key map [(shift push-mark)] #'back-button-push-mark) (tool-bar-local-item "right-arrow" #'back-button-global-forward 'next-mark map :label "Next Mark" :help "Go to next mark") (define-key map [(shift next-mark)] #'back-button-local-forward)) ;; Miscellaneous. (define-key-after map [separator-3] menu-bar-separator) (tool-bar-local-item "preferences" #'eb-customize 'customize map :label "Customize" :help "Customize user options") (setq-local tool-bar-map map))) (setq-local tool-bar-map eb-tool-bar-mode--old-map) (back-button-mode 0))) ;;;###autoload (define-global-minor-mode global-eb-tool-bar-mode eb-tool-bar-mode (lambda () (eb-tool-bar-mode 1)) :group 'eb) (provide 'eb) ;;; eb.el ends here