When working with phone calls and tickets, I use Emacs in Org mode to pre-create the entry with the heading containing the current date and time. For obvious reasons, if not constantly using a new file (which would make history searches more difficult), I end up with a very long flat list of call headings and their respective contents.

I now want to change that, so that I get a top-level header with the year, a second-level header with the month and then a third-level header with the actual call entry.

In my trials, I manage to get the results when using the first entry inside the call file, but as soon as I get the second (third, fourth), the indentation is getting deeper with each entry. I also experimented with "post-editing" the automation (e.g. (org-insert-subheading t) (beginning-of-line) (delete-char 1) (end-of-line)), but I find that very messy to the point that items like (org-insert-heading) would have no meaning anymore.

The result shall look somewhat like this:

* <2019>
** <12>
*** call <date&time_of_call>
*** call <date&time_of_call>
* <2020>
** <01>
*** call <date&time_of_call>
*** call <date&time_of_call>
** <02>
*** call <date&time_of_call>
*** call <date&time_of_call>

My code so far looks like this (I call eltest with a key shortcut):

(defvar sFilePath "~/Documents/Emacs/"
  "Path to directory.")

(defvar sTestEntryYear "<%Y>"
  "Year format string for entry headings.")
(defvar sTestEntryMonth "<%m>"
  "Month format string for entry headings.")
(defvar sTestEntry "<%a, %Y-%m-%d %H:%M:%S>"
  "Date & time format string for entry headings.")

(defun insert_test_template ()
  "Insert the test template"
      ((lambda ()
     (org-insert-subheading t)
     (insert (concat "Calls " sNow " Call|WalkUp: ProblemDescription\n\n"))
     (insert "template goes on here\n")
     (insert "RESULT\n")
     (insert "-> "))))

(defun eltest ()
  "Add a new call entry."
  (switch-to-buffer (find-file (concat sFilePath "Test.org")))
  (let ((sThisYear (format-time-string sTestEntryYear)) (sThisMonth (format-time-string sTestEntryMonth)) (sNow (format-time-string sTestEntry)))
    (unless (org-goto-local-search-headings sThisYear nil t)
      ((lambda ()
     (org-insert-heading nil nil t)
     (insert (concat sThisYear "\n")))))
    (unless (org-goto-local-search-headings sThisMonth nil t)
      ((lambda ()
     (org-insert-subheading t)
     (insert (concat sThisMonth "\n")))))
    (unless (org-goto-local-search-headings sNow nil t)
      ((lambda ()
    (while (progn
         (previous-line 1)
         (not (looking-at "^- Name  : $"))))
  • 1
    Have you looked at datetrees? – NickD Jun 3 at 22:08
  • 1
    Not yet due to me not knowing about its existence. Don't get me wrong, I do use the manual inside Emacs as well, but when one does not know what to look for, it becomes quite daunting to find stuff. I will see, if I can make sense of it for my purpose. Thanks so far! – Phoenix Jun 4 at 4:42

What you're asking for looks like Org Capture Templates.

(define-key global-map "\C-cc" 'org-capture)

(setq org-capture-templates
'(("c" "Calls arranged in a date tree" entry
    (file+datetree "~/calls.org" "Calls and Meetings")
    "* %^{type|Call|WalkUp|Meeting}: %^{problem} %T
     + %?

     +  RESULT
        + "
    :clock-in t :clock-resume t)))

To use the template with the given key binding, you hit C-c c c as soon as you get a call or a walk-up. The template prompts you for the type, then lets you enter a problem description. You are placed into a capture buffer with the text insert point at the location of the %? in the template - in this case I made it a list that you can add lines to with M-RET.

To file the event from the capture buffer, you hit C-c C-c, or C-c C-k to abort.

The result is very similar to what you asked for:

* Calls and Meetings
** 2020
*** 2020-06 June
**** 2020-06-04 Thursday
***** DONE Call: Stuff got broken <2020-06-04 Thu 09:08>
      - State "DONE"       from "STARTED"    [2020-06-04 Thu 09:08]
      - State "STARTED"    from              [2020-06-04 Thu 09:01]
      CLOCK: [2020-06-04 Thu 09:01]--[2020-06-04 Thu 09:08] =>  0:07
         + I resolved the issue by fixing the widget.
         + RESULT
           + FIXED!

The template additionally starts a clock which gives you time tracking, but you can eliminate that if you'd like.


| improve this answer | |
  • 1
    As with all major new functions I discover in Emacs, this is entirely mind-blowing and jaw-dropping. Thank you very much for the example. It is so much easier to learn such complex features seeing even a single, proper example. The manual and a lot of online resources unfortunately lack such things a lot of times leaving me stranded and reeling to work it out with painstaking trial and error. Therefore: Thank you very much! You got my vote (and would get another, if I could). – Phoenix Jun 4 at 17:39
  • I saw your plea in the comment - glad it blows your mind. I learn new things nearly every week after 25+ years of Emacs. The clocking stuff is amazing when combined with Org Agenda, which is a whole universe in itself! – gregoryg Jun 4 at 17:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.