;;; syd-org.el -*- lexical-binding: t; -*-

;; Optional Org-mode dependency used for highlighting source code in HTML
;; exports.
(use-package htmlize)

(with-eval-after-load 'org
  (syd-add-hook 'org-tab-first-hook
    (defun syd-org-cycle-only-current-subtree-h (&optional arg)
      "Toggle the local fold at the point, and no deeper.
`org-cycle's standard behavior is to cycle between three levels: collapsed,
subtree and whole document. This is slow, especially in larger org buffer. Most
of the time I just want to peek into the current subtree -- at most, expand
*only* the current subtree.

All my (performant) foldings needs are met between this and `org-show-subtree'
(on zO for evil users), and `org-cycle' on shift-TAB if I need it."
      (interactive "P")
      (unless (or (eq this-command 'org-shifttab)
                  (and (bound-and-true-p org-cdlatex-mode)
                       (or (org-inside-LaTeX-fragment-p)
                           (org-inside-latex-macro-p))))
        (save-excursion
          (org-beginning-of-line)
          (let (invisible-p)
            (when (and (org-at-heading-p)
                       (or org-cycle-open-archived-trees
                           (not (member org-archive-tag (org-get-tags))))
                       (or (not arg)
                           (setq invisible-p
                                 (memq (get-char-property (line-end-position)
                                                          'invisible)
                                       '(outline org-fold-outline)))))
              (unless invisible-p
                (setq org-cycle-subtree-status 'subtree))
              (org-cycle-internal-local)
              t)))))))

(defun syd-org--init-hacks-h ()
  ;; Open file links in current window, rather than new ones
  (setf (alist-get 'file org-link-frame-setup) #'find-file)
  ;; Open directory links in dired
  (add-to-list 'org-file-apps '(directory . emacs))
  (add-to-list 'org-file-apps '(remote . emacs))

  (defun syd-org--restart-mode-h ()
    "Restart `org-mode', but only once."
    (syd-quietly (org-mode-restart))
    (setq org-agenda-new-buffers
          (delq (current-buffer)
                org-agenda-new-buffers))
    (run-hooks 'find-file-hook))

  (syd-add-hook 'org-agenda-finalize-hook
    (defun syd-org-exclude-agenda-buffers-from-workspace-h ()
      "Don't associate temporary agenda buffers with current workspace."
      (when (and org-agenda-new-buffers
                 (bound-and-true-p persp-mode)
                 (not org-agenda-sticky))
        (let (persp-autokill-buffer-on-remove)
          (persp-remove-buffer org-agenda-new-buffers
                               (get-current-persp)
                               nil)))))

  (syd-defadvice syd-org--restart-mode-before-indirect-buffer-a (&optional buffer _)
    "Restart `org-mode' in buffers in which the mode has been deferred (see
`syd-org-defer-mode-in-agenda-buffers-h') before they become the base buffer for an
indirect org-cpature buffer. This ensures that the buffer is fully functional
not only when the *user* visits it, but also when org-capture interacts with it
via an indirect buffer."
    :before #'org-capture-get-indirect-buffer
    (with-current-buffer (or buffer (current-buffer))
      (when (memq #'syd-org--restart-mode-h on-switch-buffer-hook)
        (syd-org--restart-mode-h))))
  
  (defvar recentf-exclude)

  (syd-defadvice syd-org--optimise-backgrounded-agenda-buffers-a (fn file)
    "Disable `org-mode's startup processes for temporary agenda buffers.

Prevents recentf pollution as well. However, if the user tries to visit one of
these buffers they'll see a gimped, half-broken org buffer, so to avoid that,
install a hook to restart `org-mode' when they're switched to so they can grow
up to be fully-fledged org-mode buffers."
    :around #'org-get-agenda-file-buffer
    (if-let* ((buf (org-find-base-buffer-visiting file)))
        buf
      (let ((recentf-exclude '(always))
            ;; (doom-inhibit-large-file-detection t)
            ;; (doom-inhibit-local-var-hooks t)
            (org-inhibit-startup t)
            vc-handled-backends
            enable-local-variables
            find-file-hook)
        (when-let ((buf (delay-mode-hooks (funcall fn file))))
          (with-current-buffer buf
            (add-hook 'on-switch-buffer-hook #'syd-org--restart-mode-h
                      nil 'local))
          buf))))

  (syd-defadvice syd-org--fix-inconsistent-uuidgen-case-a (uuid)
    "Ensure uuidgen is always lowercase (consistent) regardless of system.
See https://lists.gnu.org/archive/html/emacs-orgmode/2019-07/msg00081.html."
    :filter-return #'org-id-new
    (if (eq org-id-method 'uuid)
        (downcase uuid)
      uuid)))

(defun syd-org-init-theme ()
  (require 'syd-kanagawa)
  (let* ((hl `(:weight bold))
         (fg (lambda (c) `(:foreground ,(syd-kanagawa-get c))))
         (bg (lambda (c) `(:background ,(syd-kanagawa-get c))))
         (block-delim `(:foreground unspecified
                        :inherit font-lock-comment-face
                        :extend t
                        ,@(funcall bg 'sumi-ink-0)
                        :height 0.75))
         (keyword '(:background unspecified :foreground unspecified
                    :inherit (fixed-pitch font-lock-comment-face)
                    :height 0.9)))
    (setq org-src-block-faces
          `(("jupyter-apl" syd-apl)))
    (custom-theme-set-faces
     'user
     `(org-document-title ((t (,@hl :height 1.60))))
     `(org-document-info ((t (,@hl :height 1.0))))
     `(org-document-info-keyword ((t ,keyword)))
     `(org-meta-line ((t ,keyword)))
     `(org-table ((t (:inherit fixed-pitch))))
     `(org-level-1 ((t (,@hl :height 1.40 ,@(funcall fg 'oni-violet)))))
     `(org-level-2 ((t (,@hl :height 1.35 ,@(funcall fg 'crystal-blue)))))
     `(org-level-3 ((t (,@hl :height 1.30 ,@(funcall fg 'spring-violet-2)))))
     `(org-level-4 ((t (,@hl :height 1.25 ,@(funcall fg 'light-blue)))))
     `(org-level-5 ((t (,@hl :height 1.20 ,@(funcall fg 'wave-aqua-2)))))
     `(org-level-6 ((t (,@hl :height 1.15 ,@(funcall fg 'spring-green)))))
     `(org-level-7 ((t (,@hl :height 1.10 ,@(funcall fg 'boat-yellow-1)))))
     `(org-level-8 ((t (,@hl :height 1.05 ,@(funcall fg 'boat-yellow-2)))))
     `(org-block-begin-line ((t ,block-delim)))
     `(org-block-end-line ((t ,block-delim)))
     '(org-ellipsis ((t (:height 1.0))))
     ;; It is important that the `org-indent' face uses a fixed-pitch font, lest
     ;; e.g. multi-line bullets appear misaligned.
     '(org-indent ((t (:inherit (org-hide syd-alt-fixed-pitch)))))
     ;; Must be fixed-pitch; `[ ]` and `[X]' should be the same width.
     '(org-checkbox ((t (:inherit fixed-pitch))))
     `(org-drawer ((t ,block-delim)))
     '(org-property-value ((t (:inherit fixed-pitch))))
     '(org-special-keyword ((t (:inherit (font-lock-comment-face fixed-pitch)))))
     `(org-block ((t (:inherit fixed-pitch
                               ,@(funcall bg 'sumi-ink-2)))))
     `(org-quote ((t (:inherit (variable-pitch org-block)))))
     '(org-code ((t (:inherit (shadow fixed-pitch))))))))

(evil-define-command syd-org-yank-link (register)
  (interactive "<x>")
  (if-let* ((url (thing-at-point 'url)))
      (progn (evil-set-register (or register ?\") url)
             (message "Yanked link: %s" url))
    (message "No URL at point")))

(defun syd-org-latex-preview-recompile-preamble ()
  (interactive)
  (setq org-latex-preview-process-precompiled nil)
  (org-latex-preview-clear-cache)
  (org-latex-preview 'buffer))

(defun syd-org-latex-preview-buffer ()
  (interactive)
  (org-latex-preview 'buffer))

(defun syd-org-init-keybinds ()
  (general-def
    :keymaps 'org-mode-map
    :states '(insert emacs)
    [C-M-return] #'org-insert-subheading
    "TAB" nil
    "<tab>" nil)
  (general-def
    :prefix-map 'syd-org-mode-links-map
    "l" #'org-insert-link
    "y" #'syd-org-yank-link)
  (general-define-key
   :keymaps 'org-mode-map
   :states '(normal visual motion emacs insert)
   :major-modes t
   :prefix syd-localleader-key
   :non-normal-prefix syd-alt-localleader-key
   "." #'consult-org-heading
   "/" #'consult-org-agenda
   "@" #'org-cite-insert
   "e" #'org-export-dispatch
   "f" #'org-footnote-action
   "h" #'org-toggle-heading
   "i" #'org-toggle-item
   "I" #'org-id-get-create
   "k" #'org-babel-remove-result
   "l" `("Links" . ,syd-org-mode-links-map)
   "t" #'org-todo
   "L L" #'syd-org-latex-preview-buffer
   "L r" #'syd-org-latex-preview-recompile-preamble
   "L c" #'org-latex-preview-clear-cache
   "s t" #'org-set-tags-command
   "s p" #'org-set-property
   "s d" #'org-deadline
   "s s" #'org-schedule
   "d t" #'org-timestamp
   "d T" #'org-timestamp-inactive
   "x" #'org-toggle-checkbox)
  (general-define-key
   :keymaps 'org-agenda-mode-map
   :states '(normal visual motion emacs insert)
   :major-modes t
   :prefix syd-localleader-key
   :non-normal-prefix syd-alt-localleader-key
   "t" #'org-agenda-todo
   "r" #'org-agenda-refile
   "q" #'org-agenda-set-tags
   "p p" #'org-agenda-priority
   "p u" #'org-agenda-priority-up
   "p d" #'org-agenda-priority-down
   "p k" #'org-agenda-priority-up
   "p j" #'org-agenda-priority-down
   "d d" #'org-agenda-deadline
   "d s" #'org-agenda-schedule))

(defun syd-org-init-popup-rules-h ()
  (set-popup-rules!
    '(("^\\*Org Links" :slot -1 :vslot -1 :size 2 :ttl 0)
      ("^ ?\\*\\(?:Agenda Com\\|Calendar\\|Org Export Dispatcher\\)"
       :slot -1 :vslot -1 :size #'+popup-shrink-to-fit :ttl 0)
      ("^\\*Org \\(?:Select\\|Attach\\|Table Edit\\)" :slot -1 :vslot -2 :ttl 0 :size 0.25)
      ("^\\*Edit Formulas\\*$" :slot -1 :vslot -2 :ttl 0 :size 0.25)
      ("^\\*Org Agenda"     :ignore t)
      ("^\\*Org Src"        :size 0.42  :quit nil :select t :autosave t :modeline t :ttl nil)
      ("^\\*Org-Babel")
      ("^\\*Capture\\*$\\|CAPTURE-.*$" :size 0.42 :quit nil :select t :autosave ignore))))

(defun syd-org-init-appearance-h ()
  ;; Larger LaTeX previews.
  (plist-put org-format-latex-options :scale 1.4))

(defun syd-org-init-agenda-h ()
  (setq
   ;; The lengths of these leaders take account for our added
   ;; `syd-org--agenda-repeater'.
   org-agenda-scheduled-leaders '("Sched" "S.%2dx")
   org-agenda-deadline-leaders '("Deadl" "In%2dd" "D.%2dx")
   org-agenda-timerange-leaders '("" ; Range within a single day.
                                  "%2d/%2d") ; Range spanning many days.
   ;; Hide "upcoming deadlines" until the scheduled date.
   org-agenda-skip-deadline-prewarning-if-scheduled 'pre-scheduled
   ;; Hide completed tasks.
   org-agenda-skip-scheduled-if-done t)

  ;; Show the repeater (the repeat interval, e.g. +1d) in repeating agenda
  ;; entries.
  (defun syd-org--agenda-repeater ()
    "The repeater information (e.g. +1w) in the agenda."
    (let ((pom (org-get-at-bol 'org-marker)))
      (if (or (org-get-scheduled-time pom) (org-get-deadline-time pom))
          (format "%5s: " (or (org-get-repeat) ""))
        "┄┄┄┄┄┄┄┄┄┄┄┄")))

  ;; Add `syd-org--agenda-repeater' to the agenda prefix.
  (setcdr (assoc 'agenda org-agenda-prefix-format)
          " %i %-12:c%?-12t%s%(syd-org--agenda-repeater)")

  (setq org-agenda-custom-commands
        '(("k" "My agenda for today"
           ((agenda
             ""
             ((org-agenda-span 1)
              (org-deadline-warning-days 0)))
            (agenda
             ""
             ((org-agenda-span 7)
              (org-agenda-start-day "+1d")
              (org-deadline-warning-days 0)
              (org-agenda-time-grid nil)
              (org-agenda-entry-types '(:deadline))
              (org-agenda-overriding-header "Upcoming deadlines"))))))))

(defvar syd-org-default-css "
<style>
  html
  { height: 100%;
  }
  
  body
  { height: 100%
  ; padding: 0 10px
  ; line-height: 1.6
  ; font-size: 18px
  ; margin: 40px auto
  ; max-width: 650px
  ; color: #444
  }
  
  h1, h2, h3
  { line-height: 1.2
  }
  
  pre
  { line-height: normal
  }

  .org-svg
  { max-height: 100%
  ; max-width: 100%
  }

  .figure img
  { max-height: 100%
  ; max-width: 100%
  }
</style>"
  "A default style for Org HTML exports.")

(use-package org
  :defer-incrementally
  calendar find-func format-spec org-macs org-compat org-faces org-entities
  org-list org-pcomplete org-src org-footnote org-macro ob org org-agenda
  org-capture
  ;; We are using Tecosaur's shiny new async LaTeX preview engine.  Learn more
  ;; here: https://abode.karthinks.com/org-latex-preview/#org9054eb6
  :straight `(org
              :fork (:host nil
                     :repo "https://git.tecosaur.net/tec/org-mode.git"
                     :branch "dev"
                     :remote "tecosaur")
              :files (:defaults "etc")
              :build t
              :pre-build
              (with-temp-file "org-version.el"
               (require 'lisp-mnt)
               (let ((version
                      (with-temp-buffer
                        (insert-file-contents "lisp/org.el")
                        (lm-header "version")))
                     (git-version
                      (string-trim
                       (with-temp-buffer
                         (call-process "git" nil t nil "rev-parse" "--short" "HEAD")
                         (buffer-string)))))
                (insert
                 (format "(defun org-release () \"The release version of Org.\" %S)\n" version)
                 (format "(defun org-git-version () \"The truncate git commit hash of Org mode.\" %S)\n" git-version)
                 "(provide 'org-version)\n")))
              :pin nil)
  :init
  ;; HACK: Face specs fed directly to `org-todo-keyword-faces' don't respect
  ;; underlying faces like the `org-todo' face does, so we define our own
  ;; intermediary faces that extend from org-todo.
  (with-no-warnings
    (custom-declare-face 'syd-org-todo-active
                         '((t (:inherit (bold font-lock-constant-face org-todo)))) "")
    (custom-declare-face 'syd-org-todo-project
                         '((t (:inherit (bold font-lock-doc-face org-todo)))) "")
    (custom-declare-face 'syd-org-todo-onhold
                         '((t (:inherit (bold warning org-todo)))) "")
    (custom-declare-face 'syd-org-todo-cancel
                         '((t (:inherit (bold error org-todo)))) ""))
  :custom ((org-startup-folded 'content)
           (org-directory "~/org")
           (org-agenda-files (list org-directory))
           (org-agenda-deadline-faces '((1.001 . error)
                                        (1.0 . org-warning)
                                        (0.5 . org-upcoming-deadline)
                                        (0.0 . org-upcoming-distant-deadline)))
           (org-agenda-window-setup 'current-window)
           (org-refile-use-outline-path t)
           (org-tag-persistent-alist `(("orgmode" . ?o)
                                       ("hrt" . ?h)))
           (org-agenda-skip-unavailable-files t)
           ;; Shift the agenda to show the previous 3 days and the next 7 days
           ;; for better context on your week. The past is less important than
           ;; the future.
           (org-agenda-span 10)
           (org-agenda-start-on-weekday nil)
           (org-agenda-start-day "-3d")
           ;; Optimize `org-agenda' by inhibiting extra work while opening
           ;; agenda buffers in the background. They'll be "restarted" if the
           ;; user switches to them anyway (see
           ;; `syd-org-exclude-agenda-buffers-from-workspace-h')
           (org-agenda-inhibit-startup t)
           ;; Upon finishing a task, leave a timestamp.
           (org-log-done 'time)
           (org-indirect-buffer-display 'current-window)
           ;; Force a TeX-like syntax for {sub,super}-scripts.  x^{blah blah}
           (org-use-sub-superscripts '{})
           (org-fontify-quote-and-verse-blocks t)
           (org-enforce-todo-dependencies t)
           (org-image-actual-width nil)
           (org-imenu-depth 6)
           ;; Include some sane default CSS declarations when exporting to HTML.
           (org-html-head syd-org-default-css)
           ;; Don't right-align tags.
           (org-tags-column 0)
           (org-priority-faces '((?A . error)
                                 (?B . warning)
                                 (?C . success)))
           ;; Stay out of my config dir!
           (org-id-locations-file (file-name-concat syd-cache-dir
                                                    "org-id-locations"))
           (org-cite-global-bibliography
            (list (expand-file-name "~/etc/liography.bib")))
           ;; New headings should be inserted /after/ the heading's contents.
           (org-insert-heading-respect-content t)
           ;; Hide markup syntax and leave the markup.
           (org-hide-emphasis-markers t)
           (org-ellipsis " […]")
           (org-todo-keywords
            '((sequence
               "TODO(t)"    ; A task that needs doing & is ready to do
               "PROJ(p)"    ; A project, which usually contains other tasks
               "STRT(s)"    ; A task that is in progress
               "WAIT(w)"    ; Something external is holding up this task
               "HOLD(h)"    ; This task is paused/on hold because of me
               "IDEA(i)"    ; An unconfirmed and unapproved task or notion
               "|"
               "DONE(d)"    ; Task successfully completed
               "KILL(k)"))) ; Task was cancelled, aborted, or is no longer
                            ; applicable
           (org-todo-keyword-faces
            '(("[-]"  . syd-org-todo-active)
              ("STRT" . syd-org-todo-active)
              ("WAIT" . syd-org-todo-onhold)
              ("HOLD" . syd-org-todo-onhold)
              ("PROJ" . syd-org-todo-project)
              ("KILL" . syd-org-todo-cancel)))
           (org-startup-with-latex-preview t)
           (org-pretty-entities t))
  :preface
  ;; Speed up initialisation by disabling modules we don't need.
  (defvar org-modules
    '(;; ol-w3m
      ;; ol-bbdb
      ol-bibtex
      ;; ol-docview
      ;; ol-gnus
      ;; ol-info
      ;; ol-irc
      ;; ol-mhe
      ;; ol-rmail
      ;; ol-eww
      ))
  (syd-add-hook 'org-load-hook
    #'syd-org-init-popup-rules-h
    #'syd-org-init-appearance-h)
  (with-eval-after-load 'org-agenda
    (syd-org-init-agenda-h))
  :config
  (require 'syd-prose)
  (syd-add-hook 'org-mode-hook
    #'org-indent-mode
    #'syd-prose-mode)
  (syd-org-init-theme)
  (syd-org-init-keybinds))

(use-package org-latex-preview
  :defer t
  :straight nil
  :custom (;; Generate previews whilst editing.
           (org-latex-preview-live t)
           ;; Default behaviour waits one second before generating the live
           ;; preview.
           (org-latex-preview-live-debounce 0.25)
           ;; Increase size of previews.
           (org-latex-preview-appearance-options
            (plist-put org-latex-preview-appearance-options :zoom 1.4)))
  :hook (org-mode . org-latex-preview-mode))

(use-package org-appear
  :hook (org-mode . org-appear-mode)
  :custom ((org-appear-autoemphasis t)
           (org-appear-auto-submarkers t)))

;; Unlike those appearing in `syd-org--init-roam-keybinds', these should be
;; available even outside of Org-mode.
(general-def
  :prefix-map 'syd-leader-notes-roam-map
  "f" #'org-roam-node-find
  "d t" #'org-roam-dailies-capture-today
  "d T" #'org-roam-dailies-goto-today)

(general-def
  :keymaps 'syd-leader-open-map
  "A" #'org-agenda)

(defun syd-org--init-roam-keybinds ()
  (general-def
    :prefix-map 'syd-org-roam-mode-map)
  (general-def
    :prefix-map 'syd-leader-notes-map
    "r" `("Org-roam" . ,syd-leader-notes-roam-map))
  ;; Rebind Imenu keybind to `consult-org-heading'.  It's similar enough in
  ;; appearance and functionality, but more reliable and "correct."
  ;; REVIEW: Perhaps it would be best to implement `imenu-create-index-function'
  ;; using `consult-org-heading'?
  (general-def
    :keymaps 'org-mode-map
    [remap consult-imenu] #'consult-org-heading
    [remap imenu] #'consult-org-heading)
  (general-define-key
   :keymaps 'org-mode-map
   :states '(normal visual motion emacs insert)
   :major-modes t
   :prefix syd-localleader-key
   :non-normal-prefix syd-alt-localleader-key
   "m" `("Org-roam" . ,syd-org-roam-mode-map)))

(use-package org-roam
  :hook (org-load . syd-org-init-roam-h)
  :commands (org-roam-buffer-toggle-display
             org-roam-dailies-capture-today
             org-roam-dailies-goto-date
             org-roam-dailies-goto-today
             org-roam-dailies-goto-tomorrow
             org-roam-dailies-goto-yesterday)
  :init (progn (syd-org--init-roam-keybinds)
               (syd-load-packages-incrementally
                '(ansi-color dash f rx seq magit-section emacsql)))
  :custom ((org-roam-directory org-directory)
           (org-roam-db-location (file-name-concat syd-cache-dir
                                                   "org-roam.db"))
           ;; Make org-roam buffer sticky; i.e. don't replace it when opening a
           ;; file with an *-other-window command.
           (org-roam-buffer-window-parameters '((no-delete-other-windows . t)))
           (org-roam-completion-everywhere t)
           (org-roam-dailies-capture-templates
            `(("d" "default" entry "* %?\n%U"
               :target (file+head "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>")
               :empty-lines 1))))
  :config
  (add-to-list 'org-agenda-files org-roam-directory)
  (with-eval-after-load 'org-roam-dailies
    (add-to-list 'org-agenda-files
                 (file-name-concat org-roam-directory
                                   org-roam-dailies-directory)))
  (defun syd-org-init-roam-h ()
    "Setup `org-roam' but don't immediately initialize its database.  Instead,
initialize it when it will be actually needed."
    (cl-letf (((symbol-function #'org-roam-db-sync) #'ignore))
      (org-roam-db-autosync-enable)))

  (syd-org--init-roam-keybinds)

  (syd-defadvice syd-org-roam-try-init-db-a (&rest _)
    "Try to initialize org-roam database at the last possible safe moment.
In case of failure, fail gracefully."
    :before #'org-roam-db-query
    (message "Initializing org-roam database...")
    (advice-remove 'org-roam-db-query #'syd-org-roam-try-init-db-a)
    (org-roam-db-sync)))

(use-package evil-org
  :hook ((org-mode . evil-org-mode)
         (org-capture-mode . evil-insert-state))
  :straight (:type git :host github :repo "doomelpa/evil-org-mode")
  :init
  (defvar evil-org-retain-visual-state-on-shift t)
  (defvar evil-org-special-o/O '(table-row))
  (defvar evil-org-use-additional-insert t)
  :config
  (add-hook 'evil-org-mode-hook #'evil-normalize-keymaps)
  (evil-org-set-key-theme))

(use-package evil-org-agenda
  :hook (org-agenda-mode . evil-org-agenda-mode)
  :straight nil
  :config
  (evil-org-agenda-set-keys)
  ;; Stay away from my leader key!
  (evil-define-key* 'motion evil-org-agenda-mode-map
    (kbd syd-leader-key) nil))

(use-package hide-mode-line
  :hook (org-mode . hide-mode-line-mode))

(use-package org-superstar
  :hook (org-mode . org-superstar-mode)
  :custom ((org-superstar-headline-bullets-list '(9675))
           (org-superstar-item-bullet-alist '((?- . ?•)
                                              (?+ . ?➤)
                                              (?* . ?⋆))))
  :config
  ;; Stars should use fixed-pitch font to align w/ `org-indent'.
  (custom-theme-set-faces
   'user
   `(org-superstar-header-bullet ((t (:font ,syd-alt-fixed-pitch-font))))
   `(org-superstar-item ((t (:font ,syd-alt-fixed-pitch-font))))))

(use-package org-noter
  :commands org-noter)

(use-package org-contrib)

(use-package ox-extra
  :after org-contrib
  :config
  (ox-extras-activate '(latex-header-blocks ignore-headlines)))

(with-eval-after-load 'org
  (org-link-set-parameters "wiktionary"
                           :follow #'syd-org-wiktionary-open
                           ;; :export #'syd-org-wiktionary-export
                           )
  (defun syd-org-wiktionary-open (path _)
    (browse-url (format "https://en.wiktionary.org/wiki/%s"
                        (browse-url-encode-url path))))
  ;; (defun syd-org-wiktionary-export (link description format _)
  ;;   (org-export-transcoder))
  )

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