diff --git a/modules/lang/org/autoload/org-attach.el b/modules/lang/org/autoload/org-attach.el index b3cee8902..fa41685b2 100644 --- a/modules/lang/org/autoload/org-attach.el +++ b/modules/lang/org/autoload/org-attach.el @@ -1,30 +1,5 @@ ;;; lang/org/autoload/org-attach.el -*- lexical-binding: t; -*- -;; -(defvar +org-attachments nil - "A list of all indexed attachments in `org-directory'.") - -(defvar +org-attachments-files nil - "A list of all attachments in `org-attach-id-dir'.") - -(defun +org-list-attachments (&optional beg end) - "Return a list of all attachment file names in the current buffer between BEG -and END (defaults to `point-min' and `point-max')." - (let ((case-fold-search t) - attachments) - (or end (setq end (point-max))) - (org-save-outline-visibility nil - (org-with-wide-buffer - (goto-char (or beg (point-min))) - (while (search-forward "[[attach:" end t) - (let* ((context (save-match-data (org-element-context))) - (link (expand-file-name (org-link-unescape (org-element-property :path context)) - org-attach-id-dir))) - (when (and (equal "file" (org-element-property :type context)) - (file-in-directory-p link org-attach-id-dir)) - (push (file-name-nondirectory link) attachments)))))) - (cl-delete-duplicates attachments :test #'string=))) - ;;;###autoload (defun +org-attach-icon-for (path) (char-to-string @@ -39,63 +14,46 @@ and END (defaults to `point-min' and `point-max')." ((or "zip" "gz" "tar" "7z" "rar") ?) (_ ?)))) +;;;###autoload +(defun +org/open-gallery-from-attachments () + "TODO" + (interactive) + (require 'org-attach) + (if-let (dir (org-attach-dir)) + (pop-to-buffer + ;; Rather than opening dired *and* image-dired windows, suppress them + ;; both and open only the image-dired window. + (save-window-excursion + (image-dired dir) + (current-buffer))) + (user-error "No attachments for this node"))) ;;;###autoload -(defun +org-attach/sync (arg) - "Reindex all attachments in `org-directory' and delete orphaned attachments in -`org-attach-id-dir'. If ARG (universal arg), conduct a dry run." - (declare (interactive-only t)) - (interactive "P") - (message "Reloading") - (setq +org-attachments-files (directory-files org-attach-id-dir nil "^[^.]" t)) - (with-temp-buffer - (delay-mode-hooks (org-mode)) - (dolist (org-file (directory-files-recursively org-directory "\\.org$")) - (insert-file-contents-literally org-file)) - (setq +org-attachments (+org-list-attachments))) - ;; clean up - (let ((deleted 0)) - (dolist (file (cl-set-difference +org-attachments-files +org-attachments - :test #'string=)) - (message "Deleting orphaned attachment: %s" file) - (cl-incf deleted) - (unless arg - (delete-file (expand-file-name file org-attach-id-dir)))) - (message "Buffer's attachments synced (%d deleted)" deleted))) - -;;;###autoload -(defun +org-attach/find-file () +(defun +org/find-file-in-attachments () "Open a file from `org-attach-id-dir'." (interactive) (doom-project-browse org-attach-id-dir)) ;;;###autoload -(defun +org-attach/file (path) - "Copies the file at PATH to `+org-attach-dir' and places an org link to it at -the cursor." - (interactive "fAttach file: ") - (+org-attach/uri path)) - -;;;###autoload -(defun +org-attach/uri (uri) - "Downloads the file at URL and place an org link to it at the cursor." +(defun +org/attach-file-and-insert-link (path) + "Downloads the file at PATH and insert an org link at point. +PATH (a string) can be an url, a local file path, or a base64 encoded datauri." (interactive "sUri/file: ") (unless (eq major-mode 'org-mode) (user-error "Not in an org buffer")) (require 'org-download) - (let ((raw-uri (url-unhex-string uri))) - (condition-case ex - (cond ((string-match-p "^data:image/png;base64," uri) - (org-download-dnd-base64 uri nil)) + (condition-case ex + (let ((raw-uri (url-unhex-string path))) + (cond ((string-match-p "^data:image/png;base64," path) + (org-download-dnd-base64 path nil)) ((image-type-from-file-name raw-uri) (org-download-image raw-uri)) - (t - (let ((new-path (expand-file-name (org-download--fullname raw-uri)))) + ((let ((new-path (expand-file-name (org-download--fullname raw-uri)))) ;; Download the file - (if (string-match-p (concat "^" (regexp-opt '("http" "https" "nfs" "ftp" "file")) ":/") uri) + (if (string-match-p (concat "^" (regexp-opt '("http" "https" "nfs" "ftp" "file")) ":/") path) (url-copy-file raw-uri new-path) - (copy-file uri new-path)) + (copy-file path new-path)) ;; insert the link - (org-download-insert-link raw-uri new-path)))) - (error - (user-error "Failed to attach file: %s" (error-message-string ex)))))) + (org-download-insert-link raw-uri new-path))))) + (error + (user-error "Failed to attach file: %s" (error-message-string ex))))) diff --git a/modules/lang/org/config.el b/modules/lang/org/config.el index 83b75aa13..ffce10b0c 100644 --- a/modules/lang/org/config.el +++ b/modules/lang/org/config.el @@ -355,42 +355,14 @@ underlying, modified buffer. This fixes that." (add-hook '+doom-dashboard-inhibit-functions #'+org-capture-frame-p))) -(defun +org-init-centralized-attachments-h () - "I believe Org's native attachment system is over-complicated and litters -files with metadata I don't want. So I wrote my own, which: - -+ Places attachments in a centralized location (`org-attach-id-dir' in - `org-directory'). -+ Adds attach:* link abbreviation for quick links to these files from anywhere. -+ Use `+org-attach/sync' to index all attachments in `org-directory' that use - the attach:* abbreviation and delete orphaned ones that are no longer - referenced. -+ This compliments the +dragndrop flag which provides drag'n'drop support for - images (with preview) and media files. - -Some commands of interest: -+ `org-download-screenshot' -+ `+org-attach/file' -+ `+org-attach/url' -+ `+org-attach/sync'" - (setq org-attach-id-dir (doom-path org-directory org-attach-id-dir)) - - ;; A shorter link to attachments - (add-to-list 'org-link-abbrev-alist - (cons "attach" - (abbreviate-file-name org-attach-id-dir))) - - (org-link-set-parameters - "attach" - :follow (lambda (link) (find-file (doom-path org-attach-id-dir link))) - :complete (lambda (&optional _arg) - (+org--relpath (+org-link-read-file "attach" org-attach-id-dir) - org-attach-id-dir)) - :face (lambda (link) - (if (file-exists-p (expand-file-name link org-attach-id-dir)) - 'org-link - 'error))) - +(defun +org-init-attachments-h () + "Sets up org's attachment system." + ;; Centralized attachments directory + (setq org-attach-id-dir (doom-path org-directory org-attach-id-dir) + ;; Store a link to attachments when they are attached + org-attach-store-link-p t + ;; Inherit attachment properties from parent nodes + org-attach-use-inheritance t) (after! projectile (add-to-list 'projectile-globally-ignored-directories org-attach-id-dir))) @@ -650,10 +622,21 @@ between the two." "t" #'org-todo "T" #'org-todo-list (:prefix ("a" . "attachments") - "a" #'+org-attach/file - "u" #'+org-attach/uri - "f" #'+org-attach/find-file - "s" #'+org-attach/sync) + "a" #'org-attach + "d" #'org-attach-delete-one + "D" #'org-attach-delete-all + "f" #'+org/find-file-in-attachments + "l" #'+org/attach-file-and-insert-link + "n" #'org-attach-new + "o" #'org-attach-open + "O" #'org-attach-open-in-emacs + "r" #'org-attach-reveal + "R" #'org-attach-reveal-in-emacs + "u" #'org-attach-url + "s" #'org-attach-set-directory + "S" #'org-attach-sync + (:when (featurep! +dragndrop) + "y" #'org-download-yank)) (:prefix ("b" . "tables") "-" #'org-table-insert-hline "a" #'org-table-align @@ -944,11 +927,14 @@ compelling reason, so..." org-capture :preface ;; Change org defaults (should be set before org loads) - (defvar org-directory "~/org/") - (defvar org-attach-id-dir ".attach/") - - (setq org-publish-timestamp-directory (concat doom-cache-dir "org-timestamps/") - org-preview-latex-image-directory (concat doom-cache-dir "org-latex/")) + (setq org-directory "~/org/" + org-attach-id-dir ".attach/" + org-publish-timestamp-directory (concat doom-cache-dir "org-timestamps/") + org-preview-latex-image-directory (concat doom-cache-dir "org-latex/") + org-id-locations-file (concat doom-etc-dir "org-id-locations") + ;; Global ID state means we can have ID links anywhere (required by + ;; `org-brain') + org-id-track-globally t) (defvar org-modules '(;; ol-w3m @@ -978,11 +964,11 @@ compelling reason, so..." (add-hook! 'org-load-hook #'+org-init-appearance-h #'+org-init-agenda-h + #'+org-init-attachments-h #'+org-init-babel-h #'+org-init-babel-lazy-loader-h #'+org-init-capture-defaults-h #'+org-init-capture-frame-h - #'+org-init-centralized-attachments-h #'+org-init-centralized-exports-h #'+org-init-custom-links-h #'+org-init-export-h diff --git a/modules/lang/org/contrib/brain.el b/modules/lang/org/contrib/brain.el index 019310284..4e0ed6365 100644 --- a/modules/lang/org/contrib/brain.el +++ b/modules/lang/org/contrib/brain.el @@ -4,9 +4,7 @@ (use-package! org-brain :defer t :init - (setq org-id-track-globally t - org-id-locations-file (concat doom-etc-dir "org-id-locations") - org-brain-visualize-default-choices 'all + (setq org-brain-visualize-default-choices 'all org-brain-title-max-length 24 org-brain-include-file-entries nil org-brain-file-entries-use-title nil) diff --git a/modules/lang/org/contrib/dragndrop.el b/modules/lang/org/contrib/dragndrop.el index 4095e25a4..35526cda3 100644 --- a/modules/lang/org/contrib/dragndrop.el +++ b/modules/lang/org/contrib/dragndrop.el @@ -10,7 +10,8 @@ '("^data:" . org-download-dnd-base64)) (advice-add #'org-download-enable :override #'ignore) :config - (setq org-download-image-dir org-attach-directory + (setq org-download-image-dir org-attach-id-dir + org-download-method 'attach org-download-heading-lvl nil org-download-timestamp "_%Y%m%d_%H%M%S" org-download-screenshot-method