home

My NixOS systems configurations.
Log | Files | Refs | LICENSE

commit 8f6164aeec88d61918b49ee11ce17ac850a2f29c
parent 9fbbcb78fafa1eb9f78e1ac094e165ee855cf2cc
Author: Vincent Demeester <vincent@sbr.pm>
Date:   Fri, 26 Jan 2024 11:37:42 +0100

tools/emacs: dired transient menu and org-search-from-sacha functions :)

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Diffstat:
Mtools/emacs/config/config-dired.el | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtools/emacs/config/config-org.el | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 197 insertions(+), 0 deletions(-)

diff --git a/tools/emacs/config/config-dired.el b/tools/emacs/config/config-dired.el @@ -233,5 +233,147 @@ This relies on the external 'fd' executable." (setq dired-sidebar-theme 'arrow) (setq dired-sidebar-use-term-integration t)) +(require 'transient) +(require 'easymenu) + +(defcustom cc-dired-listing-switches '("--human-readable" + "--group-directories-first" + "--time-style=long-iso") + "List of GNU ls arguments used by the function `cc/--dired-sort-by'. + +This variable requires GNU ls from coreutils installed.\n +See the man page `ls(1)' for details." + :type '(repeat string) + :group 'dired) + +(transient-define-prefix cc/dired-sort-by () + "Transient menu to sort Dired buffer by different criteria. + +This function requires GNU ls from coreutils installed." + :value '("--human-readable" + "--group-directories-first" + "--time-style=long-iso") + ; TODO: support cc-dired-listing-switches + [["Arguments" + ("-a" "all" "--all") + ("g" "group directories first" "--group-directories-first") + ("-r" "reverse" "--reverse") + ("-h" "human readable" "--human-readable") + ("t" "time style" "--time-style=" + :choices ("full-iso" "long-iso" "iso" "locale"))] + + ["Sort By" + ("n" + "Name" + (lambda () (interactive) + (cc/--dired-sort-by :name + (transient-args transient-current-command))) + :transient nil) + ("k" + "Kind" + (lambda () (interactive) + (cc/--dired-sort-by :kind + (transient-args transient-current-command))) + :transient nil) + ("l" + "Date Last Opened" + (lambda () (interactive) + (cc/--dired-sort-by :date-last-opened + (transient-args transient-current-command))) + :transient nil) + ("a" + "Date Added" + (lambda () (interactive) + (cc/--dired-sort-by :date-added + (transient-args transient-current-command))) + :transient nil) + ("m" + "Date Modified" + (lambda () (interactive) + (cc/--dired-sort-by :date-modified + (transient-args transient-current-command))) + :transient nil) + ("M" + "Date Metadata Changed" + (lambda () (interactive) + (cc/--dired-sort-by :date-metadata-changed + (transient-args transient-current-command))) + :transient nil) + ("v" + "Version" + (lambda () (interactive) + (cc/--dired-sort-by :version + (transient-args transient-current-command))) + :transient nil) + ("s" + "Size" + (lambda () (interactive) + (cc/--dired-sort-by :size + (transient-args transient-current-command))) + :transient nil)]]) + +(defun cc/--dired-sort-by (criteria &optional prefix-args) + "Sort current Dired buffer according to CRITERIA and PREFIX-ARGS. + +This function will invoke `dired-sort-other' with arguments built from +CRITERIA and PREFIX-ARGS. + +CRITERIA is a keyword of which the following are supported: + :name :date-added :version + :kind :date-metadata-changed :size + :date-last-opened :date-modified + +PREFIX-ARGS is a list of GNU ls arguments. If nil, then it will use the value +of `cc-dired-listing-switches'. Otherwise this is typically populated by the +Transient menu `cc/dired-sort-by'. + +This function requires GNU ls from coreutils installed. + +See the man page `ls(1)' for details." + (let ((arg-list (list "-l"))) + (if prefix-args + (nconc arg-list prefix-args) + (nconc arg-list cc-dired-listing-switches)) + (cond + ((eq criteria :name) + (message "Sorted by name")) + + ((eq criteria :kind) + (message "Sorted by kind") + (push "--sort=extension" arg-list)) + + ((eq criteria :date-last-opened) + (message "Sorted by date last opened") + (push "--sort=time" arg-list) + (push "--time=access" arg-list)) + + ((eq criteria :date-added) + (message "Sorted by date added") + (push "--sort=time" arg-list) + (push "--time=creation" arg-list)) + + ((eq criteria :date-modified) + (message "Sorted by date modified") + (push "--sort=time" arg-list) + (push "--time=modification" arg-list)) + + ((eq criteria :date-metadata-changed) + (message "Sorted by date metadata changed") + (push "--sort=time" arg-list) + (push "--time=status" arg-list)) + + ((eq criteria :version) + (message "Sorted by version") + (push "--sort=version" arg-list)) + + ((eq criteria :size) + (message "Sorted by size") + (push "-S" arg-list)) + + (t + (message "Default sorted by name"))) + + (dired-sort-other (mapconcat 'identity arg-list " ")))) + (provide 'config-dired) ;; config-dired.el ends here diff --git a/tools/emacs/config/config-org.el b/tools/emacs/config/config-org.el @@ -834,5 +834,60 @@ file which do not already have one." ;; org-tree-slide-content-margin-top 1 ;; org-tree-slide-skip-outline-level 4)) +;; from https://sachachua.com/blog/2024/01/using-consult-and-org-ql-to-search-my-org-mode-agenda-files-and-sort-the-results-to-prioritize-heading-matches/ +(defun my-consult-org-ql-agenda-jump () + "Search agenda files with preview." + (interactive) + (let* ((marker (consult--read + (consult--dynamic-collection + #'my-consult-org-ql-agenda-match) + :state (consult--jump-state) + :category 'consult-org-heading + :prompt "Heading: " + :sort nil + :lookup #'consult--lookup-candidate)) + (buffer (marker-buffer marker)) + (pos (marker-position marker))) + ;; based on org-agenda-switch-to + (unless buffer (user-error "Trying to switch to non-existent buffer")) + (pop-to-buffer-same-window buffer) + (goto-char pos) + (when (derived-mode-p 'org-mode) + (org-fold-show-context 'agenda) + (run-hooks 'org-agenda-after-show-hook)))) + +(defun my-consult-org-ql-agenda-format (o) + (propertize + (org-ql-view--format-element o) + 'consult--candidate (org-element-property :org-hd-marker o))) + +(defun my-consult-org-ql-agenda-match (string) + "Return candidates that match STRING. +Sort heading matches first, followed by other matches. +Within those groups, sort by date and priority." + (let* ((query (org-ql--query-string-to-sexp string)) + (sort '(date reverse priority)) + (heading-query (-tree-map (lambda (x) (if (eq x 'rifle) 'heading x)) query)) + (matched-heading + (mapcar #'my-consult-org-ql-agenda-format + (org-ql-select 'org-agenda-files heading-query + :action 'element-with-markers + :sort sort))) + (all-matches + (mapcar #'my-consult-org-ql-agenda-format + (org-ql-select 'org-agenda-files query + :action 'element-with-markers + :sort sort)))) + (append + matched-heading + (seq-difference all-matches matched-heading)))) + +(use-package org-ql + :after org + :bind ("M-s a" . my-consult-org-ql-agenda-jump)) + +(use-package org-ql-view + :after org-ql) + (provide 'config-org) ;;; config-org.el ends here