Use dired-virtual-mode for arbitrary file listings
Emacs’ Dired is a powerful file manager that builds its functionality on top of the Unix ‘ls’ command. As noted elsewhere in this manual, the user can update the ‘ls’ flags that Dired uses to display its contents (I want to sort by last modified, why won’t Denote let me?).
What Dired cannot do is parse the output of a result that is produced by piped commands, such as ‘ls -l | sort -t _ -k2’. This specific example targets the second underscore-separated field of the file name, per our conventions (The file-naming scheme). Conceretely, it matches the “alpha” as the sorting key in something like this:
20220929T200432--testing-file-one__alpha.txtConsider then, how Dired will sort those files by their identifier:
20220929T200432--testing-file-one__alpha.txt
20220929T200532--testing-file-two__beta.txt
20220929T200632--testing-file-three__alpha.txt
20220929T200732--testing-file-four__beta.txtWhereas on the command line, we can get the following:
$ ls | sort -t _ -k 2
20220929T200432--testing-file-one__alpha.txt
20220929T200632--testing-file-three__alpha.txt
20220929T200532--testing-file-two__beta.txt
20220929T200732--testing-file-four__beta.txtThis is where dired-virtual-mode shows its utility. If we tweak our command-line invocation to include ‘ls -l’, this mode can behave like Dired on the listed files. (We omit the output of the ‘-l’ flag from this tutorial, as it is too verbose.)
What we now need is to capture the output of ‘ls -l | sort -t _ -k 2’ in an Emacs buffer and then enable dired-virtual-mode. To do that, we can rely on either ‘M-x shell’ or ‘M-x eshell’ and then manually copy the relevant contents.
For the user’s convenience, I share what I have for Eshell to quickly capture the last command’s output in a dedicated buffer:
(defcustom prot-eshell-output-buffer "*Exported Eshell output*"
"Name of buffer with the last output of Eshell command.
Used by `prot-eshell-export'."
:type 'string
:group 'prot-eshell)
(defcustom prot-eshell-output-delimiter "* * *"
"Delimiter for successive `prot-eshell-export' outputs.
This is formatted internally to have newline characters before
and after it."
:type 'string
:group 'prot-eshell)
(defun prot-eshell--command-prompt-output ()
"Capture last command prompt and its output."
(let ((beg (save-excursion
(goto-char (eshell-beginning-of-input))
(goto-char (point-at-bol)))))
(when (derived-mode-p 'eshell-mode)
(buffer-substring-no-properties beg (eshell-end-of-output)))))
;;;###autoload
(defun prot-eshell-export ()
"Produce a buffer with output of the last Eshell command.
If `prot-eshell-output-buffer' does not exist, create it. Else
append to it, while separating multiple outputs with
`prot-eshell-output-delimiter'."
(interactive)
(let ((eshell-output (prot-eshell--command-prompt-output)))
(with-current-buffer (get-buffer-create prot-eshell-output-buffer)
(let ((inhibit-read-only t))
(goto-char (point-max))
(unless (eq (point-min) (point-max))
(insert (format "\n%s\n\n" prot-eshell-output-delimiter)))
(goto-char (point-at-bol))
(insert eshell-output)
(switch-to-buffer-other-window (current-buffer))))))Bind prot-eshell-export to a key in the eshell-mode-map and give it a try (I use ‘C-c C-e’). In the produced buffer, activate the dired-virtual-mode.