simfish:

Emacs/Tasks

Tasks is org-mode based productivity workflow useful for capturing and organizing task information such as a to-do list.

cover image

Introduction

Emacs org-capture can be used to specify custom templates that are suitable for capturing and saving task information into an org file.

Task information can also be organized by timestamp–start and due time.The configuration in this document extends the stock org-agenda configuration with asynchronous org-file search and org-super-agenda.

The search uses ag(silver-searcher) Linux utility to find files tagged with keywords of interest. For example, it can be configured to look for files containing TODO and WORKING labels. The org-super-agenda package is also used for organizing search results into a convenient agenda view.

Customizations

capture storage variable

(defcustom tasks:default-inbox "${HOME}/Documents/planner/inbox.org"
  "specifies the default inbox file for saving captured information"
  :type '(file)
  :group 'tasks)

capture template

(setq org-capture-templates
      `(("t"
         "Task"
         entry
         (file+headline  tasks::inbox-location    "Tasks")
         "* TODO %?\nDEADLINE:%^t\n%i\n/see/: %a")))

Task search paths

(defcustom agenda::search-paths
 `( ,(expand-file-name "~/Documents/KB")
    ,(expand-file-name "~/Documents/planner")
    ,(expand-file-name "~/Documents/research/notes"))
  "List of static directory paths where org-agenda files are stored."
  :type '(file))

Key Bindings

Capturing Information

(kb::def :states 'normal
  "o"    '(:ignore t            :which-key    "Org" )
  "oc"   '(org-capture          :which-key    "Capture")
  "oi"   '(tasks::find-inbox    :which-key    "Inbox"))

Reviewing information

(kb::def :states 'normal
  "o"  '(:ignore t "Org")
  "oa" '(tasks::org-agenda-open   :which-key "agenda"))

Commands

Capture commands

org-capture

Agenda commands

tasks::org-agenda-open

Functions

Inbox Location

(defun tasks::inbox-location ()
  "Returns the location for storing captured information."
  (require 'fs)
  (let ((inbox-file (substitute-in-file-name  tasks:default-inbox)))
    ;;setup capture file path
    (fs::dir-ensure (file-name-directory inbox-file))
    inbox-file))

Open Inbox

(defun  tasks::find-inbox ()
  "Opens the current project's inbox.org file"
  (interactive)
  (require 'fs)
  (let ((inbox-file  (tasks::inbox-location)))
    (find-file inbox-file)))

Agenda

(defun tasks::org-agenda-load ()
  "scan and initialize  `org-agenda-files'"
  (require 's)
  (let ((search-path-list agenda::search-paths)
        (cmd                   nil)
        (r                     nil)
        (org-agenda-files      nil)
        (org-agenda-file       nil))

    (setq cmd (with-temp-buffer
                (cl-loop
                 for p in search-path-list
                 do (insert "ag -l -U --hidden --org 'TODO|WORKING|DEADLINE|SCHEDULED' " "\"" p  "\""  " | grep -v 'forks'" "\n" ))
                (buffer-string)))
    (setq r   (shell-command-to-string cmd))
    (setq r   (s-lines r))

    (while (setq org-agenda-file (car r))
      (setq r (cdr r))
      (when (and  (stringp org-agenda-file)
                  (not (string-empty-p org-agenda-file))
                  (file-exists-p org-agenda-file))
        (cl-pushnew  (expand-file-name org-agenda-file)  org-agenda-files)))

    org-agenda-files))


(defun tasks::org-agenda-open ( )
  "Launches current project agenda browser and the journal directory."
  (interactive)
  (require 'log)
  (require 'org-super-agenda)
  (setq org-agenda-files (tasks::org-agenda-load))
  (org-agenda nil "c" ))

Packages

Package: org-capture

(use-package org-capture
  :demand t
  :commands
  <<org-capture-commands>>
  :general
  <<org-capture-kb>>
  :config
  <<org-capture-config>>)

Package: org-agenda

(use-package org-agenda
  :demand t
  :commands
  <<org-agenda-commands>>
  :init
  (defalias 'tasks::org-agenda-open-super   'org-super-agenda)
  <<org-agenda-init>>
  :general
  <<org-agenda-kb>>
  :config
  (require 'org-super-agenda))

Package: org-super-agenda

(use-package ts
  :guix (:name emacs-ts))

(use-package org-super-agenda
  :guix (:name emacs-org-super-agenda)
  :demand t
  :after org-agenda
  :init
  (setq org-agenda-skip-scheduled-if-done t
        org-agenda-skip-deadline-if-done t
        org-agenda-include-deadlines nil
        org-agenda-block-separator nil
        org-agenda-compact-blocks t
        org-agenda-start-day nil ;; i.e. today
        org-agenda-span 1
        org-agenda-start-on-weekday nil)
  (setq org-agenda-custom-commands
        '(("c" "Super view"
           ((agenda  "" ((org-agenda-overriding-header "")
                         (org-super-agenda-groups
                          '((:name "Today" :time-grid t :date today  :order 1)))))
            (alltodo "" ((org-agenda-overriding-header "")
                         (org-super-agenda-groups
                          '((:log t)

                            (:name "Due Today" :deadline today :order 2)
                            (:name "Working"   :todo "WORKING" :order 3)

                            (:name "Overdue"   :deadline past  :order 4)
                            (:name "Important" :priority "A"   :order 5)
                            (:name "Scheduled Soon" :scheduled future :order 6)

                            (:name "Todos"      :todo "TODO" :order 7)
                            (:discard (:anything t))
                            ;;(:name "Today's tasks" :file-path "journal/")
                            ))))))))
  :config
  (org-super-agenda-mode))

Package: silver searcher

(use-package the-silver-searcher
 :guix (:name the-silver-searcher)
 :disabled)