vulpea icon indicating copy to clipboard operation
vulpea copied to clipboard

Support headings in vulpea-meta

Open d12frosted opened this issue 3 years ago • 8 comments

Right now by definition metadata can be placed only on the file-level. When #35 is implemented, we can support heading-level metadata.

d12frosted avatar Jan 23 '21 15:01 d12frosted

hey! looks like an interesting library, I've been taking bits from your blog for a while.

my use-case within org/-roam is heavily headline reliant, so in looking to use this library I just hacked up something which achieves a precursor to this issue -- getting org AST data, scoped to subtree, where point can come from current-point as given, or some roam attribute for point.

I haven't gone so far as to limit the extent of the collection here (as is possible with org-element-*-parser, such as org-element-headline-parser, which takes some point as a limit), but as we have a copy of the buffer, we can delete parts of the buffer contents without consequence, thus making an equivalent limit.

I will follow up with a concrete application of this, but this is probably enough to drop inplace of buf here https://github.com/d12frosted/vulpea/blob/398ca17f83ea59f54f61898fefdb55332cd3ba46/vulpea-buffer.el#L181 -- I haven't got an eldev setup, nor tried this though, so that's just speculation :)

drop this into a buffer to try it out

** buffer parsing
- abc :: def
#+begin_src emacs-lisp
(let* ((pt (point))
       (fp (buffer-file-name (current-buffer))))
  (with-temp-buffer
    (org-mode)
    (insert-file-contents fp) ;; clone current buffer
    (goto-char pt)            ;; restore point
    (org-narrow-to-subtree)   ;; set implicit scope 
    (let* ((el (org-element-parse-buffer)))
      (pp (org-element-map el 'plain-list #'identity)))))
#+end_src

#+RESULTS:
#+begin_example
((plain-list
  (:type descriptive :begin 9015 :end 9028 :contents-begin 9015 :contents-end 9028 :structure
         ((9015 0 "- " nil nil "abc" 9028))
         :post-blank 0 :post-affiliated 9015 :parent
         (section
          (:begin 9015 :end 9439 :contents-begin 9015 :contents-end 9439 :post-blank 0 :post-affiliated 9015 :parent
                  (headline
                   (:raw-value "buffer parsing" :begin 8995 :end 9439 :pre-blank 0 :contents-begin 9015 :contents-end 9439 :level 4 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :post-affiliated 8995 :title
                               (#("buffer parsing" 0 14
                                  (:parent #5)))
                               :parent
                               (org-data nil #5))
                   #3))
          #1
          (src-block
           (:language "emacs-lisp" :switches nil :parameters nil :begin 9028 :end 9422 :number-lines nil :preserve-indent nil :retain-labels t :use-labels t :label-fmt nil :value "(let* ((pt (point))\n       (fp (buffer-file-name (current-buffer))))\n  (with-temp-buffer\n    (org-mode)\n    (insert-file-contents fp) ;; clone current buffer\n    (goto-char pt)            ;; restore point\n    (org-narrow-to-subtree)   ;; set implicit scope \n    (let* ((el (org-element-parse-buffer)))\n      (pp (org-element-map el 'plain-list #'identity)))))\n" :post-blank 1 :post-affiliated 9028 :parent #3))
          (fixed-width
           (:begin 9422 :end 9439 :value "nil" :post-blank 1 :post-affiliated 9433 :results
                   ("")
                   :parent #3))))
  (item
   (:bullet "- " :begin 9015 :end 9028 :contents-begin 9024 :contents-end 9028 :checkbox nil :counter nil :structure
            ((9015 0 "- " nil nil "abc" 9028))
            :pre-blank 0 :post-blank 0 :post-affiliated 9015 :tag
            (#("abc" 0 3
               (:parent #2)))
            :parent #1)
   (paragraph
    (:begin 9024 :end 9028 :contents-begin 9024 :contents-end 9028 :post-blank 0 :post-affiliated 9024 :parent #2)
    #("def\n" 0 4
      (:parent #3))))))
#+end_example

qzdl avatar Jan 13 '22 12:01 qzdl

oh, and I see you're considering the use of org-ml, which would supersede this procedural mutating approach -- but likely not the the result, a narrowed parse tree for the 'plain-list of a given heading -- I have been meaning to look into an equivalent set of traversal operations for other headline-wise operations, but I currently rely on imperative-org-command style ops across the board

qzdl avatar Jan 13 '22 12:01 qzdl

@qzdl thanks for sharing your code :) not sure when, but I am planning to support headlines out of box :)

d12frosted avatar Feb 02 '22 05:02 d12frosted

sounds lovely! will be keeping an eye out!

qzdl avatar Feb 04 '22 09:02 qzdl

Landed here because of #135; @d12frosted will this functionality support all headlines out of the box or only those that are specifically tagged with an org-id (i.e. treated as org-roam nodes)?

In the case that all headlines are supported, will there be a way to configure/disable the behaviour? For context, the way I use vulpea-meta is by nesting it under a Metadata headline for all of my notes. A sample article, for example, is:

:PROPERTIES:
:ID:       4E7ACE06-8D91-4540-B23A-92B0D4A70E75
:CREATED:  [2022-02-04 Fri 13:48]
:END:
#+title: Giving Negative Feedback Can Make Empathetic Leaders Less Effective
#+filetags: :article:

* Metadata

- url :: [[https://hbr.org/2022/01/giving-negative-feedback-can-make-empathetic-leaders-less-effective][hbr.org]]

* Notes

To be clear this isn't a deal breaker in any sense; the value that vulpea provides far outweighs the effort to change my note structure.

d4ncer avatar Feb 04 '22 22:02 d4ncer

@d4ncer That's a good question. My thinking was the following.

  1. Allow to pass region to vulpea-buffer-meta, where by default it uses whole buffer. This allows to either take first description list from any place of the buffer or from specific region (e.g. narrowed to headline).
  2. Then vulpea-meta would support headings 😸 E.g. if it's a heading, it uses vulpea-buffer-meta with heading region, otherwise... either just a buffer or it region before first heading. For performance reasons I'd rather use vulpea-buffer-meta as is, which is what you want. Semantically, it makes sense to limit the scope 😸

So no decision on this end. But thanks for sharing your use case!

To be clear this isn't a deal breaker in any sense; the value that vulpea provides far outweighs the effort to change my note structure.

All I can say - ❤️ Happy you find it useful 😸

d12frosted avatar Feb 05 '22 09:02 d12frosted

I use vulpea library for taking botanical notes, there're many species headlines exist within a single genus buffer, if headlines are supported by vulpea-meta, it will be perfect!

By the way, vine is an elaborate library although I don't drink wine very much, the code itself help me a lot!

Thanks a lot!

sagehan avatar Mar 15 '22 05:03 sagehan

@sagehan this is on my radar. Can't provide any ETA, as I struggle to perform even my full-time job tasks due to war. But hopefully I will start working on this soon enough.

By the way, vine is an elaborate library although I don't drink wine very much, the code itself help me a lot!

Great! I am happy you find it useful. Being a showcase for vulpea library capabilities is one of the goals of vino library.

d12frosted avatar Mar 15 '22 07:03 d12frosted