From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alex =?utf-8?Q?Benn=C3=A9e?= Subject: Best approaches for implementing a developer workflow using ORG? Date: Fri, 08 Jul 2016 17:27:49 +0100 Message-ID: <87r3b4p01m.fsf@linaro.org> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:57578) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bLYd7-0008NX-9T for emacs-orgmode@gnu.org; Fri, 08 Jul 2016 12:27:54 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bLYd2-0006rL-S8 for emacs-orgmode@gnu.org; Fri, 08 Jul 2016 12:27:52 -0400 Received: from mail-wm0-x236.google.com ([2a00:1450:400c:c09::236]:37698) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bLYd2-0006r5-5g for emacs-orgmode@gnu.org; Fri, 08 Jul 2016 12:27:48 -0400 Received: by mail-wm0-x236.google.com with SMTP id k123so16499282wme.0 for ; Fri, 08 Jul 2016 09:27:47 -0700 (PDT) Received: from zen.linaro.local ([81.128.185.34]) by smtp.gmail.com with ESMTPSA id p126sm3773289wmp.13.2016.07.08.09.27.44 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 08 Jul 2016 09:27:44 -0700 (PDT) Received: from zen (localhost [127.0.0.1]) by zen.linaro.local (Postfix) with ESMTPS id 6A30D3E024F for ; Fri, 8 Jul 2016 17:27:49 +0100 (BST) List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: "Emacs-orgmode" To: emacs-orgmode@gnu.org Hi, As a developer I spend a lot of time moving back and forth between email messages and COMMIT buffers copying and pasting review and signoff tags. I've been investigating if there is anyway I can streamline this work using org-mode. The first step is fairly easy. When I come across an email that has review comments or tags I can use org-capture to store a link under a sub-heading of my reviews.org file: #+name: capture-steps #+begin_src emacs-lisp (setq org-capture-templates '( ("g" "Save reference to review tag" checkitem (file+headline "review.org" "Review Tags") " - [ ] %a" :immediate-finish t) ("r" "Review Comment (email)" checkitem (file+headline "review.org" "Review Comments") " - [ ] %a"))) (defvar my-dco-tag-re (rx (: bol (zero-or-more (in blank)) ;; fresh line (any "RSTA") (one-or-more (in alpha "-")) "-by: " ;; tag (one-or-more (in alpha blank "<>@.")) ;; person eol)) "Regexp to match DCO style tag.") (defun my-capture-review-tags () "Return a list of tags for current buffer" (let ((tags)) (save-excursion (goto-char (point-min)) (while (re-search-forward my-dco-tag-re (point-max) t) (add-to-list 'tags (match-string-no-properties 0)))) tags)) (defun my-org-maybe-capture-review-tag () "Check buffer for DCO tags and if found queue a review comment." (interactive) (when (my-capture-review-tags) (org-capture nil "g"))) (when (fboundp 'mu4e-view-mode-map) (define-key mu4e-view-mode-map (kbd "C-c C-c") 'my-org-maybe-capture-review-tag)) #+end_src My stumbling block is now how do I approach automating the application of tags when I'm in a magit COMMIT buffer. After some fumbling about I can navigate my org file and find links that match a given patch title (which generally matches the email title as they start as git-send-email patch series): #+name: automating-tag-fetching #+begin_src emacs-lisp (defun my-org-get-elements (file heading) "Search FILE for HEADING and return the AST of that heading." (interactive) (let ((org-buf (org-capture-target-buffer file))) (with-current-buffer org-buf (org-element-map (org-element-parse-buffer) 'headline (lambda (hl) (when (string-match heading (org-element-property :raw-value hl)) (identity hl))))))) (defun my-org-get-unchecked-items (items) "Return the AST of unchecked ITEMS." (org-element-map items 'item (lambda (item) (when (eq (org-element-property :checkbox item) 'off) (org-element-contents item))))) (defun my-org-visit-link-and-snarf-tags () "Visit org-link-at-point and return a set of tags." (save-window-excursion (save-excursion (org-open-at-point t) (my-capture-review-tags)))) (defun my-org-find-review-tags (subject) "Search saved review tags, looking for `SUBJECT' match." (interactive) (let* ((ast (my-org-get-elements "review.org" "Review Tags")) (buffer (org-capture-target-buffer "review.org")) (unchecked (my-org-get-unchecked-items ast)) (tags)) (org-element-map unchecked 'link (lambda (link) (let ((beg (org-element-property :begin link)) (end (org-element-property :end link))) (with-current-buffer buffer (when (string-match-p subject (buffer-substring-no-properties beg end)) (add-to-list 'tags (my-org-visit-link-and-snarf-tags))))))) (when tags (mapconcat 'symbol-name tags "\n")))) #+end_src I'm not sure if my parsing of the tree is as efficient as it should be, especially the manual grubbing about with :begin and :end of link to match the link subject. However the main problem is my-org-visit-link-and-snarf-tags doesn't work as expected because there doesn't seem to be a way to visit an org-link in the background to gather the data I need. Really I want to visit the resulting buffer that org-open-at-point visits in a (with-current-buffer &body) style visit. I have tried the other option of inserting the tags as data for the capture by doing a kill-new and a template like: #+name: alternative-template #+begin_src emacs-lisp (setq org-capture-templates '( ("g" "Save reference to review tag" checkitem (file+headline "review.org" "Review Tags") " - [ ] %a\n%c" :immediate-finish t) ("r" "Review Comment (email)" checkitem (file+headline "review.org" "Review Comments") " - [ ] %a"))) #+end_src But that seemed to cause problems when capturing multiple checkbox links in a row. Maybe there is some way to stuff some meta-data in the link? However ideally I'd like to solve the problem of programitically following org-links as I'd like to automate the bringing up of review comments when I doing re-basing. It is of course possible that I'm abusing org-mode a bit too much using it in this way and I should use something more database like to store this stuff. However I would appreciate any suggestions of ways to tackle this problem. Regards, -- Alex Bennée