From 6882b9575865c407d22386da065a370fdbc80396 Mon Sep 17 00:00:00 2001 From: William Carroll Date: Sat, 30 Jul 2022 11:19:43 -0700 Subject: feat(wpcarro/emacs): Package vterm-mgt.el Pretty useful (but still needs some polishing) library for working with `vterm`, which I use on a daily basis. Change-Id: Ic6693f52ad9b16b0b4dd1338aedeeccd6ff15379 Reviewed-on: https://cl.tvl.fyi/c/depot/+/6017 Reviewed-by: wpcarro Autosubmit: wpcarro Tested-by: BuildkiteCI --- users/wpcarro/emacs/.emacs.d/wpc/vterm-mgt.el | 142 ------------------------ users/wpcarro/emacs/default.nix | 1 + users/wpcarro/emacs/pkgs/vterm-mgt/default.nix | 18 +++ users/wpcarro/emacs/pkgs/vterm-mgt/vterm-mgt.el | 142 ++++++++++++++++++++++++ 4 files changed, 161 insertions(+), 142 deletions(-) delete mode 100644 users/wpcarro/emacs/.emacs.d/wpc/vterm-mgt.el create mode 100644 users/wpcarro/emacs/pkgs/vterm-mgt/default.nix create mode 100644 users/wpcarro/emacs/pkgs/vterm-mgt/vterm-mgt.el (limited to 'users') diff --git a/users/wpcarro/emacs/.emacs.d/wpc/vterm-mgt.el b/users/wpcarro/emacs/.emacs.d/wpc/vterm-mgt.el deleted file mode 100644 index 29c24d89ec..0000000000 --- a/users/wpcarro/emacs/.emacs.d/wpc/vterm-mgt.el +++ /dev/null @@ -1,142 +0,0 @@ -;;; vterm-mgt.el --- Help me manage my vterm instances -*- lexical-binding: t -*- - -;; Author: William Carroll -;; Version: 0.0.1 -;; Package-Requires: ((emacs "25.1")) - -;;; 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 -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defgroup vterm-mgt nil - "Customization options for `vterm-mgt'.") - -(defcustom vterm-mgt-scroll-on-focus nil - "When t, call `end-of-buffer' after focusing a vterm instance." - :type '(boolean) - :group 'vterm-mgt) - -(defconst vterm-mgt--instances (cycle-new) - "A cycle tracking all of my vterm instances.") - -(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) - (vterm-mgt-reconcile-state) - (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) - (vterm-mgt-reconcile-state) - (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-reconcile-state' to allow vterm-mgt - to collect any untracked vterm instances." - (interactive) - (vterm-mgt-reconcile-state) - (let ((buffer (vterm t))) - (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))) - (when (kill-buffer buffer) - (vterm-mgt-reconcile-state)))) - -(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) - (vterm-mgt-reconcile-state) - (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-reconcile-state () - "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 - restore the state." - (interactive) - (setq vterm-mgt--instances - (->> (buffer-list) - (-filter #'vterm-mgt--instance?) - cycle-from-list))) - -(defun vterm-mgt-select () - "Select a vterm instance by name from the list in `vterm-mgt--instances'." - (interactive) - (vterm-mgt-reconcile-state) - (switch-to-buffer - (completing-read "Switch to vterm: " - (->> vterm-mgt--instances - cycle-to-list - (-map #'buffer-name))))) - -(provide 'vterm-mgt) -;;; vterm-mgt.el ends here diff --git a/users/wpcarro/emacs/default.nix b/users/wpcarro/emacs/default.nix index 99b18d8f97..be79884b46 100644 --- a/users/wpcarro/emacs/default.nix +++ b/users/wpcarro/emacs/default.nix @@ -33,6 +33,7 @@ let string struct symbol + vterm-mgt zle ]) ++ diff --git a/users/wpcarro/emacs/pkgs/vterm-mgt/default.nix b/users/wpcarro/emacs/pkgs/vterm-mgt/default.nix new file mode 100644 index 0000000000..c97e54e719 --- /dev/null +++ b/users/wpcarro/emacs/pkgs/vterm-mgt/default.nix @@ -0,0 +1,18 @@ +{ pkgs, depot, ... }: + +pkgs.callPackage + ({ emacsPackages }: + emacsPackages.trivialBuild { + pname = "vterm-mgt"; + version = "1.0.0"; + src = ./vterm-mgt.el; + packageRequires = + (with emacsPackages; [ + dash + vterm + ]) ++ + (with depot.users.wpcarro.emacs.pkgs; [ + cycle + ]); + }) +{ } diff --git a/users/wpcarro/emacs/pkgs/vterm-mgt/vterm-mgt.el b/users/wpcarro/emacs/pkgs/vterm-mgt/vterm-mgt.el new file mode 100644 index 0000000000..29c24d89ec --- /dev/null +++ b/users/wpcarro/emacs/pkgs/vterm-mgt/vterm-mgt.el @@ -0,0 +1,142 @@ +;;; vterm-mgt.el --- Help me manage my vterm instances -*- lexical-binding: t -*- + +;; Author: William Carroll +;; Version: 0.0.1 +;; Package-Requires: ((emacs "25.1")) + +;;; 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 +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defgroup vterm-mgt nil + "Customization options for `vterm-mgt'.") + +(defcustom vterm-mgt-scroll-on-focus nil + "When t, call `end-of-buffer' after focusing a vterm instance." + :type '(boolean) + :group 'vterm-mgt) + +(defconst vterm-mgt--instances (cycle-new) + "A cycle tracking all of my vterm instances.") + +(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) + (vterm-mgt-reconcile-state) + (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) + (vterm-mgt-reconcile-state) + (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-reconcile-state' to allow vterm-mgt + to collect any untracked vterm instances." + (interactive) + (vterm-mgt-reconcile-state) + (let ((buffer (vterm t))) + (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))) + (when (kill-buffer buffer) + (vterm-mgt-reconcile-state)))) + +(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) + (vterm-mgt-reconcile-state) + (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-reconcile-state () + "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 + restore the state." + (interactive) + (setq vterm-mgt--instances + (->> (buffer-list) + (-filter #'vterm-mgt--instance?) + cycle-from-list))) + +(defun vterm-mgt-select () + "Select a vterm instance by name from the list in `vterm-mgt--instances'." + (interactive) + (vterm-mgt-reconcile-state) + (switch-to-buffer + (completing-read "Switch to vterm: " + (->> vterm-mgt--instances + cycle-to-list + (-map #'buffer-name))))) + +(provide 'vterm-mgt) +;;; vterm-mgt.el ends here -- cgit 1.4.1