branch: externals/dtache commit 3fd5e83aca1872c51cbf65164bcea8181c804544 Author: Niklas Eklund <niklas.ekl...@posteo.net> Commit: Niklas Eklund <niklas.ekl...@posteo.net>
Add dtache-org extension This commit adds the dtache-org extension. This makes it possible to use dtache inside org-babel blocks, when the language is set to shell. The user provides an additional header argument :dtache t in order to use dtache on a code block. --- CHANGELOG.org | 1 + README.org | 34 +++++++++++++++++++++++---- dtache-org.el | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.org b/CHANGELOG.org index 8f3e31f60f..5e22dad2b2 100644 --- a/CHANGELOG.org +++ b/CHANGELOG.org @@ -4,6 +4,7 @@ * Development +- Add support for =org= through the =dtache-org= extension. This makes it possible to use =dtache= with =org-babel= (shell) source code blocks. - Support for multiple Emacs sessions. When a =dtache= session is created, it will now become visible in all active Emacs sessions. * Version 0.4 (2022-010-22) diff --git a/README.org b/README.org index 187997fb73..0304fcba30 100644 --- a/README.org +++ b/README.org @@ -55,7 +55,7 @@ The sessions are made persistent by writing the =dtache-session= objects to file * Installation -The package is available on [[https://elpa.gnu.org][GNU ELPA]] and [[https://melpa.org/][MELPA]], and for users of the [[https://guix.gnu.org/][GNU Guix package manager]] there is a [[https://guix.gnu.org/en/packages/emacs-dtache-0.3-0.9e0acd5/][guix package]]. +The package is available on [[https://elpa.gnu.org][GNU ELPA]] and [[https://melpa.org/][MELPA]], and for users of the [[https://guix.gnu.org/][GNU Guix package manager]] there is a guix package. * Configuration @@ -82,9 +82,10 @@ There are tree different ways to create a dtache session. | =dtache-shell-send-input= | Called from inside M-x shell | | =dtache-eshell-send-input= | Called from inside eshell | | =dtache-compile= | Called from M-x | +| =dtache-org= | Used in org-babel src blocks | | =dtache-start-session= | Called from within a function | -The =dtache-shell-command= is for the Emacs users that are accustomed to running shell commands from =M-x shell-command= or =M-x async-shell-command=. The =dtache-shell-send-input= is for those that want to run a command through =dtache= when inside a =shell= buffer. The =dtache-eshell-send-input= is the equivalent for =eshell=. The =dtache-compile= is supposed to be used as a replacement for =compile=. Last there is the =dtache-start-session= function, which users can utilize in their o [...] +The =dtache-shell-command= is for the Emacs users that are accustomed to running shell commands from =M-x shell-command= or =M-x async-shell-command=. The =dtache-shell-send-input= is for those that want to run a command through =dtache= when inside a =shell= buffer. The =dtache-eshell-send-input= is the equivalent for =eshell=. The =dtache-compile= is supposed to be used as a replacement for =compile=. The =dtache-org= provides integration with =org-babel= in order to execute shell sour [...] To detach from a =dtache= session you should use the universal =dtache-detach-session= command. The keybinding for this command is defined by the =dtache-detach-key= variable, which by default has the value =C-c C-d=. @@ -122,7 +123,7 @@ These commands are available through the =dtache-action-map=. The user can bind Then upon invocation the user can choose an action, keybindings listed in the table above, and then choose a session to perform the action upon. See further down in the document how to integrate these bindings with =embark=. * Extensions -** Dtache-shell +** Shell A =use-package= configuration of the =dtache-shell= extension, which provides the integration with =M-x shell=. @@ -142,7 +143,7 @@ A minor mode named =dtache-shell-mode= is provided, and will be enabled in =shel | dtache-shell-attach-session | Attach to a dtache session | <C-return> | | dtache-detach-session | Detach from a dtache session | dtache-detach-key | -** Dtache-eshell +** Eshell A =use-package= configuration of the =dtache-eshell= extension, which provides the integration with =eshell=. @@ -174,6 +175,29 @@ A =use-package= configuration of the =dtache-compile= extension, which provides The package implements the commands =dtache-compile= and =dtache-compile-recompile=, which are thin wrappers around the original =compile= and =recompile= commands. The users should be able to use the former as replacements for the latter without noticing any difference except from the possibility to =detach=. +** Org + +A =use-package= configuration of the =dtache-org= extension, which provides the integration with =org-babel=. + +#+begin_src elisp + (use-package dtache-org + :after (dtache org) + :config + (dtache-org-setup)) +#+end_src + +The package implements an additional header argument for =ob-shell=. The header argument is =:dtache t=. When provided it will enable the code inside a src block to be run with =dtache=. Since org is not providing any live updates on the output the session is created with =dtache-sesion-mode= set to =create=. This means that if you want to access the output of the session you do that the same way you would for any other type of session. The =dtache-org= works both with and without the =: [...] + +#+begin_example + ,#+begin_src sh :dtache t + cd ~/code + ls -la + ,#+end_src + + ,#+RESULTS: + : [detached] +#+end_example + ** Consult A =use-package= configuration of the =dtache-consult= extension, which provides the integration with the [[https://github.com/minad/consult][consult]] package. @@ -256,6 +280,7 @@ Apart from those variables there is also the different =action= variables, which | dtache-eshell-session-action | Actions for sessions launched with =dtache-eshell-send-input= | | dtache-shell-session-action | Actions for sessions launched with =dtache-shell-send-input= | | dtache-compile-session-action | Actions for sessions launched with =dtache-compile= | +| dtache-org-session-action | Actions for sessions launched with =dtache-org= | ** Completion annotations @@ -304,7 +329,6 @@ Next add the annotation function to the =dtache-metadata-annotators-alist= toget #+end_src ** Nonattachable commands - To be able to both attach to a dtach session as well as logging its output =dtache= relies on the usage of =tee=. However it is possible that the user tries to run a command which involves a program that doesn't integrate well with tee. In those situations the output could be delayed until the session ends, which is not preferable. For these situations =dtache= provides the =dtache-nonattachable-commands= variable. This is a list of regular expressions. Any command that matches any of the strings will be getting the property =attachable= set to false. diff --git a/dtache-org.el b/dtache-org.el new file mode 100644 index 0000000000..4a907921bd --- /dev/null +++ b/dtache-org.el @@ -0,0 +1,75 @@ +;;; dtache-org.el --- Dtache integration for org -*- lexical-binding: t -*- + +;; Copyright (C) 2022 Free Software Foundation, Inc. + +;; This file is not part of GNU Emacs. + +;; This program 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. + +;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + +;;; Commentary: + +;; This package integrates `dtache' with `org'. In particular it +;; integrates with `ob-shell' in order to detach babel src blocks. + +;;; Code: + +;;;; Requirements + +(require 'dtache) +(require 'ob-shell) + +;;;; Variables + +(defcustom dtache-org-session-action + '(:attach dtache-shell-command-attach-session + :view dtache-view-dwim + :run dtache-shell-command) + "Actions for a session created with `dtache-org'." + :group 'dtache + :type 'plist) + +;;;; Functions + +;;;###autoload +(defun dtache-org-setup () + "Setup `dtache-org'." + (dtache-setup) + (advice-add #'org-babel-sh-evaluate :around #'dtache-org-babel-sh)) + +(defun dtache-org-babel-sh (org-babel-sh-evaluate-fun &rest args) + "Modify ARGS before calling ORG-BABEL-SH-EVALUATE-FUN. + +This function modifies the full-body in ARGS and replaces it with a +`dtache' command. The functionality is enabled by setting a header +property of :dtache t in the org babel src block." + (pcase-let* ((`(,session ,full-body ,params ,stdin ,cmdline) args)) + (if (alist-get :dtache params) + (cl-letf* ((dtache-session-origin 'org) + (dtache-session-action dtache-org-session-action) + (dtache-session-mode 'create) + (new-command (replace-regexp-in-string "\n" " && " full-body)) + (dtach-command + (if (string= "none" (alist-get :session params)) + (dtache-dtach-command new-command t) + (format "%s\necho \"[detached]\"" (dtache-dtach-command new-command t)))) + ((symbol-function #'org-babel-eval) + (lambda (_ command) + (start-file-process-shell-command "dtache-org" nil command) + "[detached]"))) + (apply org-babel-sh-evaluate-fun `(,session ,dtach-command ,params ,stdin ,cmdline))) + (apply org-babel-sh-evaluate-fun args)))) + +(provide 'dtache-org) + +;;; dtache-org.el ends here