org-ql icon indicating copy to clipboard operation
org-ql copied to clipboard

Agenda format function

Open akirak opened this issue 5 years ago • 11 comments

Hi,

I want to customize the entry format of org-ql-block. In particular, I want to prepend the category to each entry. In the builtin agenda, this is the default and can be customizable by customizing org-agenda-prefix-format variable, but it doesn't work for org-ql, since org-ql-block uses its own function for formatting entries. I want a way to customize the formats in org-ql-block blocks.

In the source code of org-ql-agenda.el, I found your todo comment on adding support for org-agenda-like formats in the future, but it sounds really hard to re-implement org-agenda-prefix-format, and I would like to customize the format soon (or even now), I implemented an alternative solution.

It allows the user to change the format through org-ql-agenda-format-function, which takes as arguments a map (currently alist) and an element returned by org-element. In addition, I've added category to the map, since it would be more efficient to get the data inside the function.

I am not sure if this is an ideal API, so I don't expect you to merge this PR. It sufficies for my purpose, but there can be a better way.

What is your current plan on supporting custom formats, and what do you think of this solution?

Thanks.

akirak avatar Sep 08 '19 02:09 akirak

Hi Akira,

Thanks, this is very interesting.

Passing the alist of values from the other function is a nice way to save the other function the trouble of extracting them itself. On one hand, that seems simpler, but on the other, it would seem simpler to just pass the element plist. So I'm not sure what the best solution is.

If you're interested, please take a look at this branch: https://github.com/alphapapa/org-ql/tree/wip/view-section Specifically, look at org-ql-item.el and the struct there. I'm thinking about replacing the element-with-markers action with an item action (I may rename item to entry or node), which would return a struct rather than the element plist. What I plan to try is making all of the slots lazily accessed and cached, like the deadline-ts and scheduled-ts slots are now (it's similar to the technique I use in ts), by storing the element plist in its own slot, and accessing its values when necessary. I'll have to do some testing to see how it affects performance.

The idea is to make sorting and grouping easier, and in the long run, to aid with making the magit-section-like view in that branch (I posted a demo here: https://www.reddit.com/r/orgmode/comments/d11zfj/wip_magitlike_sections_for_orgql_views/).

Anyway, I think I will see how that struct idea works out before changing the formatter. Afterward, I'll take another look at org-agenda-prefix-format. It would be nice to provide a formatter that's compatible with it, but I don't know yet if that's practical or the best solution.

P.S. map-elt is handy, but since it's generic, it's probably slower than e.g. alist-get, so I'd probably avoid using it in the formatter. Sometimes I do searches which return lots of results, up to a couple thousand, and in those cases, I'm guessing it would make a noticeable difference. Using a struct like I mentioned might help performance there, but we're still working with the element property list, so there's only so much we can do.

alphapapa avatar Sep 08 '19 23:09 alphapapa

It would be nice to provide a formatter that's compatible with it, but I don't know yet if that's practical or the best solution.

I agree. I'm currently moving some of my agenda code to use org-ql for queries, and this would come in handy for me to just reuse custom functions that I use in the format string for org-agenda-prefix-format.

mpereira avatar Feb 14 '20 21:02 mpereira

In the same sentiment, is it currently possible to emulate the effect of org-agenda-sorting-strategy within org-ql-block?

mpereira avatar Feb 14 '20 22:02 mpereira

In the same sentiment, is it currently possible to emulate the effect of org-agenda-sorting-strategy within org-ql-block?

#79

alphapapa avatar Feb 14 '20 22:02 alphapapa

Thanks for the pointer @alphapapa, I'll be on the lookout!

mpereira avatar Feb 14 '20 22:02 mpereira

Question: is this related to the reason why I can't get org-agenda-hide-tags-regexp? (ie. that org-ql-block does not use the standard formatting).

dmacvicar avatar Apr 21 '20 13:04 dmacvicar

Question: is this related to the reason why I can't get org-agenda-hide-tags-regexp? (ie. that org-ql-block does not use the standard formatting).

Yes.

alphapapa avatar Apr 23 '20 06:04 alphapapa

Since it's been so long since the last 0.x release, I'm going to defer this to 0.7 in an effort to reduce the scope of 0.6 and release it sooner.

alphapapa avatar Jun 17 '21 09:06 alphapapa

Real world context/anecdote:

I'm writing an org-ql version of Task management with org-roam and this feature would be needed to implement their category display improvement.

ParetoOptimalDev avatar Nov 14 '22 18:11 ParetoOptimalDev

Real world context/anecdote:

I'm writing an org-ql version of Task management with org-roam and this feature would be needed to implement their category display improvement.

Per the advice shared in https://github.com/alphapapa/org-ql/issues/23, these functions which I've adapted should meet your needs

(defun dl/org-roam-get-keyword (name)
  (let ((key (intern (upcase name)))
        (keyword-alist (org-collect-keywords (list name))))
    (car (alist-get key keyword-alist nil nil #'string-equal))))

(defun dl/org-ql-view--format-element-a (orig-fun &rest args)
  "This function will intercept the original function and
   add the category to the result.

   ARGS is `element' in `org-ql-view--format-element'"
  (if (not args)
      ""
    (let* ((element args)
           (properties (cadar element))
           (result (apply orig-fun element))
           (buffer (marker-buffer (plist-get properties :org-marker)))
           (category (with-current-buffer buffer (dl/org-roam-get-keyword "title"))))
      (org-add-props
          (format "%s %s"
                  (s-pad-right dl-org-ql-view-format-length " "
                               (s-truncate dl-org-ql-view-format-length category))
                  result)
          (text-properties-at 0 result)))))
(advice-add 'org-ql-view--format-element :around #'dl/org-ql-view--format-element-a)

joyguar avatar Mar 23 '23 06:03 joyguar

@dstrr You should probably use org-with-point-at rather than just with-current-buffer to ensure you get the category at the item rather than elsewhere in the buffer.

alphapapa avatar Mar 23 '23 19:03 alphapapa