emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Planning links to tasks
@ 2022-10-02 19:30 Eduardo Suarez
  2022-10-02 19:42 ` Eduardo Suarez Santana
  2022-10-03  5:37 ` Ihor Radchenko
  0 siblings, 2 replies; 3+ messages in thread
From: Eduardo Suarez @ 2022-10-02 19:30 UTC (permalink / raw)
  To: emacs-orgmode

This mail is related to 'Manual Ordering and Dynamic Priority' thread.
https://lists.gnu.org/archive/html/emacs-orgmode/2022-09/msg00091.html

Hi, I have just implemented an approach to creating a hierarchy of links to
tasks, so the hierarchy can be thought of a dependency tree (something like a
Gantt but with no dates). This approach may be suitable if your org hierarchy
is not already based on todo dependencies, and there are too many tasks to
review them often.

The idea is to be able to:

- easily add an item to a plain list in a section named (e.g.)
  "Planning/Unplanned tasks", consisting of a link to a task in the same
  buffer (=org-plk-insert=),

- move by text editing this list item into a hierarchy of items in a section
  named (e.g.) "Planning/Planned tasks", so hierarchy means dependency
  (somehow).

BEGIN ORG SAMPLE

...
* Planning
** Planned tasks
- [[#task4][My task 4 header]]
  - [[#task5][My task 5 header]]
  - [[#task1][My task 1 header]]
- [[#task2][My task 2 header]]
  - [[#task7][My task 7 header]]
    - [[#task6][My task 6 header]]
  - [[#task3][My task 3 header]]
** Planned tasks
- [[#task8][My task 8 header]]
- [[#task9][My task 9 header]]

END ORG SAMPLE

When planning:

- go to "Planning/Planned tasks", and click on any task link, modify whatever
  (todo keyword, tags, timestamps) and get back with 'org-mark-ring-goto' to
  continue your planning.

- Once finished, update all link descriptions to tasks
  (=edu/org-plk-update-descriptions=).

In the code below, I have set a custom description for the links so I can see
more details about the tasks. I have also added a suffix to the description so
I can check whether a link is a planning link or not.

A capture template is required, and an ID property before storing the link,
which can be set automatically with:

  (setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id)

I'm not an (e)lisp coder, so any comments about the code (or whatever) are
welcome.

Some improvements would be great:
  - update link description at point,
  - nice looking planning links (fontify?, have no idea),
  - use another flag for planning link instead of suffix,
  - check for planning links duplicates.

CODE BEGIN HERE

;;; Code:

;; Create an org-capture-template like this:
;;
;;     ("xp"
;;      "Planning Link"
;;      item
;;      (file+olp buffer-name "Planning" "Unplanned")
;;      ;; Insert date timestamp to keep track of link creation
;;      "%<%Y%m%d> [[%L][%(edu/org-plk-insert-last-description)]]"
;;      :immediate-finish t
;;      :jump-to-captured t)

(defcustom edu/org-plk-suffix " (plk)"
  "Custom suffix for Planning Links"
  :group 'edu
  :type 'string)

(defcustom edu/org-plk-template-keys "xp"
  "Custom templates keys to insert a Planning Link"
  :group 'edu
  :type 'string)

(defvar edu/org-plk-last-description ""
  "Last description for Planning Link")

(defun edu/org-plk-format-description ()
  "Format description for Planning Link"
  (let* ((components (org-heading-components))
         (todo (nth 2 components))
         (priority (nth 3 components))
         (headline (nth 4 components))
         (tags (nth 5 components))
         (scheduled (org-entry-get nil "SCHEDULED"))
         (deadline (org-entry-get nil "DEADLINE")))
    (format "[%s/%c/%c%c] %s %s%s"
            (or todo "")
            (or priority ?-)
            (if scheduled ?S ?-)
            (if deadline ?D ?-)
            headline
            (or tags "::")
            edu/org-plk-suffix)))

(defun edu/org-plk-description-from-id (target-id)
  "Planning link description from Link ID"
  (catch 'found
    (org-map-entries
     ;; break on first element found
     #'(throw 'found (edu/org-plk-format-description))
     (format "ID=\"%s\"" target-id))))

(defun edu/org-plk-p (link &optional shift)
  "Predicate to check if link is a Planning Link"
  (let ((shift (or shift 0)))
    (and (string= (org-element-property :type link) "id")
         (string-suffix-p
          edu/org-plk-suffix
          (buffer-substring (+ shift (org-element-property :contents-begin link))
                            (+ shift (org-element-property :contents-end link)))))))

;; based on 'us/update-internal-link-descriptions'
;; https://stackoverflow.com/a/71508831
(defun edu/org-plk-update-descriptions ()
  "Update all Planning Link descriptions in buffer"
  (interactive)
  (save-excursion
    (let ((shift 0))
      ;; map over all links in the buffer
      (org-element-map (org-element-parse-buffer) 'link
        (lambda (link)
          (when (edu/org-plk-p link shift)  ;; filter-in plk's
            (let* ((new-desc-text
                    (edu/org-plk-description-from-id (org-element-property :path link)))
                   ;; shifted because of previous description updates in this run
                   (old-desc-start (+ shift (org-element-property :contents-begin link)))
                   (old-desc-end (+ shift (org-element-property :contents-end link))))
              ;; replace description
              (goto-char old-desc-start)
              (delete-region old-desc-start old-desc-end)
              (insert new-desc-text)
              ;; update shift
              (setq shift (+ shift (- (length new-desc-text)
                                      (- old-desc-end old-desc-start)))))))))))

(defun edu/org-plk-insert ()
  "Create Planning Link for heading at point"
  (interactive)
  (org-store-link nil nil)
  (setq edu/org-plk-last-description (edu/org-plk-format-description))
  (org-capture nil edu/org-plk-template-keys)
  )

(defun edu/org-plk-insert-last-description ()
  "Last Planning Link Description (as a function)"
  edu/org-plk-last-description)

CODE ENDS HERE


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Planning links to tasks
  2022-10-02 19:30 Planning links to tasks Eduardo Suarez
@ 2022-10-02 19:42 ` Eduardo Suarez Santana
  2022-10-03  5:37 ` Ihor Radchenko
  1 sibling, 0 replies; 3+ messages in thread
From: Eduardo Suarez Santana @ 2022-10-02 19:42 UTC (permalink / raw)
  To: emacs-orgmode@gnu.org

Org sample fixed:

BEGIN ORG SAMPLE

...
* Planning
** Planned tasks
- [[#task4][My task 4 header]]
  - [[#task5][My task 5 header]]
  - [[#task1][My task 1 header]]
- [[#task2][My task 2 header]]
  - [[#task7][My task 7 header]]
    - [[#task6][My task 6 header]]
  - [[#task3][My task 3 header]]
** Unplanned tasks
- [[#task8][My task 8 header]]
- [[#task9][My task 9 header]]

END ORG SAMPLE


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Planning links to tasks
  2022-10-02 19:30 Planning links to tasks Eduardo Suarez
  2022-10-02 19:42 ` Eduardo Suarez Santana
@ 2022-10-03  5:37 ` Ihor Radchenko
  1 sibling, 0 replies; 3+ messages in thread
From: Ihor Radchenko @ 2022-10-03  5:37 UTC (permalink / raw)
  To: Eduardo Suarez; +Cc: emacs-orgmode

Eduardo Suarez <esuarez@itccanarias.org> writes:

> Hi, I have just implemented an approach to creating a hierarchy of links to
> tasks, so the hierarchy can be thought of a dependency tree (something like a
> Gantt but with no dates). This approach may be suitable if your org hierarchy
> is not already based on todo dependencies, and there are too many tasks to
> review them often.
>
> The idea is to be able to:
>
> - easily add an item to a plain list in a section named (e.g.)
>   "Planning/Unplanned tasks", consisting of a link to a task in the same
>   buffer (=org-plk-insert=),
>
> - move by text editing this list item into a hierarchy of items in a section
>   named (e.g.) "Planning/Planned tasks", so hierarchy means dependency
>   (somehow).

Have you been using your code for some time now or is it just an
experiment implementing your idea?

> Some improvements would be great:
>   - update link description at point,
>   - nice looking planning links (fontify?, have no idea),
>   - use another flag for planning link instead of suffix,
>   - check for planning links duplicates.

It would be helpful if you provide a more detailed demonstration of your
approach. I imagine something similar (in terms of presentation) to
https://blog.jethro.dev/posts/capturing_inbox/

It is hard to comment anything on your ideas without seeing how your
code actually works.

Also, if you want to hear suggestions about particular parts of the
code, please provide those parts instead of throwing the whole code - it
will make things easier for people who are only interested to answer a
specific question of yours.

> (defun edu/org-plk-description-from-id (target-id)
>   "Planning link description from Link ID"
>   (catch 'found
>     (org-map-entries
>      ;; break on first element found
>      #'(throw 'found (edu/org-plk-format-description))

This is not a valid Elisp syntax.
Check out 13.7 Anonymous Functions section of Elisp manual.

>     (let ((shift 0))
>       ;; map over all links in the buffer
>       (org-element-map (org-element-parse-buffer) 'link
>         (lambda (link)
>           (when (edu/org-plk-p link shift)  ;; filter-in plk's
>             (let* ((new-desc-text
>                     (edu/org-plk-description-from-id (org-element-property :path link)))
>                    ;; shifted because of previous description updates in this run
>                    (old-desc-start (+ shift (org-element-property :contents-begin link)))
>                    (old-desc-end (+ shift (org-element-property :contents-end link))))

You can also use a simple re-search-forward and not bother with `shift'.
Or use org-element-cache-map from the latest main.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-10-05 18:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-02 19:30 Planning links to tasks Eduardo Suarez
2022-10-02 19:42 ` Eduardo Suarez Santana
2022-10-03  5:37 ` Ihor Radchenko

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).