Mi configuración de org-mode

Aviso previo: Esta configuración es una copia de una que encontré por "el internet" hace mucho tiempo y ya no soy capaz de dar de nuevo con el enlace original ¬¬

Org-Mode es una maravilla que forma parte de ese sistema operativo llamado "Emacs". Lo mismo sirve para editar documentación y exportarlo a PDF, HTML, ODT... que sirve para gestionar tareas, escribir wikis, dibular diagramas como código. Es una herramienta muy útil y que a nivel laboral me ha sacado de más de un lío.

Ejemplo de por qué Org-Mode me ha sacado de más de un lío: en el proyecto en el que estoy currando actualmente tengo que llevar la IaC de una decena de subproyectos en paralelo. Aunque las peticiones se procesan por Jira, el estado de las tareas y las personas a las que se asignan me impide ver, de un sólo vistazo, el avance de todas las tareas en su conjunto. ¿Solución? Org-mode. Un fichero por cada subproyecto con las tareas en estados TODO, INPROGRESS, BLOCKED, DONE... incluso para tener un diario de las reuniones que he tenido con las personas de cada proyecto...

Configurando Org-Mode

Doy por supuesto que tienes emacs, spacemacs o similar configurado y te desenvuelves más o menos. Os voy a mostrar la configuración en Spacemacs.

Lo primero que hacemos, en el fichero de configuración, es añadir org y plantuml a la lista de "layers"

dotspacemacs-configuration-layers
   '(
     emacs-lisp
     .....
     git
     helm
     markdown
     multiple-cursors
     org
     (plantuml :variables plantuml-jar-path "~/Software/plantUml.jar")
     ....
     treemacs)

Pongo sólo unas líneas de ejemplo. En el caso de plantuml hay que indicar donde nos hemos descargado el .jar de la aplicación.

