On Saturday, 6 November 2021 10:10:55 CET Victor A. Stoichita wrote:
> Greetings to all,
> 
> Reading the manual about setting glopal/per-file tags [1], I wonder if
> it is possible to use org-tag-persistent-alist AND per-file
> dynamic tags.

I use footnote 53 from https://orgmode.org/manual/Setting-Tags.html[1].
I put my tags in `tags-file.org`, using `#+TAGS:`.
I've put the next two lines in `init.el`.

(setq org-agenda-files (list "~/path-to/tags-file.org")
         org-complete-tags-always-offer-all-agenda-tags t)

And I have completion on both the tags in `tags-file.org` and tags in the 
current buffer.
I don't use `org-tag-alist`, so the comments made in 
https://emacs.stackexchange.com/q/
69369#comment111307_69369[2], would not apply.

I use a script to collect the tags, based on Kitchin's 
https://stackoverflow.com/a/
27527252[3], and help from `#emacs`.
I use `with-temp-buffer` because otherwise all the files accessed by 
`org-map-entries` are 
showing when I do `C-x C-b` and I find it cumbersome.
The tags are sorted by frequency, which is not necessary here, but it's really 
nice.
I suppose you could put a `defun nice-function-name` on top of it, but so far, 
it's only a 
hack.
`~/path-to-directory` and `tags-file.org` should be tweaked to your needs. 
`default-
directory` can be used for the former, too.
(caveat: the script makes use of `-flatten`, `-map` and `-uniq, from `dash.el`. 
It also 
makes use of `mapcar` where `-map` would do, `seq-sort` where `-sort` would do, 
`seq-
reduce` where `-reduce` would do. Standard elisp has `flatten-tree`, for 
`-flatten`, 
`mapcar` for `-map`, `delete-dups` for `-uniq`. https://github.com/Droogans/
unmaintainable-code[4])

(let* ((dir "~/path-to-directory")
       (all-tags
        (-flatten
         (-map
          (lambda (fpath)
            (with-temp-buffer
              (insert-file-contents fpath)
              (org-mode)
              (org-map-entries
               (lambda ()
                 (let ((tag-string (car (last (org-heading-components)))))
                   (when tag-string
                     (split-string tag-string ":" t)))) nil nil)))
          (directory-files-recursively dir "^[^#].*org$")))))
  (let ((tags-count
         (cl-loop for tag in (-uniq all-tags)
                  collect (cons tag (cl-count tag all-tags :test 'string=)))))
    (let ((tags-list
           (mapcar 'car (seq-sort (lambda (a b) (< (cdr b) (cdr a))) 
tags-count))))
      (let ((tags-string
             (cl-reduce (lambda (a b) (concat a " " b)) tags-list)))
        (let ((filled-tags-string
               (with-temp-buffer
                 (setq fill-column 70
                       fill-prefix "#+TAGS: ")
                 (insert (concat "#+TAGS: " tags-string)) (fill-paragraph) 
(buffer-string))))
          (with-temp-file "tags-file.org" (insert filled-tags-string)))))))


> 
> When using org-set-tags-command, I’d like to select from a list
> comprising both:
> 1. the list of predefined tags in org-tag-persistent-alist
> 2. the list of all the tags that are already in use in the current
>    buffer (some of which might not be in the persistent alist). I don’t
>    want to use the #+TAGS keyword at file-level, just the list of tags
>    already attached to some headline in the buffer.
> 
> The manual says:
> > If you have globally defined your preferred set of tags using the
> > variable org-tag-alist, but would like to use a dynamic tag list in
> > a specific file, add an empty ‘TAGS’ keyword to that file
> 
> And then it says:
> > If you have a preferred set of tags that you would like to use in every
> > file, in addition to those defined on a per-file basis by ‘TAGS’
> > keyword, then you may specify a list of tags with the variable
> > org-tag-persistent-alist.
> 
> I tried to combine both behaviors by putting an empty ’TAGS’ keyword at
> the top of my file. But this still only gives me the tags in
> org-tag-persistent-alist. What would be the best way to add to it for
> completion the tags already used in the buffer?
> 
> Regards,

Reply via email to