Trevoke / org-gtd.el

A package for using GTD with org-mode

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

When filing into a project, look for heading in agenda files, not in gtd-dir (org-gtd-project-extend--apply)

dmgerman opened this issue · comments

org-gtd-project-extend--apply properly builds a list of potential targets from the agenda + gtd files. So far so good.

Problem 1. There does not seem to be a way to differentiate between two headings (projects) in different files with the same name

Problem 2. Once the function asks the user for the destination, it then searches the gtd directory for such header.
If the project is NOT in the gtd directory, it fails with an error.

Good solution:

  1. Keep a pair of file/project from agenda + gtd files, instead of just the headers.
  2. Ask user for destination with both filename and header
  3. Use the filename instead of searching again in the gtd directory.

Not-so-good solution:

  1. add a check: if heading-marker is nil, report an error and do not execute body of the let*

well, i really need this, so here is a draft. I am assuming that between checking for destinations and refiling, the destination buffer remains.

     (defun org-gtd-project-extend--apply ()
     "Refile the org heading at point under a chosen heading in the agenda files."
      (with-org-gtd-context
      (let* ((org-gtd-refile-to-any-target nil)
             (org-use-property-inheritance '("ORG_GTD"))
             (headings (org-map-entries
                        ;; build a pair: prompt string and buffer
                        (lambda () (let ((cbuffer (current-buffer))
                                         (heading (org-get-heading t t t t)))
                                     (cons (format "%s %s" (buffer-name) heading)
                                           (cons heading cbuffer)
                                           )))
                        org-gtd-project-headings
                        'agenda))
             ;; complete reading ignores the cdr, and removes duplicates
             ;; so we need to find its first match
             (chosen-location
              (cdr (assoc (completing-read "Choose a destination:" headings nil t)
                           headings)))
             (chosen-heading (car chosen-location))
             (chosen-buffer (cdr chosen-location))
             (heading-marker (org-find-exact-headline-in-buffer chosen-heading
                                                                chosen-buffer)))
        (setq-local org-gtd--organize-type 'project-task)
        (org-gtd-organize-apply-hooks)
        (org-refile 3 nil `(,chosen-heading
                            ,(buffer-file-name chosen-buffer)
                              nil
                              ,(marker-position heading-marker))
                    nil)
        (org-gtd-projects-fix-todo-keywords heading-marker)
        (message "Moved to %s %s" (buffer-name chosen-buffer) chosen-heading)
        )))

If I summarize this correctly, there's two different requests here:

  1. display file name / buffer name as part of the set of options that the user can choose from when refiling
  2. look for projects everywhere

We should already be potentially looking for projects everywhere (we would be looking for top-level headings with ORG_GTD: Projects property, and we are wrapping this with with-org-gtd-context, which should be putting together your existing agenda files with the contents of `org-gtd-directory). If this is not the case, for some reason, let me know, but please open a separate issue just for this.

As far as changing the display, I have to say that "adding to an existing project" is a slight pain in my side because it has required making "custom logic for refiling", and I was really hoping to keep the refile logic to a single path, but I'm beginning to see that this was likely a foolish need.

Anyway.
I'll look at the code / poke at the tests for this tomorrow morning, but I think what you wrote is pretty sound, I'll just probably want to move some of the refile bits into org-gtd-refile.el (or at least make them into actual functions), but I don't see a reason to not implement this.

I have the feeling that the problem with the current implementation of this function is that there is an assumed invariant:

That any Project file (with the ORG_GTD tag) must live in the GTD directory

But other functions, such as org-gtd-engage do not have this restrictions.

that is why I was getting an error: I have two directories where I am placing Project files, and one of them is not tin the GTD directory.

@dmgerman that is correct, and this is the result of:

  • a single developer
  • multiple feature requests
  • shallow understanding of the problem and the solution
  • lack of time or desire or ability to refactor fully
  • incomplete tests

For years, org-gtd only looked inside the org-gtd-directory. A request to extend existing projects was eventually implemented, but without the ability to bring the refile logic out into org-gtd-refile.el, which was fine, but then, there was a request to extend org-agenda-files beyond org-gtd-directory, which was also fine, except I forgot that there was this one bit of logic here that needed to be refactored to allow for that.

This code was great because there happened to be org-find-exact-heading-in-directory which did exactly what I wanted. Now I have to work ... Just a little bit harder, but the good news is that it gets me a step closer to more seamless refile logic.

It occurs to me there isn't actually a good solution to this.

People can have the same file name in multiple directories. People can use emacs without uniquifying their buffer names. People can use the same project top-level heading, and they can use the same project names.

SOMEWHERE people are going to be unhappy. And any suggestion involving displaying the filepath, which is basically the only true unambiguous solver, is going to be asking a lot of customization questions down that path as well.

For now, I will extend the heading search to all org-agenda-files (which is going to be the meaningful business logic adjustment here anyway) and let's defer trying to make a display adjustment for now.

Probably the only truly meaningful answer to the display question is to let the user provide an optional function that lets them customize the display however they want, if they need it, and cannot reasonably have unique project names...

Okay, this should work now, but I didn't mark it stable yet so if you're pinned on MELPA stable you may not get this.