Nos vamos a la sección (defun dotspacemacs/user-config () y añadimos el siguiente código. Lo voy a poner a pedazos para ir explicándolo y al final lo tenéis entero:

En esta primera sección configuramos plantuml, que es una herramienta para dibujar diagramas mediante código.

(with-eval-after-load 'org
  (setq org-plantuml-jar-path (expand-file-name "~/Software/plantUml.jar"))
  (add-to-list 'org-src-lang-modes '("plantuml" . plantuml))
  (org-babel-do-load-languages 'org-babel-load-languages '((plantuml . t)))

A continuación indicamos donde se almacenarán los ficheros de Org-mode. En mi caso los tengo subidos a un NextCloud, así los puedo compartir entre varios ordenadores, el móvil...

El fichero refile.org lo usaremos para ir metiendo las tareas de forma rápida hasta que decidamos dónde deben estar ya organizadas y las iremos moviendo a los ficheros definitivos.

  (setq org-directory "~/nextCloud/org")
  (setq org-default-notes-file "~/nextCloud/org/refile.org")

En la siguiente sección indicamos las secuencias de evolución que pueden tener las tareas. En mi caso es bastante sencillo y se puede complicar hasta el infinito y más allá. Mediante la admiración "!" indicamos a org que rellene la fecha en la que se hace el cambio de estado. En el caso de poner "@/" lo que hacemos es que podremos rellenar el motivo por el cual una tarea se bloquea o se cancela.

En la segunda parte de esta sección indicamos el color con el que se van a pintar las tareas en función de su estado

  (setq org-use-fast-todo-selection t)
  (setq org-todo-keywords
        '((sequence "TODO(t)" "INPROGRESS(i!)" "|" "DONE(d!)")
          (sequence "BLOCK(b@/!)" "|" "CANCELLED(c@/!)" "CALL" "MEETING")))
  (setq org-todo-keyword-faces
        (quote (("TODO" :foreground "orange" :weight bold)
                ("INPROGRESS" :foreground "blue" :weight bold)
                ("BLOCK" :foreground "red" :weight bold)
                ("DONE" :foreground "forest green" :weight bold)
                ("CANCELLED" :foreground "forest green" :weight bold)
                ("CALL" :foreground "blue" :weight bold)
                ("MEETING" :foreground "blue" :weight bold))))
  (setq org-todo-state-tags-triggers
        (quote (("BLOCK" ("BLOCK" . t))
               ("CANCELLED" ("CANCELLED" . t))
                ("INPROGRESS" ("BLOCK"))
                ("DONE" ("BLOCK"))
                ("TODO" ("BLOCK") ("CANCELLED")))))

Asociamos una combinación de tectlas para "capturar" así como unas plantillas que nos mostrarán un menú cuando ejecutemos el comando C-c c pudiendo añadir una tarea TODO al fichero refile.org, añadir una entrada al diario, añadir y cronometrar una reunión o una llamada de teléfono.

Por último definimos un número máximo de subniveles

  (global-set-key (kbd "C-c c") 'org-capture)
  ;; Capture templates for: TODO tasks, Notes, appointments, phone calls, meetings, and org-protocol
  (setq org-capture-templates
        (quote (("t" "todo" entry (file "~/nextCloud/org/refile.org")
                 "* TODO %?\n%U\n%a\n" :clock-in t :clock-resume t)
                ("j" "Journal" entry (file+datetree "~/nextCloud/org/diary.org")
                 "* %?\n%U\n" :clock-in t :clock-resume t)
                ("m" "Meeting" entry (file "~/nextCloud/org/refile.org")
                 "* MEETING with %? :MEETING:\n%U" :clock-in t :clock-resume t)
                ("c" "Phone call" entry (file "~/nextCloud/org/refile.org")
                 "* CALL %? :CALL:\n%U" :clock-in t :clock-resume t))))
  (setq org-refile-targets
        (quote ((nil :maxlevel . 9)
                (org-agenda-files :maxlevel . 9 ))))
)

Y aquí está todo el código completo:

(with-eval-after-load 'org
  (setq org-jira-custom-jqls
        '(
          (:jql " assignee = currentUser() and resolution = unresolved order by created DESC"
                :limit 100
                :filename "my-work")
          ))
  (setq org-plantuml-jar-path (expand-file-name "~/Software/plantUml.jar"))
  (add-to-list 'org-src-lang-modes '("plantuml" . plantuml))
  (org-babel-do-load-languages 'org-babel-load-languages '((plantuml . t)))
  (setq org-directory "~/disroot/org")
  (setq org-default-notes-file "~/disroot/org/refile.org")
  (setq org-use-fast-todo-selection t)
  (setq org-todo-keywords
        '((sequence "TODO(t)" "INPROGRESS(i!)" "|" "DONE(d!)")
          (sequence "BLOCK(b@/!)" "|" "CANCELLED(c@/!)" "CALL" "MEETING")))
  (setq org-todo-keyword-faces
        (quote (("TODO" :foreground "orange" :weight bold)
                ("INPROGRESS" :foreground "blue" :weight bold)
                ("BLOCK" :foreground "red" :weight bold)
                ("DONE" :foreground "forest green" :weight bold)
                ("CANCELLED" :foreground "forest green" :weight bold)
                ("CALL" :foreground "blue" :weight bold)
                ("MEETING" :foreground "blue" :weight bold))))
  (setq org-todo-state-tags-triggers
        (quote (("BLOCK" ("BLOCK" . t))
               ("CANCELLED" ("CANCELLED" . t))
                ("INPROGRESS" ("BLOCK"))
                ("DONE" ("BLOCK"))
                ("TODO" ("BLOCK") ("CANCELLED")))))
  (global-set-key (kbd "C-c c") 'org-capture)
  ;; Capture templates for: TODO tasks, Notes, appointments, phone calls, meetings, and org-protocol
  (setq org-capture-templates
        (quote (("t" "todo" entry (file "~/disroot/org/refile.org")
                 "* TODO %?\n%U\n%a\n" :clock-in t :clock-resume t)
                ("j" "Journal" entry (file+datetree "~/disroot/org/diary.org")
                 "* %?\n%U\n" :clock-in t :clock-resume t)
                ("m" "Meeting" entry (file "~/disroot/org/refile.org")
                 "* MEETING with %? :MEETING:\n%U" :clock-in t :clock-resume t)
                ("c" "Phone call" entry (file "~/disroot/org/refile.org")
                 "* CALL %? :CALL:\n%U" :clock-in t :clock-resume t))))
  (setq org-refile-targets
        (quote ((nil :maxlevel . 9)
                (org-agenda-files :maxlevel . 9 ))))
)