;;; init-config.el --- Configuración de org-mode   -*- lexical-binding: t -*-

;; Author: kj <webmaster@outcontrol.net>
;; URL: https://git.kj2.me/kj/confi-emacs-actual

;;; Commentary:

;; Aquí se encuentran todas las configuraciones relacionadas a org-mode.
;;
;; org-mode es un de los reclamos más potentes de Emacs. Aunque solo es
;; un formato de texto enrriquecido, básicamente algo similar a
;; markdown, Emacs es el que lo ha llevado muy bien y probalemente el que
;; mejor lo soporta.
;;
;; Cabe mencionar que este modo es también el predefinido para todo un
;; ecosistema dentro de Emacs, como es el caso de la agenda o la base de
;; conocimientos org-roam.

;;; Code:
(defun kj/org-hook ()
  "Configuración para el hook de 'org-mode'."

  (display-line-numbers-mode 0)
  ;; (variable-pitch-mode 1)
  (visual-line-mode 1)
  (visual-fill-column-mode 1)

  ;; Configuración de fonts
  ;; (set-face-attribute (car face) nil :font "Cantarell" :weight 'regular :height (cdr face))

  ;; Ensure that anything that should be fixed-pitch in Org files appears that way
  ;; (set-face-attribute 'org-hide nil :inherit 'fixed-pitch)
  ;; (set-face-attribute 'org-block nil :foreground 'unspecified :inherit 'fixed-pitch)
  ;; (set-face-attribute 'org-code nil   :inherit '(shadow fixed-pitch))
  (setq org-fontify-quote-and-verse-blocks t) ;; Permitir configuración de bloques quote y verse.
  ;; (set-face-attribute 'org-block nil :underline nil :foreground nil :background "#282a36")
  ;; (set-face-attribute 'org-block-begin-line nil :underline nil :foreground nil :background "#1e1f28")
  ;; (set-face-attribute 'org-block-end-line nil :underline nil :foreground nil :background nil)
  ;; (set-face-attribute 'org-block-end-line nil :background 'unspecified)
  (set-face-attribute 'org-table nil   :inherit '(shadow fixed-pitch))
  (set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
  (set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
  (set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
  (set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch)

  ;; (set-face-attribute 'org-block nil :background
  ;;                   (color-darken-name
  ;;                    (face-attribute 'default :background) 3))

  ;; (setq org-src-block-faces '(("emacs-lisp" (:background "#EEE2FF"))
  ;;                           ("python" (:background "#E5FFB8"))))

  ;; Tachar los elementos "DONE"
  (set-face-attribute 'org-done nil :strike-through t)
  (set-face-attribute 'org-headline-done nil
                      :strike-through t
                      :foreground "light gray")

  ;; Embellecer las prioridades
  (setq org-highest-priority ?A
        org-default-priority ?B
        org-lowest-priority  ?D) ;; Cambiar prioridades de A,B,C a A,B,C,D
  (push '("[#A]" . "⚡" ) prettify-symbols-alist)
  (push '("[#B]" . "🔥" ) prettify-symbols-alist)
  (push '("[#C]" . "🐢" ) prettify-symbols-alist)
  (push '("[#D]" . "☕" ) prettify-symbols-alist)
  ;; (push '("#+begin_quote" . "❝" ) prettify-symbols-alist)
  ;; (push '("#+end_quote" . "❞" ) prettify-symbols-alist)
  ;; (push '("#+begin_export" . "📤" ) prettify-symbols-alist)
  ;; (push '("#+end_export" . "⎯" ) prettify-symbols-alist)
  ;; (push '("#+begin_comment" . "📝" ) prettify-symbols-alist)
  ;; (push '("#+end_comment" . "⎯" ) prettify-symbols-alist)
  ;; (push '("#+begin_src" . "❯" ) prettify-symbols-alist)
  ;; (push '("#+end_src" . "⎯" ) prettify-symbols-alist)
  ;; (push '("#+begin_example" . "🦉" ) prettify-symbols-alist)
  ;; (push '("#+end_example" . "⎯" ) prettify-symbols-alist)
  (prettify-symbols-mode)

  ;; Habilitar evaluación de lenguajes en org-mode (babel)
  (org-babel-do-load-languages 'org-babel-load-languages
                               (append org-babel-load-languages
                                       '(
                                         (C . t)
                                         (R . t)
                                         (awk . t)
                                         (calc . t)
                                         (clojure . t)
                                         (go . t)
                                         (haskell . t)
                                         (java . t)
                                         (js . t)
                                         (php . t)
                                         (python . t)
                                         (rust . t)
                                         (translate . t)
                                         (shell . t)
                                         )))
  ;; No solicitar confirmación para evaluar
  (setq org-confirm-babel-evaluate nil)
  )

;; org-mode
(use-package org
  :defer t
  :ensure nil
  :bind (("C-c a" . org-agenda)
         ("C-c c" . org-capture))
  :hook
  (org-mode . kj/org-hook)
  :config
  (setq org-ellipsis " ▾")
  (setq org-hide-emphasis-markers t)
  ;;(setq org-startup-folded 'content)

  (setq org-agenda-start-with-log-mode t)
  (setq org-log-done 'time)
  (setq org-log-into-drawer t)
  (setq org-cycle-separator-lines -1)

  ;; Identación
  (setq org-startup-indented t)
  (setq org-src-preserve-indentation nil)
  (setq org-edit-src-content-indentation 0)
  (setq org-src-tab-acts-natively t)

  ;; Palabras claves del To Do de org-mode
  (setq org-todo-keywords
        ;;'((sequence "☐" "✔" "⌛" "❌")))
        '((sequence "TODO(t)" "DOING(n)" "WAITING(w)" "|" "DONE(d!)" "CANCELED(c!)")))
  (setq org-todo-keyword-faces
        '(("TODO" . "#ff6464")
          ("DOING" . "yellow")
          ("DONE" . "green")
          ("HOLD" . "orange")
          ("CANCELED" . "#aaa"))
        )

  ;; Tachar los checkbox marcados como terminados
  (defface org-checkbox-done-text
  '((t (:foreground "#71696A" :strike-through t)))
  "Face for the text part of a checked org-mode checkbox.")

  (font-lock-add-keywords
   'org-mode
   `(("^[ \t]*\\(?:[-+*]\\|[0-9]+[).]\\)[ \t]+\\(\\(?:\\[@\\(?:start:\\)?[0-9]+\\][ \t]*\\)?\\[\\(?:X\\|\\([0-9]+\\)/\\2\\)\\][^\n]*\n\\)"
      1 'org-checkbox-done-text prepend))
   'append)

  ;; Archivos a usarse en org-agenda
  (setq org-agenda-files
        '("~/Documentos/ORG/Agenda/Tareas.org")
        )

  ;; Archivos entre los que se moverán las tareas
  (setq org-refile-targets
        '(("Archivo.org" :maxlevel . 1)
          ("Tareas.org" :maxlevel . 1)))

  ;; Guardar los archivos cuando se muevan tareas entre ellos
  (advice-add 'org-refile :after 'org-save-all-org-buffers)

  (setq org-capture-templates
        `(("t" "Tareas")
          ("tt" "Tareas" entry (file+olp "~/Documentos/ORG/Agenda/Tareas.org")
           "* TODO %? \n %a\n %i" :empty-lines 1)
          )
        )

  ;; Configuración de imágenes
  (setq org-startup-with-inline-images t) ;; Mostrar por defecto las imágenes
  (setq org-display-remote-inline-images 'cache) ;; Mostrar imágenes remotas
  (setq org-image-actual-width 512)
  )

;; Org-yt para soportar embebidos.
(use-package org-yt
  :after org
  :ensure (:host github :repo "TobiasZawada/org-yt")
  :config
  (defun org-http-image-data-fn (protocol link _description)
    "Interpret LINK as an URL to an image file."
    (when (and (image-type-from-file-name link)
               (not (eq org-display-remote-inline-images 'skip)))
      (if-let (buf (url-retrieve-synchronously (concat protocol ":" link)))
          (with-current-buffer buf
            (goto-char (point-min))
            (re-search-forward "\r?\n\r?\n" nil t)
            (buffer-substring-no-properties (point) (point-max)))
        (message "Download of image \"%s\" failed" link)
        nil)))
  (org-link-set-parameters "http"  :image-data-fun #'org-http-image-data-fn)
  (org-link-set-parameters "https" :image-data-fun #'org-http-image-data-fn)
  )

;; Los head "*" se ven como puntos
(use-package org-bullets
  :defer t
  :hook
  (org-mode . org-bullets-mode)
  :config
  (setq org-bullets-bullet-list '("◉"
                                  "○"
                                  "●"
                                  "◈"
                                  "◇"
                                  "◆"
                                  "✸"
                                  "✳"))
  )

;; Mejora visualmente varias cosas de org
(use-package org-modern
  :defer t
  :ensure t
  :hook ((org-mode . org-modern-mode)
         (org-agenda . org-modern-mode))
  :config
  ;; Me gustan varias cosas por defecto, así que desactivo aquí varias de las "mejoras"
  (setq org-modern-table nil                ;; Mejora visual de las tablas
        org-modern-table-vertical 1         ;; Grosor de las líneas verticales de las tablas
        org-modern-table-horizontal 0.2     ;; Grosor de las líneas horizontales de las tablas
        org-modern-priority nil             ;; Mejora de las prioridades (Arriba ya las puse bonitas con prettyfy-symbols, así que mejor está desactivado)
        org-modern-todo nil                 ;; Mejora visual a las lista de tareas
        org-modern-statistics nil           ;; Mejora visual a las estadísticas de completado de uan tarea (ej: [50%] o [5/9])
        org-modern-checkbox nil             ;; Mejora de los checkboxes (a mi parecer se ven más feos, los por defecto ya están bonitos).
        org-modern-keyword nil              ;; Oculta el "#+" en los keywords de org
        org-modern-block-name nil           ;; Mejora visual para los org blocks (bloques de código, ejemplo, citas, etc.)
        org-modern-star nil                 ;; Lista de bullets a usar en los headers (falla si se activa junto a org-bullets).
        org-modern-list nil)
  )

(use-package visual-fill-column
  :defer t
  :after (org)
  :config
  ;; Tamaño de la columna
  (setq-default visual-fill-column-width 150)
  ;; Centrar el texto
  (setq-default visual-fill-column-center-text t
                visual-fill-column-adjust-for-text-scale nil
                visual-fill-column-enable-sensible-window-split t)
  )

;; Segundo cerebro: Base de conocimientos en formato Zettelkasten
(use-package org-roam
  :defer t
  :ensure t
  :bind (("<f4>" . org-roam-node-insert)
         ("<f3>" . org-roam-node-find))
  :init
  (setq org-roam-v2-ack t)
  (setq org-roam-completion-system 'ivy)
  :custom
  (org-roam-directory "~/Documentos/ORG/Notas")
  (org-roam-completion-everywhere t)
  :config
  (org-roam-setup))

;; Interface web para navegar en mi base de conocimientos.
(use-package org-roam-ui
  :defer t
  :ensure t
  :config
  (setq org-roam-ui-sync-theme t
        org-roam-ui-follow t
        org-roam-ui-update-on-save t
        org-roam-ui-open-on-start t))

;; Continúa el formato de la lista cuando presionas enter.
(use-package org-autolist
  :defer t
  :ensure t
  :hook (org-mode . org-autolist-mode))

;; Org babel para PHP
(use-package ob-php
  :defer t
  :ensure t)

;; Org babel para GO
(use-package ob-go
  :defer t
  :ensure t)

;; Org babel para Rust
(use-package ob-rust
  :defer t
  :ensure t)

;; Org babel para traducciones (mediante google translate)
(use-package ob-translate
  :defer t
  :ensure t)

;; Org mode en modo presentación
(use-package org-present
  :defer t
  :after (org)
  :config
  (add-hook 'org-present-mode-hook
            (lambda ()
              (org-display-inline-images)
              (org-present-hide-cursor)
              (org-present-read-only)
              ))
  (add-hook 'org-present-mode-quit-hook
            (lambda ()
              ;; (org-remove-inline-images)
              (org-present-show-cursor)
              (org-present-read-write)))

  (add-hook 'org-present-after-navigate-functions
            (lambda ()
              ;; Show only top-level headlines
              (org-overview)
              ;; Unfold the current entry
              (org-show-entry)
              ;; Show only direct subheadings of the slide but don't expand them
              (org-show-children)
              ))
  )

;; Mostrar los caracteres ocultos de org mode al pasar con el cursor.
(use-package org-appear
  :defer t
  ;; :hook (org-mode . org-appear-mode)
  )

;; Polymode para org-mode
;; (use-package poly-org)

(provide 'init-org)
;;; init-org.el ends here