Browse Source

add document for ob-eshell

stardiviner 11 months ago
parent
commit
9156ecf809
1 changed files with 165 additions and 0 deletions
  1. 165 0
      org-contrib/babel/languages/ob-doc-eshell.org

+ 165 - 0
org-contrib/babel/languages/ob-doc-eshell.org

@@ -0,0 +1,165 @@
+#+OPTIONS:    H:3 num:nil toc:2 \n:nil ::t |:t ^:{} -:t f:t *:t tex:t d:(HIDE) tags:not-in-toc
+#+STARTUP:    align fold nodlcheck hidestars oddeven lognotestate hideblocks
+#+SEQ_TODO:   TODO(t) INPROGRESS(i) WAITING(w@) | DONE(d) CANCELED(c@)
+#+TAGS:       Write(w) Update(u) Fix(f) Check(c) noexport(n)
+#+TITLE:      Org-babel-eshell
+#+AUTHOR:     stardiviner
+#+EMAIL:      numbchild at gmail dot com
+#+LANGUAGE:   en
+#+HTML_HEAD:      <style type="text/css">#outline-container-introduction{ clear:both; }</style>
+#+LINK_UP:    ../languages.html
+#+LINK_HOME:  https://orgmode.org/worg/
+
+* Motivation
+
+Eshell is Emacs built-in powerful shell. Combine Eshell with Org-mode Babel is great!
+
+
+* Simple execution
+
+#+begin_src eshell
+(setq hello-world "hello, world")
+echo $hello-world
+#+end_src
+
+#+RESULTS[<2018-04-22 09:52:01> d1708dc4cf0532b5fb254837e3e313a76fe0f02c]:
+: hello, world
+
+
+* Support variables assignment
+
+#+begin_src eshell :var name="stardiviner"
+echo "hello, " $name
+#+end_src
+
+#+RESULTS[<2018-04-22 10:03:51> d49eeac7c268b4cc02d8670a54f6b34084359c9d]:
+: ("hello, " "stardiviner")
+
+
+* Support session
+
+#+begin_src eshell :session *kk*
+(setq hello-world "hello, world")
+(setq hello-stardiviner "hello, stardiviner")
+#+end_src
+
+#+RESULTS[<2018-04-22 10:08:31> 5dd0a2ab05c6100510e599eb8cc321d952f7f0a4]:
+: hello, stardiviner
+
+#+begin_src eshell :session *kk*
+echo $hello-world
+#+end_src
+
+#+RESULTS[<2018-04-22 10:13:18> 1bfdc81da0834b97295ddd7ed57fd78c9bb5c8f1]:
+: hello, world
+
+
+* Source code
+
+#+begin_src emacs-lisp
+;;; ob-eshell.el --- Babel Functions for Eshell            -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2009-2018 Free Software Foundation, Inc.
+
+;; Author: stardiviner <numbchild@gmail.com>
+;; Keywords: literate programming, reproducible research
+;; Homepage: https://orgmode.org
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Org Babel support for evaluating Eshell source code.
+
+;;; Code:
+(require 'ob)
+(require 'eshell)
+
+(defvar org-babel-default-header-args:eshell '())
+
+(defun org-babel-execute:eshell (body params)
+  "Execute a block of Eshell code BODY with PARAMS.
+This function is called by `org-babel-execute-src-block'.
+
+The BODY can be any code which allowed executed in Eshell.
+Eshell allow to execute normal shell command and Elisp code.
+More details please reference Eshell Info.
+
+The PARAMS are variables assignments."
+  (let* ((session (org-babel-eshell-initiate-session
+		   (cdr (assq :session params))))
+	 (full-body (org-babel-expand-body:generic
+		     body params (org-babel-variable-assignments:eshell params))))
+    (if session
+	(progn
+	  (with-current-buffer session
+	    (dolist (line (split-string full-body "\n"))
+	      (goto-char eshell-last-output-end)
+	      (insert line)
+	      (eshell-send-input))
+	    ;; get output of last input
+	    ;; TODO: collect all output instead of last command's output.
+	    (goto-char eshell-last-input-end)
+	    (buffer-substring-no-properties (point) eshell-last-output-start)))
+      (with-temp-buffer
+	(eshell-command full-body t)
+	(buffer-string)))))
+
+(defun org-babel-prep-session:eshell (session params)
+  "Prepare SESSION according to the header arguments specified in PARAMS."
+  (let* ((session (org-babel-eshell-initiate-session session))
+	 ;; Eshell session buffer is read from variable `eshell-buffer-name'.
+	 (eshell-buffer-name session)
+	 (var-lines (org-babel-variable-assignments:eshell params)))
+    (call-interactively #'eshell)
+    (mapc #'eshell-command var-lines)
+    session))
+
+(defun ob-eshell-session-live-p (session)
+  "Non-nil if Eshell SESSION exists."
+  (get-buffer session))
+
+(defun org-babel-eshell-initiate-session (&optional session params)
+  "Initiate a session named SESSION according to PARAMS."
+  (when (and session (not (string= session "none")))
+    (save-window-excursion
+      (or (ob-eshell-session-live-p session)
+	  (progn
+	    (let ((eshell-buffer-name session))
+	      (eshell))
+	    (get-buffer (current-buffer)))))
+    session))
+
+(defun org-babel-variable-assignments:eshell (params)
+  "Convert ob-eshell :var specified variables into Eshell variables assignments."
+  (mapcar
+   (lambda (pair)
+     (format "(setq %s %S)" (car pair) (cdr pair)))
+   (org-babel--get-vars params)))
+
+(defun org-babel-load-session:eshell (session body params)
+  "Load BODY into SESSION with PARAMS."
+  (save-window-excursion
+    (let ((buffer (org-babel-prep-session:eshell session params)))
+      (with-current-buffer buffer
+	(goto-char (point-max))
+	(insert (org-babel-chomp body)))
+      buffer)))
+
+(provide 'ob-eshell)
+
+;;; ob-eshell.el ends here
+#+end_src