Files
emacs/lisp/dirvish/dirvish-ls.el

184 lines
7.8 KiB
EmacsLisp

;;; dirvish-ls.el --- Setup ls command switches on the fly -*- lexical-binding: t -*-
;; Copyright (C) 2021-2025 Alex Lu
;; Author : Alex Lu <https://github.com/alexluigit>
;; Keywords: files, convenience
;; Homepage: https://github.com/alexluigit/dirvish
;; SPDX-License-Identifier: GPL-3.0-or-later
;;; Commentary:
;; Setup ls command switches on the fly.
;;; Code:
(require 'dirvish)
(require 'transient)
(defun dirvish-ls--clear-switches-choices ()
"Reload the listing switches setup UI."
(interactive)
(transient-setup 'dirvish-ls-switches-menu))
(defun dirvish-ls--apply-switches-to-buffer (&optional switches)
"Apply listing SWITCHES to current buffer."
(interactive)
(let* ((args (transient-args transient-current-command))
(switches (or switches (string-join (append '("-l") args) " "))))
(when current-prefix-arg (setq dired-listing-switches switches))
(setq dired-actual-switches switches)
(revert-buffer)))
(defun dirvish-ls--apply-switches-to-all (&optional switches)
"Apply listing SWITCHES to current session."
(interactive)
(let* ((args (transient-args transient-current-command))
(switches (or switches (string-join (append '("-l") args) " "))))
(when current-prefix-arg (setq dired-listing-switches switches))
(setf (dv-ls-switches (dirvish-curr)) switches)
(dolist (buf (cl-remove-if-not
(lambda (b) (with-current-buffer b (derived-mode-p 'dired-mode))) (buffer-list)))
(with-current-buffer buf
(setq dired-actual-switches switches)
(revert-buffer)))))
(defun dirvish-ls--reset-switches-for-buffer ()
"Reset listing switches for current buffer."
(interactive)
(dirvish-ls--apply-switches-to-buffer dired-listing-switches))
(defun dirvish-ls--reset-switches-for-all ()
"Reset listing switches for current buffer."
(interactive)
(dirvish-ls--apply-switches-to-all dired-listing-switches))
(transient-define-infix dirvish-ls--filter-switch ()
:description "show all files"
:class 'transient-switches
:argument-format "--%s"
:argument-regexp "\\(--\\(all\\|almost-all\\)\\)"
:choices '("all" "almost-all"))
(transient-define-infix dirvish-ls--sort-switch ()
:description "sort by"
:class 'transient-switches
:argument-format "--sort=%s"
:argument-regexp "\\(--sort=\\(time\\|none\\|extension\\|size\\|version\\|width\\)\\)"
:choices '("time" "none" "extension" "size" "version" "width"))
(transient-define-infix dirvish-ls--time-switch ()
:description "show time as | sort files with"
:class 'transient-switches
:argument-format "--time=%s"
:argument-regexp "\\(--time=\\(use\\|birth\\|ctime\\)\\)"
:choices '("use" "birth" "ctime"))
(transient-define-infix dirvish-ls--time-style-switch ()
:description "time style"
:class 'transient-switches
:argument-format "--time-style=%s"
:argument-regexp "\\(--time-style=\\(full-iso\\|long-iso\\|iso\\|locale\\|+\\)\\)"
:choices '("full-iso" "long-iso" "iso" "locale" "+"))
(transient-define-infix dirvish-ls--indicator-style-switch ()
:description "add indicator"
:class 'transient-switches
:argument-format "--indicator-style=%s"
:argument-regexp "\\(--indicator-style=\\(slash\\|file-type\\|classify\\)\\)"
:choices '("slash" "file-type" "classify"))
(defun dirvish-ls--quicksort-do-sort (switches)
"Sort current buffer with Dired sort SWITCHES."
(let* ((regexp "\\(--time=\\w+\\|--sort=\\w+\\|--reverse\\)\\( \\)?")
(others (replace-regexp-in-string regexp "" dired-actual-switches))
(new-switches (concat others " " switches)))
(setq dired-actual-switches new-switches)
(revert-buffer)))
;;;###autoload (autoload 'dirvish-quicksort "dirvish-ls" nil t)
(defcustom dirvish-ls-quicksort-keys
'(("n" "" "name (a-z)")
("N" "--reverse" "name (z-a)")
("e" "--sort=extension" "extension (a-z)")
("E" "--sort=extension --reverse" "extension (z-a)")
("s" "--sort=size" "size (largest first)")
("S" "--sort=size --reverse" "size (smallest first)")
("v" "--sort=version" "version number (earliest first)")
("V" "--sort=version --reverse" "version number (latest first)")
("w" "--sort=width" "width (shortest first)")
("W" "--sort=width --reverse" "width (longest first)")
("m" "--sort=time" "modification time (newest first)")
("M" "--sort=time --reverse" "modification time (oldest first)")
("a" "--sort=time --time=use" "access time (newest first)")
("A" "--sort=time --time=use --reverse" "access time (oldest first)")
("b" "--sort=time --time=birth" "birth time (newest first)")
("B" "--sort=time --time=birth --reverse" "birth time (oldest first)")
("c" "--sort=time --time=ctime" "change time (newest first)")
("C" "--sort=time --time=ctime --reverse" "change time (oldest first)"))
"SORT-KEYs for command `dirvish-quicksort'.
A SORT-KEY is a (KEY SWITCHES DOC) alist where KEY is the key to
invoke the sort function, SWITCHES is the the sort flags for
`dired-sort-other', DOC is the documentation string."
:group 'dirvish :type 'alist
:set
(lambda (k v)
(set k v)
(eval
`(transient-define-prefix dirvish-quicksort ()
"Sort Dirvish buffer by different criteria."
[:description
(lambda () (dirvish--format-menu-heading "Sort by:"))
,@(cl-loop
for (key switches desc) in v collect
(list key desc `(lambda ()
(interactive)
(dirvish-ls--quicksort-do-sort ,switches))))]))))
;;;###autoload (autoload 'dirvish-ls-switches-menu "dirvish-ls" nil t)
(transient-define-prefix dirvish-ls-switches-menu ()
"Setup Dired listing switches."
:init-value
(lambda (o) (oset o value (split-string (or dired-actual-switches ""))))
[:description
(lambda ()
(format "%s\n%s %s\n%s %s"
(propertize "Setup Listing Switches"
'face '(:inherit dired-mark :underline t)
'display '((height 1.2)))
(propertize "lowercased switches also work in" 'face 'font-lock-doc-face)
(propertize "dired-hide-details-mode" 'face 'font-lock-constant-face)
(propertize "C-u RET and C-u M-RET will modify" 'face 'font-lock-doc-face)
(propertize "dired-listing-switches" 'face 'font-lock-constant-face)))
["options"
("a" dirvish-ls--filter-switch)
("s" dirvish-ls--sort-switch)
("i" dirvish-ls--indicator-style-switch)
("t" dirvish-ls--time-switch)
("T" dirvish-ls--time-style-switch)
("B" "Scale sizes when printing, eg. 10K" "--block-size=")
""
"toggles"
("r" "Reverse order while sorting" "--reverse")
("d" "List directories on top" "--group-directories-first")
("~" "Hide backups files (eg. foo~)" "--ignore-backups")
("A" "Show the author" "--author")
("C" "Show security context" "--context")
("H" "Human readable file size" "--human-readable")
("G" "Hide group names" "--no-group")
("O" "Hide owner names" "-g")
("L" "Info for link references or link itself" "--dereference")
("N" "Numeric user and group IDs" "--numeric-uid-gid")
("P" "Powers of 1000 for file size rather than 1024" "--si")
("I" "Show index number" "--inode")
("S" "Show the allocated size" "--size")
""
"Actions"
("RET" " Apply to this buffer" dirvish-ls--apply-switches-to-buffer)
("M-RET" "Apply to all Dired buffers" dirvish-ls--apply-switches-to-all)
("C-r" " Reset this buffer" dirvish-ls--reset-switches-for-buffer)
("M-r" " Reset all Dired buffers" dirvish-ls--reset-switches-for-all)
("C-l" " Clear choices" dirvish-ls--clear-switches-choices :transient t)]])
(provide 'dirvish-ls)
;;; dirvish-ls.el ends here