Compare commits

...

18 Commits

Author SHA1 Message Date
Allard Hendriksen cb4f151554 Update documentation and changelog 2022-10-05 22:41:18 +02:00
Allard Hendriksen e672ca5a95
Merge pull request #17 from KaiHa/pr14
Support variables (fixes #14)
2022-10-05 22:25:16 +02:00
Kai Harries 155ffea48e Support variables (fixes #14)
Forward the variables that are set in the org-babel-header.

E.g

  #+begin_src tmux :var name="Ismael"
    echo hello ${name}
  #+end_src
2022-09-28 22:18:57 +02:00
Allard Hendriksen 3687ed7b87 Fix bug with ob-tmux-format-keys
It was misspelled..
2019-07-08 14:02:40 +02:00
Allard Hendriksen 4d222155a2 Fix bug with where lines with leading "-" were omitted
The following all works:

; echo ;
-echo  ;

; ;  ;   ;    ;
;-;--;---;----;

echo "€ hello 🐩"

Thanks to @medranocalvo for suggesting the fix: use hex encoding to
send the lines.
2019-07-05 17:57:02 +02:00
Allard Hendriksen 9bf6b35b8a Add deprecation warning for :terminal header arguments
This commit adds a deprecation warning when the org source block
header argument :terminal is set. This should give people time to
adjust their settings.

The settings `org-babel-tmux-terminal` org-babel-tmux-terminal-opts`
take precedence over the `:terminal` argument.

Since this is a backward-incompatible change, I have added a
changelog..
2019-07-05 17:55:29 +02:00
dkrm 00e0de3cd7 Update README: add explanation to terminal settings 2019-01-02 17:23:12 +01:00
dkrm 9cd0c05338 Add the possibility to choose the terminal 2018-12-21 12:47:45 +01:00
dkrm 9a3361f13f Remove unnecessary concat function 2018-12-21 11:49:10 +01:00
dkrm 867d1802b2 Fix issue #7 (allowing options to the terminal) 2018-12-21 11:39:17 +01:00
Allard Hendriksen 73bed0ebad Fix bug where trailing semicolon at end of line would be omitted
Tmux assumes a semicolon at the end of a command-line argument means
that a new command is started. See tmux man page around "Multiple
commands may ... a command sequence." This allows, for example, the
following two commands to be executed in one line:

    tmux new-window; split-window -d

Unfortunately, this behaviour meant that trailing semicolons would not
be sent from ob-tmux. For instance,

echo hello;

would yield

> echo hello

In bash, a semi-colon is also interpreted as a command
separator. Hence, zapping the semicolon would usually not cause any
problems. It does, however, cause problems in multi-line strings,
heredocs, etc.

In short, the bug has now been fixed. I have checked that tmux does
not eat any other characters. The code that removes the semicolon is
in the function cmd_list_parse in the file cmd-list.c in the tmux
source code.
2018-08-31 12:17:45 +02:00
Allard Hendriksen 4b5c30eea9 Remove redundant TODO comments
Socket is set in `ob-tmux--execute'.
2018-08-30 16:52:38 +02:00
Allard Hendriksen 2ad983419f Update README: installation instructions for MELPA 2018-08-30 16:52:19 +02:00
Allard Hendriksen 92f398cf0e Fix license language
Previously, the license paragraphs referred to 'GNU Emacs' instead of
'this program'.
2018-08-06 16:31:46 +02:00
Allard Hendriksen 8886f31291 Bump version 0.1.5 2018-07-19 17:51:18 +02:00
Allard Hendriksen 16c59c9b18 Change defvar -> defcustom
Inspired by ob-elvish commit:
9552e44996
2018-07-19 17:49:49 +02:00
Allard Hendriksen eab05445f2 Move internal functions
To get rid of compiler warnings.
2018-07-17 10:59:26 +02:00
Allard Hendriksen fb4333a59e Rename internal functions
To get rid of compiler warnings.
2018-07-17 10:55:47 +02:00
3 changed files with 194 additions and 60 deletions

View File

@ -8,29 +8,62 @@ functionality can be used to document software installation, build
instructions, and administrative tasks. The documentation can be
tested and adjusted while it is written.
* Installation
Unfortunately, ob-tmux has not yet been added to melpa. You will need
to copy the ~ob-tmux.el~ file to a directory in your ~load-path~.
This package is available on from [[https://melpa.org/#/ob-tmux][MELPA]].
If you have added MELPA to your package sources, you can install
ob-tmux interactively
#+BEGIN_EXAMPLE
M-x package-install [RET] ob-tmux [RET]
#+END_EXAMPLE
Alternatively, you can copy the ~ob-tmux.el~ file to a directory in
your ~load-path~.
** Configuration
In your ~.emacs~ or ~.emacs.d/init.el~ file, add the following:
#+BEGIN_SRC elisp
(require 'ob-tmux)
(setq org-babel-default-header-args:tmux
'((:results . "silent") ;
(:session . "default") ; The default tmux session to send code to
(:socket . nil) ; The default tmux socket to communicate with
;; You can use "xterm" and "gnome-terminal".
;; On mac, you can use "iterm" as well.
(:terminal . "gnome-terminal")))
'((:results . "silent") ;
(:session . "default") ; The default tmux session to send code to
(:socket . nil))) ; The default tmux socket to communicate with
;; The tmux sessions are prefixed with the following string.
;; You can customize this if you like.
(setq org-babel-tmux-session-prefix "ob-")
;; The terminal that will be used.
;; You can also customize the options passed to the terminal.
(setq org-babel-tmux-terminal "xterm")
(setq org-babel-tmux-terminal-opts '("-T" "ob-tmux" "-e"))
; The default terminal is "gnome-terminal" with options "--".
;; Finally, if your tmux is not in your $PATH for whatever reason, you
;; may set the path to the tmux binary as follows:
(setq org-babel-tmux-location "/usr/bin/tmux")
#+END_SRC
If you use =use-package=, you can also write
#+BEGIN_SRC elisp
(use-package ob-tmux
;; Install package automatically (optional)
:ensure t
:custom
(org-babel-default-header-args:tmux
'((:results . "silent") ;
(:session . "default") ; The default tmux session to send code to
(:socket . nil))) ; The default tmux socket to communicate with
;; The tmux sessions are prefixed with the following string.
;; You can customize this if you like.
(org-babel-tmux-session-prefix "ob-")
;; The terminal that will be used.
;; You can also customize the options passed to the terminal.
;; The default terminal is "gnome-terminal" with options "--".
(org-babel-tmux-terminal "xterm")
(org-babel-tmux-terminal-opts '("-T" "ob-tmux" "-e"))
;; Finally, if your tmux is not in your $PATH for whatever reason, you
;; may set the path to the tmux binary as follows:
(org-babel-tmux-location "/usr/bin/tmux"))
#+END_SRC
* Usage
You can start a new terminal window with a tmux session as follows:
@ -59,6 +92,12 @@ following example, the ~:session~ argument has been changed to
Executing this code block will add a window, ~new-window~, to your
session.
You can parameterize scripts by using ~:var variable="value"~. This will add a
line containing =variable="value"= preceding the content body.
: #+begin_src tmux :var name="Ismael"
: echo hello ${name}
: #+end_src
You can exit your tmux session by detaching. The terminal window will
close automatically. Ob-tmux will not detect that you have
detached. Any commands you send will be sent to the tmux session in
@ -136,10 +175,6 @@ it is already logged in remotely.
My tmux indexes start at 1. By default, tmux window indexes start at
zero. This might lead to problems. I have not yet checked.
Terminals other than xterm and gnome-terminal have not been
tested. If you have positive or negative experiences with any other
terminal, let me know.
I will try to respond within a week to any issues raised. I cannot
promise I will fix them.
* Contributions

33
changelog.md Normal file
View File

@ -0,0 +1,33 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Fixed
- Fix issue with lines containing leading minus signs "-". (Thanks to
medranocalvo!)
- Fix issue with lines containing trailing semicolon ";".
### Changed
- License language
### Deprecated
- Possibility to configure terminal using org-babel header arguments.
### Added
- Add possibility to define variables (Thanks to KaiHa!)
- Add installation instructions for MELPA.
- Add possibility to configure terminal and add options to the
terminal. (Thanks to dkrm0!)
## [0.1.5] - 2018-07-19
### Changed
- Make variables defcustom
- Rename internal functions
## [0.1.1] - 2018-07-17
### Added
- Initial release
[Unreleased]: https://github.com/ahendriksen/ob-tmux/compare/0.1.5...HEAD
[0.1.5]: https://github.com/ahendriksen/ob-tmux/compare/0.1.1...0.1.5
[0.1.1]: https://github.com/ahendriksen/ob-tmux/tree/0.1.1

View File

@ -6,24 +6,24 @@
;; Author: Allard Hendriksen
;; Keywords: literate programming, interactive shell, tmux
;; URL: https://github.com/ahendriksen/ob-tmux
;; Version: 0.1.2
;; Package-version: 0.1.2
;; Version: 0.1.5
;; Package-version: 0.1.5
;; Package-Requires: ((emacs "25.1") (seq "2.3") (s "1.9.0"))
;; This file is NOT part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; 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.
;; GNU Emacs is distributed in the hope that it will be useful,
;; 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
@ -43,21 +43,37 @@
(require 'seq)
(require 's)
(defvar org-babel-tmux-location "tmux"
(defcustom org-babel-tmux-location "tmux"
"The command location for tmux.
In case you want to use a different tmux than one selected by your $PATH")
Change in case you want to use a different tmux than the one in your $PATH."
:group 'org-babel
:type 'string)
(defvar org-babel-tmux-session-prefix "org-babel-session-"
"The string that will be prefixed to tmux sessions started by ob-tmux.")
(defcustom org-babel-tmux-session-prefix "org-babel-session-"
"The string that will be prefixed to tmux session names started by ob-tmux."
:group 'org-babel
:type 'string)
(defvar org-babel-tmux-default-window-name "ob1"
"This is the default tmux window name used for windows that are not explicitly named in an org session.")
(defcustom org-babel-tmux-default-window-name "ob1"
"This is the default tmux window name used for windows that are not explicitly named in an org session."
:group 'org-babel
:type 'string)
(defcustom org-babel-tmux-terminal "gnome-terminal"
"This is the terminal that will be spawned."
:group 'org-babel
:type 'string)
(defcustom org-babel-tmux-terminal-opts '("--")
"The list of options that will be passed to the terminal."
:group 'org-babel
:type 'list)
(defvar org-babel-default-header-args:tmux
'((:results . "silent")
(:session . "default")
(:socket . nil)
(:terminal . "gnome-terminal"))
(:socket . nil))
"Default arguments to use when running tmux source blocks.")
(add-to-list 'org-src-lang-modes '("tmux" . sh))
@ -75,7 +91,11 @@ Argument PARAMS the org parameters of the code block."
(message "Sending source code block to interactive terminal session...")
(save-window-excursion
(let* ((org-session (cdr (assq :session params)))
(terminal (cdr (assq :terminal params)))
(org-header-terminal (cdr (assq :terminal params)))
(vars (mapcar
(lambda (y) (format "%s=\"%s\"" (cadr y) (cddr y)))
(seq-filter (lambda (x) (eq :var (car x))) params)))
(terminal (or org-header-terminal org-babel-tmux-terminal))
(socket (cdr (assq :socket params)))
(socket (when socket (expand-file-name socket)))
(ob-session (ob-tmux--from-org-session org-session socket))
@ -92,8 +112,12 @@ Argument PARAMS the org parameters of the code block."
;; Disable window renaming from within tmux
(ob-tmux--disable-renaming ob-session)
(ob-tmux--send-body
ob-session (org-babel-expand-body:generic body params)))))
ob-session (org-babel-expand-body:generic body params vars))
;; Warn that setting the terminal from the org source block
;; header arguments is going to be deprecated.
(message "ob-tmux terminal: %s" org-header-terminal)
(when org-header-terminal
(ob-tmux--deprecation-warning org-header-terminal)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ob-tmux object
@ -104,20 +128,23 @@ Argument PARAMS the org parameters of the code block."
window
socket)
(defun ob-tmux--tmux-session (org-session)
"Extract tmux session from ORG-SESSION string."
(let* ((session (car (split-string org-session ":"))))
(concat org-babel-tmux-session-prefix
(if (string-equal "" session) "default" session))))
(defun ob-tmux--tmux-window (org-session)
"Extract tmux window from ORG-SESSION string."
(let* ((window (cadr (split-string org-session ":"))))
(if (string-equal "" window) nil window)))
(defun ob-tmux--from-org-session (org-session &optional socket)
"Create a new ob-tmux-session object from ORG-SESSION specification.
Optional argument SOCKET: the location of the tmux socket (only use if non-standard)."
(defun -tmux-session (org-session)
(let* ((session (car (split-string org-session ":"))))
(concat org-babel-tmux-session-prefix
(if (string-equal "" session) "default" session))))
(defun -tmux-window (org-session)
(let* ((window (cadr (split-string org-session ":"))))
(if (string-equal "" window) nil window)))
(ob-tmux--create
:session (-tmux-session org-session)
:window (-tmux-window org-session)
:session (ob-tmux--tmux-session org-session)
:window (ob-tmux--tmux-window org-session)
:socket socket))
(defun ob-tmux--window-default (ob-session)
@ -174,19 +201,17 @@ automatically space separated."
(defun ob-tmux--start-terminal-window (ob-session terminal)
"Start a TERMINAL window with tmux attached to session.
Argument OB-SESSION: the current ob-tmux session."
(let* ((process-name (concat "org-babel: terminal")))
Argument OB-SESSION: the current ob-tmux session."
(let ((start-process-mandatory-args `("org-babel: terminal"
"*Messages*"
,terminal))
(tmux-cmd `(,org-babel-tmux-location
"attach-session"
"-t" ,(ob-tmux--target ob-session))))
(unless (ob-tmux--socket ob-session)
(if (string-equal terminal "xterm")
(start-process process-name "*Messages*"
terminal
"-T" (ob-tmux--target ob-session)
"-e" org-babel-tmux-location "attach-session"
"-t" (ob-tmux--target ob-session))
(start-process process-name "*Messages*"
terminal "--"
org-babel-tmux-location "attach-session"
"-t" (ob-tmux--target ob-session))))))
(apply 'start-process (append start-process-mandatory-args
org-babel-tmux-terminal-opts
tmux-cmd)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tmux interaction
@ -198,7 +223,6 @@ Argument OB-SESSION: the current ob-tmux session."
Argument OB-SESSION: the current ob-tmux session."
(unless (ob-tmux--session-alive-p ob-session)
(ob-tmux--execute ob-session
;; TODO: set socket
"new-session"
"-d" ;; just create the session, don't attach.
"-c" (expand-file-name "~") ;; start in home directory
@ -211,7 +235,6 @@ Argument OB-SESSION: the current ob-tmux session."
Argument OB-SESSION: the current ob-tmux session."
(unless (ob-tmux--window-alive-p ob-session)
(ob-tmux--execute ob-session
;; TODO: set socket
"new-window"
"-c" (expand-file-name "~") ;; start in home directory
"-n" (ob-tmux--window-default ob-session)
@ -223,7 +246,6 @@ Argument OB-SESSION: the current ob-tmux session."
Argument OB-SESSION: the current ob-tmux session."
(when (ob-tmux--window-alive-p ob-session)
(ob-tmux--execute ob-session
;; TODO set socket
"set-window-option"
"-t" (ob-tmux--target ob-session)
option value)))
@ -239,17 +261,23 @@ Argument OB-SESSION: the current ob-tmux session."
(ob-tmux--set-window-option ob-session "allow-rename" "off")
(ob-tmux--set-window-option ob-session "automatic-rename" "off")))
(defun ob-tmux--format-keys (string)
"Format STRING as a sequence of hexadecimal numbers, to be sent via the `send-keys' command."
(mapcar (lambda (c) (format "0x%x" c))
string))
(defun ob-tmux--send-keys (ob-session line)
"If tmux window exists, send a LINE of text to it.
Argument OB-SESSION: the current ob-tmux session."
(when (ob-tmux--window-alive-p ob-session)
(ob-tmux--execute ob-session
;; TODO set socket
"send-keys"
"-l"
"-t" (ob-tmux--target ob-session)
line "\n")))
(let* ((hex-line (ob-tmux--format-keys line)))
(apply 'ob-tmux--execute
ob-session
"send-keys"
"-t" (ob-tmux--target ob-session)
hex-line))))
(defun ob-tmux--send-body (ob-session body)
"If tmux window (passed in OB-SESSION) exists, send BODY to it.
@ -257,7 +285,9 @@ Argument OB-SESSION: the current ob-tmux session."
Argument OB-SESSION: the current ob-tmux session."
(let ((lines (split-string body "[\n\r]+")))
(when (ob-tmux--window-alive-p ob-session)
(mapc (lambda (l) (ob-tmux--send-keys ob-session l)) lines))))
(mapc (lambda (l)
(ob-tmux--send-keys ob-session (concat l "\n")))
lines))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Tmux interrogation
@ -289,6 +319,42 @@ If no window is specified in OB-SESSION, returns 't."
't))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Warnings
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun ob-tmux--deprecation-warning (org-header-terminal)
(let* ((message (format "DEPRECATION WARNING: Setting `:terminal` using org source block header arguments is deprecated.
Consider changing your ob-tmux configuration as follows:
(setq org-babel-default-header-args:tmux
'((:results . \"\")
(:session . \"\")
(:terminal. \"%s\") ; <--- REMOVE THIS LINE
(:socket . nil)))
;; You can now customize the terminal and its options as follows:
(setq org-babel-tmux-terminal \"%s\")
(setq org-babel-tmux-terminal-opts '(\"-T\" \"ob-tmux\" \"-e\"))
; The default terminal is \"gnome-terminal\" with options \"--\".
If you have any source blocks containing `:terminal`, please consider removing them:
#+begin_src tmux :session test :terminal %s
echo hello
#+end_src
Becomes:
#+begin_src tmux :session test
echo hello
#+end_src
End of warning. (See *Warnings* buffer for full message)
" org-header-terminal org-header-terminal org-header-terminal)))
(display-warning 'deprecation-warning message :warning)
message))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Test functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;