Support vterm-mgt.el
I enjoyed using term-switcher so much that I ended up adopting vterm as my primary terminal. After reaching for vterm as often as I did, I realized that I would enjoy supporting cycling through instances, creating new instances, deleting existing instances, renaming instances. Thus spawned vterm-mgt.el. I'm particularly excited about the KBD to toggle between vterm instances and source code buffers.
This commit is contained in:
		
							parent
							
								
									8584059e7c
								
							
						
					
					
						commit
						2af05f698c
					
				
					 4 changed files with 146 additions and 5 deletions
				
			
		| 
						 | 
					@ -15,9 +15,10 @@
 | 
				
			||||||
(require 'chrome)
 | 
					(require 'chrome)
 | 
				
			||||||
(require 'scrot)
 | 
					(require 'scrot)
 | 
				
			||||||
(require 'ivy-clipmenu)
 | 
					(require 'ivy-clipmenu)
 | 
				
			||||||
(require 'term-switcher)
 | 
					 | 
				
			||||||
(require 'general)
 | 
					(require 'general)
 | 
				
			||||||
(require 'window-manager)
 | 
					(require 'window-manager)
 | 
				
			||||||
 | 
					(require 'vterm-mgt)
 | 
				
			||||||
 | 
					(require 'buffer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
					;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
				
			||||||
;; Configuration
 | 
					;; Configuration
 | 
				
			||||||
| 
						 | 
					@ -43,7 +44,27 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(keybinding/exwm "<C-M-tab>" #'exwm/switch-to-exwm-buffer)
 | 
					(keybinding/exwm "<C-M-tab>" #'exwm/switch-to-exwm-buffer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(general-define-key (kbd/raw 'x11 "t") #'ts/switch-to-terminal)
 | 
					;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
				
			||||||
 | 
					;; Vterm
 | 
				
			||||||
 | 
					;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;; Show or hide a vterm buffer.  I'm intentionally not defining this in
 | 
				
			||||||
 | 
					;; vterm-mgt.el because it consumes `buffer/show-previous', and I'd like to
 | 
				
			||||||
 | 
					;; avoid bloating vterm-mgt.el with dependencies that others may not want.
 | 
				
			||||||
 | 
					(general-define-key (kbd/raw 'x11 "t")
 | 
				
			||||||
 | 
					                    (lambda ()
 | 
				
			||||||
 | 
					                      (interactive)
 | 
				
			||||||
 | 
					                      (if (vterm-mgt--instance? (current-buffer))
 | 
				
			||||||
 | 
					                          (switch-to-buffer (first (buffer/source-code-buffers)))
 | 
				
			||||||
 | 
					                        (call-interactively #'vterm-mgt-find-or-create))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(general-define-key
 | 
				
			||||||
 | 
					 :keymaps '(vterm-mode-map)
 | 
				
			||||||
 | 
					 "C-S-n" #'vterm-mgt-instantiate
 | 
				
			||||||
 | 
					 "C-S-w" #'vterm-mgt-kill
 | 
				
			||||||
 | 
					 "<C-tab>" #'vterm-mgt-next
 | 
				
			||||||
 | 
					 "<C-S-iso-lefttab>" #'vterm-mgt-prev
 | 
				
			||||||
 | 
					 "<s-backspace>" #'vterm-mgt-rename-buffer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(provide 'keybindings)
 | 
					(provide 'keybindings)
 | 
				
			||||||
;;; keybindings.el ends here
 | 
					;;; keybindings.el ends here
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										120
									
								
								emacs/.emacs.d/wpc/vterm-mgt.el
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								emacs/.emacs.d/wpc/vterm-mgt.el
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,120 @@
 | 
				
			||||||
 | 
					;;; vterm-mgt.el --- Help me manage my vterm instances -*- lexical-binding: t -*-
 | 
				
			||||||
 | 
					;; Author: William Carroll <wpcarro@gmail.com>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;;; Commentary:
 | 
				
			||||||
 | 
					;; Supporting functions to instantiate vterm buffers, kill existing vterm
 | 
				
			||||||
 | 
					;; buffers, rename vterm buffers, cycle forwards and backwards through vterm
 | 
				
			||||||
 | 
					;; buffers.
 | 
				
			||||||
 | 
					;;
 | 
				
			||||||
 | 
					;; Many of the functions defined herein are intended to be bound to
 | 
				
			||||||
 | 
					;; `vterm-mode-map'.  Some assertions are made to guard against calling
 | 
				
			||||||
 | 
					;; functions that are intended to be called from outside of a vterm buffer.
 | 
				
			||||||
 | 
					;; These assertions shouldn't error when the functions are bound to
 | 
				
			||||||
 | 
					;; `vterm-mode-map'.  If for some reason, you'd like to bind these functions to
 | 
				
			||||||
 | 
					;; a separate keymap, caveat emptor.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;;; Code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
				
			||||||
 | 
					;; Dependencies
 | 
				
			||||||
 | 
					;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(require 'dash)
 | 
				
			||||||
 | 
					(require 'cycle)
 | 
				
			||||||
 | 
					(require 'vterm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
				
			||||||
 | 
					;; Configuration
 | 
				
			||||||
 | 
					;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defconst vterm-mgt--instances (cycle/new)
 | 
				
			||||||
 | 
					  "A cycle tracking all of my vterm instances.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defcustom vterm-mgt-scroll-on-focus nil
 | 
				
			||||||
 | 
					  "When t, call `end-of-buffer' after focusing a vterm instance.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun vterm-mgt--instance? (b)
 | 
				
			||||||
 | 
					  "Return t if the buffer B is a vterm instance."
 | 
				
			||||||
 | 
					  (equal 'vterm-mode (buffer-local-value 'major-mode b)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defmacro vterm-mgt--assert-vterm-buffer ()
 | 
				
			||||||
 | 
					  "Error when the `current-buffer' is not a vterm buffer."
 | 
				
			||||||
 | 
					  '(prelude/assert (vterm-mgt--instance? (current-buffer))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun vterm-mgt-next ()
 | 
				
			||||||
 | 
					  "Replace the current buffer with the next item in `vterm-mgt--instances'.
 | 
				
			||||||
 | 
					This function should be called from a buffer running vterm."
 | 
				
			||||||
 | 
					  (interactive)
 | 
				
			||||||
 | 
					  (vterm-mgt--assert-vterm-buffer)
 | 
				
			||||||
 | 
					  (cycle/focus-item (current-buffer) vterm-mgt--instances)
 | 
				
			||||||
 | 
					  (switch-to-buffer (cycle/next vterm-mgt--instances))
 | 
				
			||||||
 | 
					  (when vterm-mgt-scroll-on-focus (end-of-buffer)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun vterm-mgt-prev ()
 | 
				
			||||||
 | 
					  "Replace the current buffer with the previous item in `vterm-mgt--instances'.
 | 
				
			||||||
 | 
					This function should be called from a buffer running vterm."
 | 
				
			||||||
 | 
					  (interactive)
 | 
				
			||||||
 | 
					  (vterm-mgt--assert-vterm-buffer)
 | 
				
			||||||
 | 
					  (cycle/focus-item (current-buffer) vterm-mgt--instances)
 | 
				
			||||||
 | 
					  (switch-to-buffer (cycle/prev vterm-mgt--instances))
 | 
				
			||||||
 | 
					  (when vterm-mgt-scroll-on-focus (end-of-buffer)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun vterm-mgt-instantiate ()
 | 
				
			||||||
 | 
					  "Create a new vterm instance.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Prefer calling this function instead of `vterm'.  This function ensures that the
 | 
				
			||||||
 | 
					  newly created instance is added to `vterm-mgt--instances'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If however you must call `vterm', if you'd like to cycle through vterm
 | 
				
			||||||
 | 
					  instances, make sure you call `vterm-mgt-populate-cycle' to allow vterm-mgt to
 | 
				
			||||||
 | 
					  collect any untracked vterm instances."
 | 
				
			||||||
 | 
					  (interactive)
 | 
				
			||||||
 | 
					  (let ((buffer (vterm)))
 | 
				
			||||||
 | 
					    (cycle/append buffer vterm-mgt--instances)
 | 
				
			||||||
 | 
					    (cycle/focus-item buffer vterm-mgt--instances)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun vterm-mgt-kill ()
 | 
				
			||||||
 | 
					  "Kill the current buffer and remove it from `vterm-mgt--instances'.
 | 
				
			||||||
 | 
					This function should be called from a buffer running vterm."
 | 
				
			||||||
 | 
					  (interactive)
 | 
				
			||||||
 | 
					  (vterm-mgt--assert-vterm-buffer)
 | 
				
			||||||
 | 
					  (let ((buffer (current-buffer)))
 | 
				
			||||||
 | 
					    (cycle/remove buffer vterm-mgt--instances)
 | 
				
			||||||
 | 
					    (kill-buffer buffer)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun vterm-mgt-find-or-create ()
 | 
				
			||||||
 | 
					  "Call `switch-to-buffer' on a focused vterm instance if there is one.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When `cycle/focused?' returns nil, focus the first item in the cycle.  When
 | 
				
			||||||
 | 
					there are no items in the cycle, call `vterm-mgt-instantiate' to create a vterm
 | 
				
			||||||
 | 
					instance."
 | 
				
			||||||
 | 
					  (interactive)
 | 
				
			||||||
 | 
					  (if (cycle/empty? vterm-mgt--instances)
 | 
				
			||||||
 | 
					      (vterm-mgt-instantiate)
 | 
				
			||||||
 | 
					    (if (cycle/focused? vterm-mgt--instances)
 | 
				
			||||||
 | 
					        (switch-to-buffer (cycle/current vterm-mgt--instances))
 | 
				
			||||||
 | 
					      (progn
 | 
				
			||||||
 | 
					        (cycle/jump 0 vterm-mgt--instances)
 | 
				
			||||||
 | 
					        (switch-to-buffer (cycle/current vterm-mgt--instances))))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun vterm-mgt-rename-buffer (name)
 | 
				
			||||||
 | 
					  "Rename the current buffer ensuring that its NAME is wrapped in *vterm*<...>.
 | 
				
			||||||
 | 
					This function should be called from a buffer running vterm."
 | 
				
			||||||
 | 
					  (interactive "SRename vterm buffer: ")
 | 
				
			||||||
 | 
					  (vterm-mgt--assert-vterm-buffer)
 | 
				
			||||||
 | 
					  (rename-buffer (format "vterm<%s>" name)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(defun vterm-mgt-repopulate-cycle ()
 | 
				
			||||||
 | 
					  "Fill `vterm-mgt--instances' with the existing vterm buffers.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If for whatever reason, the state of `vterm-mgt--instances' is corrupted and
 | 
				
			||||||
 | 
					  misaligns with the state of vterm buffers in Emacs, use this function to
 | 
				
			||||||
 | 
					  attempt to restore the state."
 | 
				
			||||||
 | 
					  (interactive)
 | 
				
			||||||
 | 
					  (setq vterm-mgt--instances
 | 
				
			||||||
 | 
					        (->> (buffer-list)
 | 
				
			||||||
 | 
					             (-filter #'vterm-mgt--instance?)
 | 
				
			||||||
 | 
					             cycle/from-list)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(provide 'vterm-mgt)
 | 
				
			||||||
 | 
					;;; vterm-mgt.el ends here
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,7 @@
 | 
				
			||||||
(require 'display)
 | 
					(require 'display)
 | 
				
			||||||
(require 'dotfiles)
 | 
					(require 'dotfiles)
 | 
				
			||||||
(require 'org-helpers)
 | 
					(require 'org-helpers)
 | 
				
			||||||
(require 'vterm)
 | 
					(require 'vterm-mgt)
 | 
				
			||||||
(require 'dash)
 | 
					(require 'dash)
 | 
				
			||||||
(require 'evil)
 | 
					(require 'evil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -521,7 +521,7 @@ This function asssumes that BUFFER passes the `exwm/exwm-buffer?' predicate."
 | 
				
			||||||
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
					     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
				
			||||||
     (progn
 | 
					     (progn
 | 
				
			||||||
       (exwm/switch "Terminal")
 | 
					       (exwm/switch "Terminal")
 | 
				
			||||||
       (vterm))
 | 
					       (vterm-mgt-instantiate))
 | 
				
			||||||
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
					     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
				
			||||||
     ;; Todos
 | 
					     ;; Todos
 | 
				
			||||||
     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
					     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,7 @@ let
 | 
				
			||||||
    ]) ++
 | 
					    ]) ++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    (with epkgs.melpaPackages; [
 | 
					    (with epkgs.melpaPackages; [
 | 
				
			||||||
 | 
					      vterm
 | 
				
			||||||
      base16-theme
 | 
					      base16-theme
 | 
				
			||||||
      ivy-pass
 | 
					      ivy-pass
 | 
				
			||||||
      clipmon # TODO: Prefer an Emacs client for clipmenud.
 | 
					      clipmon # TODO: Prefer an Emacs client for clipmenud.
 | 
				
			||||||
| 
						 | 
					@ -122,7 +123,6 @@ let
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    (with depot.tools.emacs-pkgs; [
 | 
					    (with depot.tools.emacs-pkgs; [
 | 
				
			||||||
      dottime
 | 
					      dottime
 | 
				
			||||||
      term-switcher
 | 
					 | 
				
			||||||
    ]));
 | 
					    ]));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# TODO: Do I need `pkgs.lib.fix`?
 | 
					# TODO: Do I need `pkgs.lib.fix`?
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue