config

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

ob-eshell.el (4040B)


      1 ;;; ob-eshell.el --- Babel Functions for Eshell      -*- lexical-binding: t; -*-
      2 
      3 ;; Copyright (C) 2018-2024 Free Software Foundation, Inc.
      4 
      5 ;; Author: stardiviner <numbchild@gmail.com>
      6 ;; Maintainer: stardiviner <numbchild@gmail.com>
      7 ;; URL: https://github.com/stardiviner/ob-eshell
      8 ;; Keywords: literate programming, reproducible research
      9 
     10 ;; This file is part of GNU Emacs.
     11 
     12 ;; GNU Emacs is free software: you can redistribute it and/or modify
     13 ;; it under the terms of the GNU General Public License as published by
     14 ;; the Free Software Foundation, either version 3 of the License, or
     15 ;; (at your option) any later version.
     16 
     17 ;; GNU Emacs is distributed in the hope that it will be useful,
     18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     20 ;; GNU General Public License for more details.
     21 
     22 ;; You should have received a copy of the GNU General Public License
     23 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
     24 
     25 ;;; Commentary:
     26 
     27 ;; Org Babel support for evaluating Eshell source code.
     28 
     29 ;;; Code:
     30 
     31 (require 'org-macs)
     32 (org-assert-version)
     33 
     34 (require 'ob)
     35 (require 'eshell)
     36 
     37 (declare-function eshell-send-input "esh-mode"
     38                   (&optional use-region queue-p no-newline))
     39 
     40 (defvar eshell-last-output-start)
     41 (defvar eshell-last-output-end)
     42 (defvar eshell-last-input-end)
     43 
     44 (defvar org-babel-default-header-args:eshell '())
     45 
     46 (defun org-babel-execute:eshell (body params)
     47   "Execute a block of Eshell code BODY with PARAMS.
     48 This function is called by `org-babel-execute-src-block'.
     49 
     50 The BODY argument is code which can be executed in Eshell.
     51 Eshell allows executing normal shell command and Elisp code.
     52 For more details, see Info node `(eshell) Top'.
     53 
     54 The PARAMS argument is passed to
     55 `org-babel-expand-body:generic' (which see)."
     56   (let* ((session (org-babel-eshell-initiate-session
     57 		   (cdr (assq :session params))))
     58 	 (full-body (org-babel-expand-body:generic
     59 		     body params (org-babel-variable-assignments:eshell params))))
     60     (if session
     61 	(progn
     62 	  (with-current-buffer session
     63 	    (dolist (line (split-string full-body "\n"))
     64 	      (goto-char eshell-last-output-end)
     65 	      (insert line)
     66 	      (eshell-send-input))
     67 	    ;; get output of last input
     68 	    ;; TODO: collect all output instead of last command's output.
     69 	    (goto-char eshell-last-input-end)
     70 	    (buffer-substring-no-properties (point) eshell-last-output-start)))
     71       (with-temp-buffer
     72 	(eshell-command full-body t)
     73 	(buffer-string)))))
     74 
     75 (defun org-babel-prep-session:eshell (session params)
     76   "Prepare SESSION according to the header arguments specified in PARAMS."
     77   (let* ((session (org-babel-eshell-initiate-session session))
     78 	 ;; Eshell session buffer is read from variable `eshell-buffer-name'.
     79 	 (eshell-buffer-name session)
     80 	 (var-lines (org-babel-variable-assignments:eshell params)))
     81     (call-interactively #'eshell)
     82     (mapc #'eshell-command var-lines)
     83     session))
     84 
     85 (defun ob-eshell-session-live-p (session)
     86   "Non-nil if Eshell SESSION exists."
     87   (get-buffer session))
     88 
     89 (defun org-babel-eshell-initiate-session (&optional session _params)
     90   "Initiate a session named SESSION."
     91   (when (and session (not (string= session "none")))
     92     (save-window-excursion
     93       (unless (ob-eshell-session-live-p session)
     94 	(let ((eshell-buffer-name session)) (eshell))))
     95     session))
     96 
     97 (defun org-babel-variable-assignments:eshell (params)
     98   "Convert ob-eshell variables from PARAMS into Eshell variables assignments."
     99   (mapcar
    100    (lambda (pair)
    101      ;; Use `ignore' to suppress value in the command output.
    102      (format "(ignore (setq %s %S))" (car pair) (cdr pair)))
    103    (org-babel--get-vars params)))
    104 
    105 (defun org-babel-load-session:eshell (session body params)
    106   "Load BODY into SESSION with PARAMS."
    107   (save-window-excursion
    108     (let ((buffer (org-babel-prep-session:eshell session params)))
    109       (with-current-buffer buffer
    110 	(goto-char (point-max))
    111 	(insert (org-babel-chomp body)))
    112       buffer)))
    113 
    114 (provide 'ob-eshell)
    115 
    116 ;;; ob-eshell.el ends here