1

Given a plain list like:

- buy tea
- call Anna
- Reply email to John
- pay bill 1
- phone Derick
- Reply to grad-pa

which you don't want to sort alphabetically, how can you sort it? Things like 'call' or 'phone' should go into the same category.

How could put the elements into separate categories like:

* contact
  - phone Derick
  - call Anna
* Money
  - pay bill 1
  - buy tea

Otherwise, I'd need to through the whole list several times and copy and paste all elements of each category, instead of going through it only once and marking the list items, and then sort them with a function.

2

The basic way to sort lists is with org-sort (C-c ^). It will offer you a number of different sorting options one of which (f) lets you call a custom sorting function. This function will be called on each entry and should return either a string or a number that will be used as a key to sort. You will need to write a custom function to order things the way you want.

0

Here's some code that lets you run M-x category-sort-this-buffer to sort the lines in the current buffer into specified categories.

Before evaluating it, you should change the puthash calls categories->words to the categories and trigger words you want.

(defvar categories->words
  (let ((table (make-hash-table :test #'equal)))
    (puthash "money" (list "buy" "pay" "purchase") table)
    (puthash "contact" (list "phone" "call" "email" "reply") table)
    (puthash "thing3" (list "the-rest") table)
    table))

(defvar words->categories
  (let ((table (make-hash-table :test #'equal)))
    (maphash (lambda (category words)
               (dolist (word words)
                 (puthash word category table)))
             categories->words)
    table)
  "A table mapping various words to the category they're in")

(defun get-category-for-line (line)
  "Return the category for LINE, defaulting to DEFAULT."
  (gethash (downcase (second (split-string line)))
           words->categories
           "uncategorized"))

(defun category-sort-this-buffer ()
  "Sort this buffer by category"
  (interactive)
  (let ((lines (split-string (buffer-string) "\n" t))
        (last-category nil))
    (erase-buffer)
    (dolist (new-line (cl-sort lines
                               #'string-lessp
                               :key #'get-category-for-line))
      (let ((current-category (get-category-for-line new-line)))
        (unless (equal last-category
                       current-category)
          (setq last-category current-category)
          (insert "* " current-category "\n"))
        (insert new-line "\n")))))

It sets up two variables to hold the categories and words relationships, pulls the contents of the buffer out, sorts it, and puts the lines back in with category names. So your example:

- buy tea
- call Anna
- Reply email to John
- pay bill 1
- phone Derick
- Reply to grad-pa

ends up as:

* contact
- call Anna
- Reply email to John
- phone Derick
- Reply to grad-pa
* money
- buy tea
- pay bill 1

Note that this will, if a line doesn't have a category, be put in a category labeled "uncategorized". You could change that in #'category-sort-this-buffer.

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.