branch: externals/dtache
commit d0b0ed41e2247d0edd369e75efae6bafbad7c2be
Author: Niklas Eklund <[email protected]>
Commit: Niklas Eklund <[email protected]>
Merge develop branch into master
---
.dir-locals.el | 3 +-
README.org | 50 ++++++++----
dtache-shell.el | 52 +++++++++----
dtache.el | 172 +++++++++++++++++++++++++++++++++--------
embark-dtache.el | 2 +
marginalia-dtache.el | 10 +--
test/dtache-test.el | 36 +++++++--
test/marginalia-dtache-test.el | 8 +-
8 files changed, 253 insertions(+), 80 deletions(-)
diff --git a/.dir-locals.el b/.dir-locals.el
index 2115bd6105..846a89e9bf 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -1,2 +1,3 @@
((nil . ((compile-command . "guix build --file=guix.scm")))
- (prog-mode (eval flycheck-mode)))
+ (prog-mode (eval flycheck-mode))
+ (magit-status-mode (magit-todos-exclude-globs)))
diff --git a/README.org b/README.org
index 09f9924ece..925a967d30 100644
--- a/README.org
+++ b/README.org
@@ -7,15 +7,9 @@
:description: Why Dtache?
:end:
- =Dtache= allows a program to be seamlessly executed in an
- environment that is isolated from =Emacs= which made possible by the
- [[https://github.com/crigler/dtach][dtach]] program. This package makes sure
that, even though programs
- are running in isolated sessions, they get tightly integrated with
- Emacs.
+ =Dtache= allows a program to be seamlessly executed in an environment that
is isolated from =Emacs= which made possible by the
[[https://github.com/crigler/dtach][dtach]] program. This package makes sure
that, even though programs are running in isolated sessions, they get tightly
integrated with Emacs.
- The =dtache= package is split up into two, =dtache.el= and
- =dtache-shell.el=. The former provides the backend implementation,
- whilst the former provides the integration with =M-x shell=.
+ The =dtache= package is split up into two, =dtache.el= and
=dtache-shell.el=. The former provides the backend implementation, whilst the
former provides the integration with =M-x shell=.
** Screenshots
@@ -34,8 +28,13 @@ Configuration for the =dtache= package. This package
provides the backend for =d
(setq dtache-db-directory (no-littering-expand-var-file-name "dtache"))
(setq dtache-session-directory (expand-file-name "dtache"
(temporary-file-directory)))
(setq dtache-shell-history-file "~/.bash_history")
+
(general-def '(motion normal) dtache-log-mode-map
- "q" #'quit-window))
+ "q" #'kill-buffer-and-window)
+ (general-def '(motion normal) dtache-tail-mode-map
+ "q" #'dtache-quit-tail-log)
+
+ (add-to-list 'recentf-exclude (rx (regexp "dtache.*\.log"))))
#+end_src
*** Dtache-shell
@@ -47,9 +46,8 @@ Configuration for the =dtache-shell= package. This package
provides the integrat
:hook (shell-mode . dtache-shell-mode)
:config
(general-def dtache-shell-mode-map
- "<return>" #'dtache-shell-send-input
"<S-return>" #'dtache-shell-create
- "<C-return>" #'dtache-shell-attach
+ "<C-return>" #'dtache-tail-log
"C-c C-q" #'dtache-shell-detach))
#+end_src
@@ -90,6 +88,24 @@ The =dtache= package supports
[[https://www.gnu.org/software/emacs/manual/html_n
'(:application tramp :protocol "ssh") 'remote-dtache)
#+end_src
+** Degraded mode
+
+Occasionally the =dtache= user might run into shell commands that don't play
well with the package. The symptom is that the logs are not updated until the
session finish, which removes a lot of the use-case for dtache. To mitigate the
problem dtache can be instructed to run in a degraded mode for those commands.
This is done by adding a regexp that matches the troublesome command and add it
to the list =dtache-degraded-list=.
+
+#+begin_src elisp
+ (setq dtache-degraded-list '("foo"))
+#+end_src
+
+In degraded mode =dtache= will skip the usage of =tee= and instead redirect
all the outputs to the dtache log. Use =dtache-tail-log= to tail the output
from the session. It's still possible to attach in the terminal but there is no
output forwarded to it.
+
+** Notification
+
+Make =dtache= send a notification once a session is finished. This would only
make sense to add for sessions on the localhost. Add the following advice to
the config.
+
+#+begin_src elisp
+ (advice-add 'dtache-session-command :override
#'dtache-session-notify-command)
+#+end_src
+
* Commands
The following is a list of commands that can be run on =dtache= sessions.
@@ -98,12 +114,12 @@ The following is a list of commands that can be run on
=dtache= sessions.
Commands to be used in shell buffers.
-| Command | Description |
-|-------------------------+--------------------------------------------------|
-| dtache-shell-create | Create a session |
-| dtache-shell-attach | Attach to a session |
-| dtache-shell-detach | Detach from a session |
-| dtache-shell-send-input | Optionally create a session with prefix argument |
+| Command | Description |
+|-------------------------+-----------------------------|
+| dtache-shell-send-input | Optionally create a session |
+| dtache-shell-create | Create a session |
+| dtache-shell-attach | Attach to a session |
+| dtache-shell-detach | Detach from a session |
** Dtache
diff --git a/dtache-shell.el b/dtache-shell.el
index af149f0b95..8453ad5339 100755
--- a/dtache-shell.el
+++ b/dtache-shell.el
@@ -39,6 +39,10 @@
"A list of regexps to block non-supported input.")
(defvar dtache-shell-silence-dtach-messages t
"Filter out messages from the `dtach' program.")
+(defvar dtache-shell-create-primary-function #'dtache-shell-new-session
+ "Primary function for creating a session.")
+(defvar dtache-shell-create-secondary-function #'dtache-shell-create-session
+ "Secondary function for creating a session.")
;;;; Functions
@@ -63,14 +67,33 @@
Optionally CREATE-SESSION with prefix argument."
(interactive "P")
(if create-session
- (dtache-shell-create)
+ (funcall dtache-shell-create-primary-function)
(comint-send-input)))
;;;###autoload
-(defun dtache-shell-create ()
- "Create a session."
+(defun dtache-shell-create (&optional secondary)
+ "Create a new session with `dtache-shell-create-primary-function'.
+
+If prefix argument SECONDARY call `dtache-shell-create-secondary-function'."
+ (interactive "P")
+ (if secondary
+ (funcall dtache-shell-create-secondary-function)
+ (funcall dtache-shell-create-primary-function)))
+
+;;;###autoload
+(defun dtache-shell-create-session ()
+ "Create a session and attach to it."
+ (interactive)
+ (let* ((dtache--dtach-mode "-c")
+ (comint-input-sender #'dtache-shell--create-input-sender))
+ (comint-send-input)))
+
+;;;###autoload
+(defun dtache-shell-new-session ()
+ "Create a new session."
(interactive)
- (let ((comint-input-sender #'dtache-shell--create-input-sender))
+ (let ((dtache--dtach-mode "-n")
+ (comint-input-sender #'dtache-shell--create-input-sender))
(comint-send-input)))
;;;###autoload
@@ -89,25 +112,28 @@ Optionally CREATE-SESSION with prefix argument."
cluttering the comint-history with dtach commands."
(interactive
(list (dtache-select-session)))
- (if (dtache--session-active-p session)
- (cl-letf ((dtache--current-session session)
- (comint-input-sender #'dtache-shell--attach-input-sender)
- ((symbol-function 'comint-add-to-input-history) (lambda (_)
t)))
- (comint-kill-input)
- (comint-send-input))
- (funcall dtache-attach-alternate-function session)))
+ (cl-letf ((dtache--current-session session)
+ (comint-input-sender #'dtache-shell--attach-input-sender)
+ ((symbol-function 'comint-add-to-input-history) (lambda (_) t)))
+ (comint-kill-input)
+ (comint-send-input)))
;;;; Support functions
+(cl-defmethod dtache--attach-to-session (session &context (major-mode
shell-mode))
+ "Attach to a dtache SESSION when MAJOR-MODE is `shell-mode'."
+ (dtache-shell-attach session))
+
(defun dtache-shell--attach-input-sender (proc _string)
"Attach to `dtache--session' and send the attach command to PROC."
- (let* ((socket
+ (let* ((dtache--dtach-mode "-a")
+ (socket
(concat
(dtache--session-session-directory dtache--current-session)
(dtache--session-id dtache--current-session)
dtache-socket-ext))
(input
- (concat dtache-program " -a " socket)))
+ (concat dtache-program " " dtache--dtach-mode " " socket)))
(comint-simple-send proc input)))
(defun dtache-shell--create-input-sender (proc string)
diff --git a/dtache.el b/dtache.el
index ce7b567cb9..ce963f4e36 100644
--- a/dtache.el
+++ b/dtache.el
@@ -40,6 +40,7 @@
(require 'emacsql-sqlite)
(require 'tramp-sh)
+(require 'autorevert)
;;;; Variables
@@ -53,7 +54,7 @@
"The `dtach' program.")
(defvar dtache-shell "bash"
"Shell to run the dtach command in.")
-(defvar dtache-metadata-annotators '((:git . dtache--session-git-branch))
+(defvar dtache-metadata-annotators '((:git-branch .
dtache--session-git-branch))
"An alist of annotators for metadata.")
(defvar dtache-max-command-length 95
"Maximum length of displayed command.")
@@ -76,9 +77,14 @@
"Message printed when `dtach' finishes.")
(defconst dtache-detach-character "\C-\\"
"Character used to detach from a session.")
+(defvar dtache-degraded-list '()
+ "Regexps that should run in dedgraded mode.")
+(defvar dtache-tail-interval 2
+ "Interval in seconds for dtache to tail.")
;;;;; Private
+(defvar dtache--dtach-mode nil "Mode of operation.")
(defvar dtache--session-candidates nil "An alist of session candidates.")
(defvar dtache--current-session nil "The current session.")
@@ -93,9 +99,9 @@
(session-directory nil :read-only t)
(metadata nil :read-only t)
(host nil :read-only t)
+ (degraded nil :read-only t)
(duration nil)
(log-size nil)
- (stderr-p nil)
(active nil))
;;;; Functions
@@ -202,21 +208,38 @@ This function also makes sure that the HISTFILE is
disabled for local shells."
(defun dtache-dtach-command (session)
"Return a dtach command for SESSION."
- (let* ((command (dtache-session-command session))
- (directory (dtache--session-session-directory session))
+ (let* ((directory (dtache--session-session-directory session))
(file-name (dtache--session-id session))
- (stdout (concat directory file-name dtache-stdout-ext))
- (stderr (concat directory file-name dtache-stderr-ext))
- (log (concat directory file-name dtache-log-ext))
(socket (concat directory file-name dtache-socket-ext))
;; Construct the command line
- ;; { { echo stdout; echo stderr >&2; } >>(tee stdout ); } 2>>(tee
stderr) | tee log
- (commandline (format "{ { %s; }%s }%s %s"
- (format "%s" command)
- (format " > >(tee %s );" stdout)
- (format " 2> >(tee %s )" stderr)
- (format " | tee %s" log))))
- (format "%s -c %s -z %s -c %s" dtache-program socket dtache-shell
(shell-quote-argument commandline))))
+ (commandline (dtache--output-command session))
+ (dtach-mode (if (dtache--session-degraded session)
+ "-n"
+ dtache--dtach-mode)))
+ (format "%s %s %s -z %s -c %s" dtache-program dtach-mode socket
dtache-shell (shell-quote-argument commandline))))
+
+(defun dtache-degraded-p (command)
+ "Return t if COMMAND should run in degreaded mode."
+ (if (thread-last dtache-degraded-list
+ (seq-filter (lambda (regexp)
+ (string-match-p regexp command)))
+ (length)
+ (= 0))
+ nil
+ t))
+
+(defun dtache-session-notify-command (session)
+ "Append notify-send to SESSION's command."
+ (let* ((command (dtache--session-command session))
+ (emacs-icon
+ (concat data-directory
+ "images/icons/hicolor/scalable/apps/emacs.svg")))
+ (if (file-remote-p default-directory)
+ command
+ (concat
+ command
+ (format " && notify-send \"Dtache finished: %s\"" command)
+ (format " --icon %s" emacs-icon)))))
(defun dtache-metadata ()
"Return a property list with metadata."
@@ -265,7 +288,7 @@ This function also makes sure that the HISTFILE is disabled
for local shells."
(with-current-buffer (get-buffer-create buffer-name)
(setq-local buffer-read-only nil)
(erase-buffer)
- (insert-file-contents file )
+ (insert-file-contents file)
(setq-local default-directory
(dtache--session-working-directory session))
(compilation-mode))
@@ -321,6 +344,15 @@ This function also makes sure that the HISTFILE is
disabled for local shells."
(list (dtache-select-session)))
(dtache--open-file session 'log))
+;;;###autoload
+(defun dtache-tail-log (session)
+ "Tail SESSION's log."
+ (interactive
+ (list (dtache-select-session)))
+ (if (dtache--session-active-p session)
+ (dtache--tail-file session 'log)
+ (dtache--open-file session 'log)))
+
;;;###autoload
(defun dtache-open-stdout (session)
"Open SESSION's stdout."
@@ -335,16 +367,40 @@ This function also makes sure that the HISTFILE is
disabled for local shells."
(list (dtache-select-session)))
(dtache--open-file session 'stderr))
+;;;###autoload
+(defun dtache-attach-to-session (session)
+ "Attach to SESSION."
+ (interactive
+ (list (dtache-select-session)))
+ (if (dtache--session-active-p session)
+ (dtache--attach-to-session session)
+ (funcall dtache-attach-alternate-function session)))
+
+;;;###autoload
+(defun dtache-quit-tail-log ()
+ "Quit `dtache' tail log.
+
+The log can have been updated, but that is not done by the user but
+rather the tail mode. To avoid a promtp `buffer-modified-p' is set to
+nil before closing."
+ (interactive)
+ (set-buffer-modified-p nil)
+ (kill-buffer-and-window))
+
;;;; Support functions
;;;;; Session
+(cl-defgeneric dtache--attach-to-session (session)
+ "Attach to SESSION.")
+
(defun dtache--create-session (command)
"Create a `dtache' session from COMMAND."
(let ((session
(dtache--session-create :id (dtache--create-id command)
:command command
:working-directory default-directory
+ :degraded (dtache-degraded-p command)
:creation-time (time-to-seconds
(current-time))
:session-directory (file-name-as-directory
dtache-session-directory)
:host (dtache--host)
@@ -399,10 +455,6 @@ This function also makes sure that the HISTFILE is
disabled for local shells."
(setf (dtache--session-log-size session) (file-attribute-size
(file-attributes
(dtache-session-file session
'log))))
- (setf (dtache--session-stderr-p session) (> (file-attribute-size
- (file-attributes
- (dtache-session-file session
'stderr)))
- 0))
session)
(defun dtache--session-git-branch ()
@@ -512,6 +564,38 @@ This function also makes sure that the HISTFILE is
disabled for local shells."
;;;;; Other
+(defun dtache--output-command (session)
+ "Return output command for SESSION."
+ (if (dtache--session-degraded session)
+ (dtache--output-to-file-command session)
+ (dtache--output-to-both-command session)))
+
+(defun dtache--output-to-file-command (session)
+ "Return a command to send SESSION's output directly to log."
+ (let* ((command (dtache-session-command session))
+ (directory (dtache--session-session-directory session))
+ (file-name (dtache--session-id session))
+ (log (concat directory file-name dtache-log-ext)))
+ ;; Construct the command line
+ ;; echo &> log
+ (format "{ %s; } &> %s" command log)))
+
+(defun dtache--output-to-both-command (session)
+ "Return a command to send SESSION's output to both shell and log."
+ (let* ((command (dtache-session-command session))
+ (directory (dtache--session-session-directory session))
+ (file-name (dtache--session-id session))
+ (stdout (concat directory file-name dtache-stdout-ext))
+ (stderr (concat directory file-name dtache-stderr-ext))
+ (log (concat directory file-name dtache-log-ext)))
+ ;; Construct the command line
+ ;; { { echo stdout; echo stderr >&2; } >>(tee stdout ); } 2>>(tee
stderr) | tee log
+ (format "{ { %s; }%s }%s %s"
+ (format "%s" command)
+ (format " > >(tee %s );" stdout)
+ (format " 2> >(tee %s )" stderr)
+ (format " | tee %s" log))))
+
(defun dtache--host ()
"Return name of host."
(if-let ((remote-host (file-remote-p default-directory))
@@ -532,8 +616,8 @@ This function also makes sure that the HISTFILE is disabled
for local shells."
Modification time is not reliable whilst a session is active. Instead
the current time is used."
- ;; TODO: This function might need to take into account that there
- ;; might be a time offset between two computers
+ ;; TODO: Consider calculating a time offset between host and remote
+ ;; computer
(if (dtache--session-active session)
(- (time-to-seconds) (dtache--session-creation-time session))
(- (time-to-seconds
@@ -544,33 +628,55 @@ the current time is used."
(defun dtache--open-file (session file)
"Oen SESSION's FILE."
- (let* ((buffer-name
- (format "*dtache-%s-%s*" file
- (dtache--session-short-id session)))
- (file-path
+ (let* ((file-path
+ (dtache-session-file session file)))
+ (if (file-exists-p file-path)
+ (progn
+ (find-file-other-window file-path)
+ (setq-local default-directory (dtache--session-working-directory
session))
+ (dtache-log-mode)
+ (goto-char (point-max)))
+ (message "Dtache can't find file: %s" file-path))))
+
+(defun dtache--tail-file (session file)
+ "Tail SESSION's FILE."
+ (let* ((file-path
(dtache-session-file session file)))
(when (file-exists-p file-path)
- (with-current-buffer (get-buffer-create buffer-name)
- (erase-buffer)
- (insert-file-contents file-path)
- (setq-local default-directory (dtache--session-working-directory
session)))
- (pop-to-buffer buffer-name)
- (dtache-log-mode))))
+ (find-file-other-window file-path)
+ (dtache-tail-mode)
+ (goto-char (point-max)))))
(defun dtache--create-id (command)
"Return a hash identifier for COMMAND."
(let ((current-time (current-time-string)))
- (secure-hash 'md5 (concat command current-time))))
+ (secure-hash 'md5 (concat command current-time))))
;;;; Major mode
(defvar dtache-log-mode-map
(let ((map (make-sparse-keymap)))
+ (define-key map (kbd "q") #'kill-buffer-and-window)
map)
"Keymap for `dtache-log-mode'.")
(define-derived-mode dtache-log-mode nil "Dtache Log"
- "Major mode for dtache logs.")
+ "Major mode for dtache logs."
+ (read-only-mode t))
+
+(defvar dtache-tail-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "q") #'dtache-quit-tail-log)
+ map)
+ "Keymap for `dtache-tail-mode'.")
+
+(define-derived-mode dtache-tail-mode auto-revert-tail-mode "Dtache Tail"
+ "Major mode for tailing dtache logs."
+ (setq-local auto-revert-interval dtache-tail-interval)
+ (auto-revert-set-timer)
+ (setq-local auto-revert-verbose nil)
+ (auto-revert-tail-mode)
+ (read-only-mode t))
(provide 'dtache)
diff --git a/embark-dtache.el b/embark-dtache.el
index 71dcde4adc..7e308d62c6 100644
--- a/embark-dtache.el
+++ b/embark-dtache.el
@@ -38,7 +38,9 @@
(embark-define-keymap embark-dtache-map
"Keymap for Embark dtache actions."
+ ("a" dtache-attach-to-session)
("l" dtache-open-log)
+ ("t" dtache-tail-log)
("e" dtache-open-stderr)
("o" dtache-open-stdout)
("i" dtache-insert-session-command)
diff --git a/marginalia-dtache.el b/marginalia-dtache.el
index 612d3af8e7..cac5694fac 100644
--- a/marginalia-dtache.el
+++ b/marginalia-dtache.el
@@ -79,7 +79,7 @@
(let* ((session (dtache-decode-session candidate)))
(marginalia--fields
((marginalia-dtache--active session) :width 3 :face
'marginalia-dtache-active)
- ((marginalia-dtache--stderr-p session) :width 3 :face
'marginalia-dtache-error)
+ ((marginalia-dtache--degraded session) :width 3 :face
'marginalia-dtache-error)
((marginalia-dtache--git-branch session) :truncate
marginalia-dtache-git-branch-length :face 'marginalia-dtache-git)
((marginalia-dtache--duration session) :truncate
marginalia-dtache-duration-length :face 'marginalia-dtache-duration)
((marginalia-dtache--size session) :truncate
marginalia-dtache-size-length :face 'marginalia-dtache-size)
@@ -110,7 +110,7 @@
(defun marginalia-dtache--git-branch (session)
"Return the git branch for SESSION."
- (plist-get (dtache--session-metadata session) :git))
+ (plist-get (dtache--session-metadata session) :git-branch))
(defun marginalia-dtache--active (session)
"Return string if SESSION is active."
@@ -118,9 +118,9 @@
"*"
""))
-(defun marginalia-dtache--stderr-p (session)
- "Return string if SESSION has errors."
- (if (dtache--session-stderr-p session)
+(defun marginalia-dtache--degraded (session)
+ "Return string if SESSION is degraded."
+ (if (dtache--session-degraded session)
"!"
""))
diff --git a/test/dtache-test.el b/test/dtache-test.el
index e48e11ad3e..5dd7ffc0e4 100644
--- a/test/dtache-test.el
+++ b/test/dtache-test.el
@@ -70,13 +70,15 @@
;;;; Tests
(ert-deftest dtache-test-dtach-command ()
- (let* ((dtache-shell "zsh")
- (dtache-program "/usr/bin/dtach")
- (actual
- (dtache-dtach-command
- (dtache--session-create :id "12345" :session-directory
"/tmp/dtache/")))
- (expected "^/usr/bin/dtach -c /tmp/dtache/12345.socket -z zsh -c .*"))
- (should (string-match-p expected actual))))
+ (cl-letf* (((symbol-function #'dtache--output-command) (lambda (_)
"command"))
+ (dtache-shell "zsh")
+ (dtache-program "/usr/bin/dtach")
+ (dtache--dtach-mode "-c")
+ (actual
+ (dtache-dtach-command
+ (dtache--session-create :id "12345" :session-directory
"/tmp/dtache/")))
+ (expected "/usr/bin/dtach -c /tmp/dtache/12345.socket -z zsh -c
command"))
+ (should (string= expected actual))))
(ert-deftest dtache-test-metadata ()
;; No annotators
@@ -251,6 +253,26 @@
(should (= (length sessions) 1))
(should (string= (dtache--session-id (elt sessions 0))
(dtache--session-id session3)))))))
+(ert-deftest dtache-test-output-command ()
+ ;; Degraded
+ (let* ((actual
+ (dtache--output-command
+ (dtache--session-create :id "12345" :session-directory
"/tmp/dtache/" :command "ls" :degraded t)))
+ (expected "{ ls; } &> /tmp/dtache/12345.log"))
+ (should (string= actual expected)))
+
+ ;; Normal
+ (let* ((actual
+ (dtache--output-command
+ (dtache--session-create :id "12345" :session-directory
"/tmp/dtache/" :command "ls")))
+ (expected "{ { ls; } > >(tee /tmp/dtache/12345.stdout ); } 2> >(tee
/tmp/dtache/12345.stderr ) | tee /tmp/dtache/12345.log"))
+ (should (string= actual expected))))
+
+(ert-deftest dtache-test-degraded-p ()
+ (let ((dtache-degraded-list '("ls")))
+ (should (not (dtache-degraded-p "cd")))
+ (should (dtache-degraded-p "ls -la"))))
+
(provide 'dtache-test)
;;; dtache-test.el ends here
diff --git a/test/marginalia-dtache-test.el b/test/marginalia-dtache-test.el
index 913f087ec7..6c8c9abb14 100644
--- a/test/marginalia-dtache-test.el
+++ b/test/marginalia-dtache-test.el
@@ -45,16 +45,16 @@
(should (string= "1k" (marginalia-dtache--size (dtache--session-create
:log-size 1024)))))
(ert-deftest marginalia-dtache-git ()
- (should (string= "foo" (marginalia-dtache--git-branch
(dtache--session-create :metadata '(:git "foo")))))
+ (should (string= "foo" (marginalia-dtache--git-branch
(dtache--session-create :metadata '(:git-branch "foo")))))
(should (not (marginalia-dtache--git-branch (dtache--session-create)))))
(ert-deftest marginalia-dtache-active ()
(should (string= "*" (marginalia-dtache--active (dtache--session-create
:active t))))
(should (string= "" (marginalia-dtache--active (dtache--session-create
:active nil)))))
-(ert-deftest marginalia-dtache-stderr-p ()
- (should (string= "!" (marginalia-dtache--stderr-p (dtache--session-create
:stderr-p t))))
- (should (string= "" (marginalia-dtache--stderr-p (dtache--session-create
:stderr-p nil)))))
+(ert-deftest marginalia-dtache-degraded ()
+ (should (string= "!" (marginalia-dtache--degraded (dtache--session-create
:degraded t))))
+ (should (string= "" (marginalia-dtache--degraded (dtache--session-create
:degraded nil)))))
(provide 'marginalia-dtache-test)