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…
Reference in a new issue