From 553c22c3ac390117e095ec78fd756a713acdc641 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Oct 2019 18:20:29 -0500 Subject: [PATCH] Add: Adjust search parameters in view buffers --- README.org | 3 +- org-ql-search.el | 112 +++++++++++++++++++++++++++-------------------- org-ql-view.el | 50 ++++++++++++++------- org-ql.info | 53 +++++++++++----------- 4 files changed, 128 insertions(+), 90 deletions(-) diff --git a/README.org b/README.org index be50959..f489562 100644 --- a/README.org +++ b/README.org @@ -105,7 +105,7 @@ Read ~QUERY~ and search with ~org-ql~. Interactively, prompt for these variable ~SORT~: One or a list of ~org-ql~ sorting functions, like ~date~ or ~priority~. *Bindings:* Keys bound in results buffer. -+ =g=: Refresh results. ++ =g=: Refresh results. With prefix, prompt to adjust search parameters. + =C-x C-s=: Save query to variable ~org-ql-views~ (accessible with command ~org-ql-view~). *Note:* The view buffer is currently put in ~org-agenda-mode~, which means that /some/ Org Agenda commands work, such as jumping to entries and changing item priorities (without necessarily updating the view). This feature is experimental and not guaranteed to work correctly with all commands. (It works to the extent it does because the appropriate text properties are placed on each item, imitating an Agenda buffer.) @@ -376,6 +376,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Predicates =outline-path= (alias =olp=) and =outline-path-segment= (alias =olps=). + Info manual. + Command ~org-ql-search~ can search files in ~org-directory~; customization options are available in the ~org-ql-search~ group. ++ Command ~org-ql-view-refresh~ can be called with a prefix argument to adjust search parameters. + Function ~helm-org-ql-source~, which returns a Helm source that searches given buffers/files with ~helm-org-ql~. It can be used for custom Helm commands that search certain files. *Internal* diff --git a/org-ql-search.el b/org-ql-search.el index 9ef07c0..eb4e550 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -139,28 +139,39 @@ display the results. By default, the value of `org-ql-view-buffer' is used, and a new buffer is created if necessary." (declare (indent defun)) - (interactive (list (pcase-exhaustive (completing-read "Buffers/Files: " - (list 'buffer 'agenda 'directory 'all) - nil t) - ((or "" "buffer") (current-buffer)) - ("agenda" (org-agenda-files)) - ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) - (buffer-list))) - ("directory" (org-ql-search-directories-files)) - ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) - (else (s-split (rx (1+ space)) else))) - (read-string "Query: ") - :narrow (eq current-prefix-arg '(4)) + (interactive (list (if (and org-ql-view-buffers-files + (bufferp org-ql-view-buffers-files)) + ;; 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. + org-ql-view-buffers-files + (pcase-exhaustive (completing-read "Buffers/Files: " + (list 'buffer 'agenda 'directory 'all) + nil nil (when org-ql-view-buffers-files + (prin1-to-string (cons 'list org-ql-view-buffers-files)))) + ((or "" "buffer") (current-buffer)) + ("agenda" (org-agenda-files)) + ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) + (buffer-list))) + ("directory" (org-ql-search-directories-files)) + ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) + (else (s-split (rx (1+ space)) else)))) + (read-string "Query: " (when org-ql-view-query + (format "%S" org-ql-view-query))) + :narrow (or org-ql-view-narrow (eq current-prefix-arg '(4))) :super-groups (when (bound-and-true-p org-super-agenda-auto-selector-keywords) - (pcase (completing-read "Group by: " - (append (list "Don't group" - "Global super-groups") - (cl-loop for type in org-super-agenda-auto-selector-keywords - collect (substring (symbol-name type) 6))) - nil t) - ("Global super-groups" org-super-agenda-groups) - ((or "" "Don't group") nil) - (property (list (list (intern (concat ":auto-" property))))))) + (let ((keywords (cl-loop for type in org-super-agenda-auto-selector-keywords + collect (substring (symbol-name type) 6)))) + (pcase (completing-read "Group by: " + (append (list "Don't group" + "Global super-groups") + keywords) + nil nil (when org-ql-view-super-groups + (format "%S" org-ql-view-super-groups))) + ("Global super-groups" org-super-agenda-groups) + ((or "" "Don't group") nil) + ((and keyword (guard (member keyword keywords))) + (list (list (intern (concat ":auto-" keyword))))) + (else (read else))))) :sort (pcase (completing-read "Sort by: " (list "Don't sort" "date" @@ -168,35 +179,42 @@ necessary." "priority" "scheduled" "todo") - nil t) + nil t (when org-ql-view-sort + (prin1-to-string org-ql-view-sort))) ((or "" "Don't sort") nil) (sort (intern sort))))) - (let* ((query (cl-etypecase query - (string (if (string-match-p (rx bos (1+ alpha) ":") query) + ;; NOTE: Using `with-temp-buffer' is a hack to work around the fact that `make-local-variable' + ;; does not work reliably from inside a `let' form when the target buffer is current on entry + ;; to or exit from the `let', even though `make-local-variable' is actually done in + ;; `org-ql-view--display'. So we do all this within a temp buffer, which works around it. + (with-temp-buffer + (let* ((query (cl-etypecase query + (string (if (or (string-prefix-p "(" query) + (string-prefix-p "\"" query)) + ;; Read sexp query. + (read query) ;; Parse non-sexp query into sexp query. - (org-ql--plain-query query) - ;; Read sexp query. - (read query))) - (list query))) - (results (org-ql-select buffers-files query - :action 'element-with-markers - :narrow narrow - :sort sort)) - (strings (-map #'org-ql-view--format-element results)) - (buffer (or buffer (format "%s %s*" org-ql-view-buffer-name-prefix (or title query)))) - (header (org-ql-view--header-line-format buffers-files query title)) - ;; Bind variables for `org-ql-view--display' to set. - (org-ql-view-buffers-files buffers-files) - (org-ql-view-query query) - (org-ql-view-sort sort) - (org-ql-view-narrow narrow) - (org-ql-view-super-groups super-groups) - (org-ql-view-title title)) - (when super-groups - (let ((org-super-agenda-groups super-groups)) - (setf strings (org-super-agenda--group-items strings)))) - (org-ql-view--display :buffer buffer :header header - :string (s-join "\n" strings)))) + (org-ql--plain-query query))) + (list query))) + (results (org-ql-select buffers-files query + :action 'element-with-markers + :narrow narrow + :sort sort)) + (strings (-map #'org-ql-view--format-element results)) + (buffer (or buffer (format "%s %s*" org-ql-view-buffer-name-prefix (or title query)))) + (header (org-ql-view--header-line-format buffers-files query title)) + ;; Bind variables for `org-ql-view--display' to set. + (org-ql-view-buffers-files buffers-files) + (org-ql-view-query query) + (org-ql-view-sort sort) + (org-ql-view-narrow narrow) + (org-ql-view-super-groups super-groups) + (org-ql-view-title title)) + (when super-groups + (let ((org-super-agenda-groups super-groups)) + (setf strings (org-super-agenda--group-items strings)))) + (org-ql-view--display :buffer buffer :header header + :string (s-join "\n" strings))))) (defun org-ql-search-block (query) "Insert items for QUERY into current buffer. diff --git a/org-ql-view.el b/org-ql-view.el index d65a7a7..9e57e0d 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -266,18 +266,27 @@ TYPE may be `ts', `ts-active', `ts-inactive', `clocked', or 'face '(:weight bold :inherit highlight)) (org-ql-view key)))) -(defun org-ql-view-refresh () - "Refresh current `org-ql-search' buffer." - (interactive) - (let ((current-line (buffer-substring-no-properties (line-beginning-position) (line-end-position))) - (old-pos (point))) - (org-ql-search org-ql-view-buffers-files - org-ql-view-query - :sort org-ql-view-sort - :narrow org-ql-view-narrow - :super-groups org-ql-view-super-groups - :title org-ql-view-title - :buffer (current-buffer)) +(defun org-ql-view-refresh (&optional prompt) + "Refresh current `org-ql-search' buffer. +If PROMPT is non-nil (interactively, with prefix), prompt to +update search arguments." + (interactive "P") + (let* ((current-line (buffer-substring-no-properties (line-beginning-position) (line-end-position))) + (old-pos (point)) + (defaults (list org-ql-view-buffers-files + org-ql-view-query + :sort org-ql-view-sort + :narrow org-ql-view-narrow + :super-groups org-ql-view-super-groups + :title org-ql-view-title)) + (org-ql-view-buffer (current-buffer))) + (if prompt + (call-interactively #'org-ql-search) + (apply #'org-ql-search defaults)) + ;; Now in the results buffer. + (rename-buffer (format "%s %s*" + org-ql-view-buffer-name-prefix + (or org-ql-view-title org-ql-view-query))) (goto-char (point-min)) (or (when (search-forward current-line nil t) (beginning-of-line)) @@ -338,17 +347,24 @@ subsequent refreshing of the buffer: `org-ql-view-buffers-files', `org-ql-view-query', `org-ql-view-sort', `org-ql-view-narrow', `org-ql-view-super-groups', `org-ql-title.'" (declare (indent defun)) - (let* ((buffer (cl-etypecase buffer + (let* ((vars (list 'org-ql-view-buffers-files 'org-ql-view-query + 'org-ql-view-sort 'org-ql-view-narrow + 'org-ql-view-super-groups 'org-ql-view-title)) + ;; Save the values of variables which are set buffer-locally in the + ;; results buffer, which we want to override and set buffer-locally again. + (vals (cl-loop for symbol in vars + collect (cons symbol (symbol-value symbol)))) + (buffer (cl-etypecase buffer (string (org-ql-view--buffer buffer)) (null (org-ql-view--buffer buffer)) (buffer buffer)))) (with-current-buffer buffer (use-local-map org-ql-view-map) ;; Prepare buffer, saving data for refreshing. - (cl-loop for symbol in (list 'org-ql-view-buffers-files 'org-ql-view-query - 'org-ql-view-sort 'org-ql-view-narrow - 'org-ql-view-super-groups 'org-ql-view-title) - do (set (make-local-variable symbol) (symbol-value symbol))) + (cl-loop for symbol in vars + do (progn + (kill-local-variable symbol) + (set (make-local-variable symbol) (alist-get symbol vals nil nil #'equal)))) (setf header-line-format header) ;; Clear buffer, insert entries, etc. (let ((inhibit-read-only t)) diff --git a/org-ql.info b/org-ql.info index 3632511..d7c135f 100644 --- a/org-ql.info +++ b/org-ql.info @@ -216,7 +216,8 @@ Interactively, with prefix, leave narrowed. ‘priority’. *Bindings:* Keys bound in results buffer. - • g: Refresh results. + • g: Refresh results. With prefix, prompt to adjust search + parameters. • C-x C-s: Save query to variable ‘org-ql-views’ (accessible with command ‘org-ql-view’). @@ -692,6 +693,8 @@ File: README.info, Node: 04-pre, Next: 03, Up: Changelog • Info manual. • Command ‘org-ql-search’ can search files in ‘org-directory’; customization options are available in the ‘org-ql-search’ group. + • Command ‘org-ql-view-refresh’ can be called with a prefix argument + to adjust search parameters. • Function ‘helm-org-ql-source’, which returns a Helm source that searches given buffers/files with ‘helm-org-ql’. It can be used for custom Helm commands that search certain files. @@ -950,30 +953,30 @@ Node: Quelpa2241 Node: Usage2684 Node: Commands3594 Node: org-ql-search3823 -Node: helm-org-ql5416 -Node: org-ql-view5828 -Node: org-ql-view-sidebar6026 -Node: org-ql-view-recent-items6382 -Node: org-ql-sparse-tree6866 -Node: Queries7666 -Node: Non-sexp query syntax8508 -Node: Predicates10008 -Node: Date/time predicates14865 -Node: Functions / Macros17500 -Node: Agenda-like views17687 -Node: Listing / acting-on results19092 -Node: Changelog23694 -Node: 04-pre24201 -Node: 0324862 -Node: 02327838 -Node: 02228064 -Node: 02128330 -Node: 0228527 -Node: 0132560 -Node: Notes32659 -Node: Comparison with Org Agenda searches32821 -Node: org-sidebar33692 -Node: License33971 +Node: helm-org-ql5471 +Node: org-ql-view5883 +Node: org-ql-view-sidebar6081 +Node: org-ql-view-recent-items6437 +Node: org-ql-sparse-tree6921 +Node: Queries7721 +Node: Non-sexp query syntax8563 +Node: Predicates10063 +Node: Date/time predicates14920 +Node: Functions / Macros17555 +Node: Agenda-like views17742 +Node: Listing / acting-on results19147 +Node: Changelog23749 +Node: 04-pre24256 +Node: 0325029 +Node: 02328005 +Node: 02228231 +Node: 02128497 +Node: 0228694 +Node: 0132727 +Node: Notes32826 +Node: Comparison with Org Agenda searches32988 +Node: org-sidebar33859 +Node: License34138  End Tag Table