Add/Change/Fix: Storing links to containing buffer or files

This feels too complicated, but I don't see a way around it, short of
redesigning all of the argument expansion/contraction, which might end
up in the same place, anyway.

See #147.
This commit is contained in:
Adam Porter 2020-11-10 21:17:27 -06:00
parent 8102d7a8ee
commit bfd4d462a0

View file

@ -623,7 +623,7 @@ protocol. See, e.g. `org-ql-view--link-store'."
(title (--when-let (alist-get "title" params nil nil #'string=) (title (--when-let (alist-get "title" params nil nil #'string=)
(read it))) (read it)))
(buffers-files (--if-let (alist-get "buffers-files" params nil nil #'string=) (buffers-files (--if-let (alist-get "buffers-files" params nil nil #'string=)
(read it) (org-ql-view--expand-buffers-files (read it))
(current-buffer)))) (current-buffer))))
(when (and org-ql-view-ask-unsafe-links (when (and org-ql-view-ask-unsafe-links
(or (string-match (rx bol (0+ space) "(") query) (or (string-match (rx bol (0+ space) "(") query)
@ -642,25 +642,29 @@ protocol. See, e.g. `org-ql-view--link-store'."
:super-groups groups :super-groups groups
:title title))) :title title)))
(defvar org-ql-view--link-store-counter 0
"Workaround for an idiosyncrasy of `org-store-link' that calls link-storing functions twice.")
(defun org-ql-view--link-store () (defun org-ql-view--link-store ()
"Store a link to the current Org QL view. "Store a link to the current Org QL view.
When opened, the link searches the buffer it's opened from." When opened, the link searches the buffer it's opened from."
(require 'url-parse) (require 'url-parse)
(require 'url-util) (require 'url-util)
(when org-ql-view-query (when org-ql-view-query
(unless (cl-etypecase org-ql-view-buffers-files (cl-incf org-ql-view--link-store-counter)
;; I really wish `anaphora' were in ELPA, because `aetypecase' would be ;; Only Org QL View buffers should have `org-ql-view-query' set.
;; nice here, and I'd prefer to avoid adding more MELPA-only dependencies. (cl-flet ((prompt-for (buffers-files)
(buffer t) ;; HACK: Use counter to avoid prompting the first of the
(string (file-exists-p org-ql-view-buffers-files)) ;; two times that `org-store-link' calls this function.
(list (and (cl-every #'stringp org-ql-view-buffers-files) (when (cl-evenp org-ql-view--link-store-counter)
(cl-every #'file-exists-p org-ql-view-buffers-files)))) (pcase-exhaustive
(user-error "Can only store links to views of either a single buffer/file or a list of files")) (completing-read (format "Link to search file containing inserted link or %s? " buffers-files)
(let* ((params (list (when (and org-ql-view-buffers-files (list "containing file" buffers-files) nil t)
;; If it's one buffer (i.e. the view searches the current ("containing file" nil)
;; buffer), don't serialize it, because buffers are unreadable. (buffers-files (prin1-to-string buffers-files))))))
(not (bufferp org-ql-view-buffers-files))) (let* ((buffers-files (prompt-for (org-ql-view--contract-buffers-files org-ql-view-buffers-files)))
(list "buffers-files" (prin1-to-string org-ql-view-buffers-files))) (params (list (when buffers-files
(list "buffers-files" buffers-files))
(when org-ql-view-super-groups (when org-ql-view-super-groups
(list "super-groups" (prin1-to-string org-ql-view-super-groups))) (list "super-groups" (prin1-to-string org-ql-view-super-groups)))
(when org-ql-view-sort (when org-ql-view-sort
@ -674,7 +678,7 @@ When opened, the link searches the buffer it's opened from."
(org-store-link-props (org-store-link-props
:type "org-ql-search" :type "org-ql-search"
:link url :link url
:description (concat "org-ql-search: " org-ql-view-title))) :description (concat "org-ql-search: " org-ql-view-title))))
t)) t))
;;;; Transient ;;;; Transient
@ -992,6 +996,9 @@ property."
;;;;; Completion ;;;;; Completion
;; These functions are somewhat regrettable because of the need to keep them
;; in sync, but it seems worth it to provide users with the flexibility.
(defun org-ql-view--contract-buffers-files (buffers-files) (defun org-ql-view--contract-buffers-files (buffers-files)
"Return BUFFERS-FILES in its \"contracted\" form. "Return BUFFERS-FILES in its \"contracted\" form.
The contracted form is \"org-agenda-files\" if BUFFERS-FILES The contracted form is \"org-agenda-files\" if BUFFERS-FILES
@ -1020,6 +1027,8 @@ current buffer. Otherwise BUFFERS-FILES is returned unchanged."
"buffer") "buffer")
((or 'org-agenda-files '(function org-agenda-files)) ((or 'org-agenda-files '(function org-agenda-files))
"org-agenda-files") "org-agenda-files")
((and (pred bufferp) (guard (file-exists-p (buffer-file-name buffers-files))))
(buffer-file-name buffers-files))
(_ (let ((print-length nil)) (_ (let ((print-length nil))
(prin1-to-string buffers-files)))))) (prin1-to-string buffers-files))))))
@ -1034,17 +1043,23 @@ current buffer. Otherwise BUFFERS-FILES is returned unchanged."
;; Buffers can't be input by name, so if the default value is a buffer, just use it. ;; Buffers can't be input by name, so if the default value is a buffer, just use it.
;; TODO: Find a way to fix this. ;; TODO: Find a way to fix this.
org-ql-view-buffers-files org-ql-view-buffers-files
(pcase-exhaustive (org-ql-view--expand-buffers-files
(completing-read "Buffers/Files: " (completing-read "Buffers/Files: "
(list 'buffer 'org-agenda-files 'org-directory 'all) (list 'buffer 'org-agenda-files 'org-directory 'all)
nil nil (initial-input)) nil nil (initial-input))))))
(defun org-ql-view--expand-buffers-files (buffers-files)
"Return BUFFERS-FILES expanded to a list of files or buffers.
The counterpart to `org-ql-view--contract-buffers-files'."
(pcase-exhaustive buffers-files
((pred bufferp) buffers-files)
((or "" "buffer") (current-buffer)) ((or "" "buffer") (current-buffer))
("org-agenda-files" (org-agenda-files)) ("org-agenda-files" (org-agenda-files))
("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode)
(buffer-list))) (buffer-list)))
("org-directory" (org-ql-search-directories-files)) ("org-directory" (org-ql-search-directories-files))
((and form (guard (rx bos "("))) (-flatten (eval (read form)))) ((and form (guard (rx bos "("))) (-flatten (eval (read form))))
(else (s-split (rx (1+ space)) else)))))) (else (s-split (rx (1+ space)) else))))
(defun org-ql-view--complete-super-groups () (defun org-ql-view--complete-super-groups ()
"Return value for `org-ql-view-super-groups' using completion." "Return value for `org-ql-view-super-groups' using completion."