config

Personal configuration.
git clone git://code.dwrz.net/config
Log | Files | Refs

eshell-vterm.el (4098B)


      1 ;;; eshell-vterm.el --- Vterm for visual commands in eshell -*- lexical-binding: t; -*-
      2 
      3 ;; Author: Illia Ostapyshyn <ilya.ostapyshyn@gmail.com>
      4 ;; Maintainer: Illia Ostapyshyn <ilya.ostapyshyn@gmail.com>
      5 ;; Created: 2021-06-29
      6 ;; Package-Version: 20240305.1149
      7 ;; Package-Revision: 20f4b246fa60
      8 ;; Package-Requires: ((emacs "27.1") (vterm "0.0.1"))
      9 ;; Keywords: eshell, vterm, terminals, shell, visual, tools, processes
     10 ;; URL: https://github.com/iostapyshyn/eshell-vterm
     11 
     12 ;; This file is not part of GNU Emacs.
     13 
     14 ;; This file is free software; you can redistribute it and/or modify
     15 ;; it under the terms of the GNU General Public License as published by
     16 ;; the Free Software Foundation; either version 2, or (at your option)
     17 ;; any later version.
     18 
     19 ;; This file is distributed in the hope that it will be useful,
     20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     22 ;; GNU General Public License for more details.
     23 
     24 ;; You should have received a copy of the GNU General Public License
     25 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
     26 
     27 ;;; Commentary:
     28 
     29 ;; This package provides a global minor mode allowing eshell to use
     30 ;; vterm for visual commands.
     31 
     32 ;;; Code:
     33 
     34 (require 'vterm)
     35 (require 'em-term)
     36 (require 'esh-ext)
     37 
     38 (defvar eshell-parent-buffer)
     39 
     40 (defun eshell-vterm-exec-visual (&rest args)
     41   "Run the specified PROGRAM in a terminal emulation buffer.
     42 ARGS are passed to the program.  At the moment, no piping of input is
     43 allowed.  In case ARGS is nil, a new VTerm session is created."
     44   (if args
     45       (let* (eshell-interpreter-alist
     46              (interp (eshell-find-interpreter (car args) (cdr args)))
     47              (program (car interp))
     48              (args (flatten-tree
     49                     (eshell-stringify-list (append (cdr interp)
     50                                                    (cdr args)))))
     51              (args (mapconcat #'shell-quote-argument args " "))
     52              (term-buf (generate-new-buffer
     53                         (concat "*" (file-name-nondirectory program) "*")))
     54              (eshell-buf (current-buffer))
     55              (vterm-shell (concat (shell-quote-argument
     56                                    (file-local-name program))
     57                                   " " args)))
     58         (save-current-buffer
     59           (switch-to-buffer term-buf)
     60           (cl-letf (((symbol-function 'vterm--get-shell)
     61                      (lambda () vterm-shell)))
     62             (vterm-mode))
     63           (setq-local eshell-parent-buffer eshell-buf)
     64           (let ((proc (get-buffer-process term-buf)))
     65             (if (and proc (eq 'run (process-status proc)))
     66                 (set-process-sentinel proc #'eshell-vterm-sentinel)
     67               (error "Failed to invoke visual command")))))
     68     (vterm '(4))) ; Start a new session
     69   nil)
     70 
     71 (defun eshell-vterm-sentinel (proc msg)
     72   "Clean up the buffer visiting PROC with message MSG.
     73 If `eshell-destroy-buffer-when-process-dies' is non-nil, destroy
     74 the buffer."
     75   (let ((vterm-kill-buffer-on-exit nil))
     76     (vterm--sentinel proc msg)) ;; First call the normal term sentinel.
     77   (when eshell-destroy-buffer-when-process-dies
     78     (let ((proc-buf (process-buffer proc)))
     79       (when (and proc-buf (buffer-live-p proc-buf)
     80                  (not (eq 'run (process-status proc)))
     81                  (= (process-exit-status proc) 0))
     82         (if (eq (current-buffer) proc-buf)
     83             (let ((buf (and (boundp 'eshell-parent-buffer)
     84                             eshell-parent-buffer
     85                             (buffer-live-p eshell-parent-buffer)
     86                             eshell-parent-buffer)))
     87               (if buf
     88                   (switch-to-buffer buf))))
     89         (kill-buffer proc-buf)))))
     90 
     91 ;;;###autoload
     92 (define-minor-mode eshell-vterm-mode
     93   "Use Vterm for eshell visual commands."
     94   :global t
     95   :group 'eshell-vterm
     96   (if eshell-vterm-mode
     97       (advice-add #'eshell-exec-visual :override #'eshell-vterm-exec-visual)
     98     (advice-remove #'eshell-exec-visual #'eshell-vterm-exec-visual)))
     99 
    100 (provide 'eshell-vterm)
    101 ;;; eshell-vterm.el ends here