Merge branch 'develop'

* develop:
  Switch to fallback buffer on kill-all-buffers
  Add GNUTLS feature detection to doom doctor #175
  Fix evil-mc not whitelisting custom commands
  doom-modeline: minor refactor
  org/org: resolve +rss-elfeed-files later
  Update changelog
  Prevent/delay hash-table rehashing
  Remove dead wiki link from README
  feature/hydra: lv-use-separator = t
  Use left-margin to center dashboard elements #192
  init.example.el: disable :lang modules by default
  Add lang/ledger #194
  org-attach: remove vestigial reference to variable
  Add org-attach to init.example.el
  +org|realign-table-maybe: now recalculates table formulas too
  +org/toggle-fold: realign tables
  Refactor +org/dwim-at-point
  Refactor org/org-attach
  Add task entry to org-capture-templates
  org: restore checkbox TODO keywords
This commit is contained in:
Henrik Lissner 2017-09-13 17:12:34 +02:00
commit 895d59f9b4
19 changed files with 340 additions and 187 deletions

View file

@ -11,7 +11,6 @@
* Todo * Todo
+ *Potential plugins:* + *Potential plugins:*
+ =completion/ivy= [[https://github.com/yevgnen/ivy-rich][ivy-rich]], possible replacement for ~+ivy/switch-buffer~
+ =app/present= [[https://github.com/larstvei/Focus][focus]], for presenting code + =app/present= [[https://github.com/larstvei/Focus][focus]], for presenting code
+ [[https://github.com/emacs-lsp/lsp-mode][lsp-mode]], client for MS Language Server Protocol, keep an eye on this + [[https://github.com/emacs-lsp/lsp-mode][lsp-mode]], client for MS Language Server Protocol, keep an eye on this
+ =lang/javascript= [[https://github.com/NicolasPetton/Indium][indium]] (IDE), keep an eye on this + =lang/javascript= [[https://github.com/NicolasPetton/Indium][indium]] (IDE), keep an eye on this
@ -26,10 +25,9 @@
+ =lang/python= [[https://github.com/Wilfred/pyimport][pyimport]] or [[https://github.com/anachronic/importmagic.el][importmagic]] + =lang/python= [[https://github.com/Wilfred/pyimport][pyimport]] or [[https://github.com/anachronic/importmagic.el][importmagic]]
+ [[https://github.com/mhayashi1120/Emacs-imagex][emacs-imagex]], for manipulating images at point (zooming?) + [[https://github.com/mhayashi1120/Emacs-imagex][emacs-imagex]], for manipulating images at point (zooming?)
+ =tools/term= [[https://github.com/riscy/shx-for-emacs][shx]], an extension for the shell in Emacs + =tools/term= [[https://github.com/riscy/shx-for-emacs][shx]], an extension for the shell in Emacs
+ =app/crm= [[https://github.com/skeeto/emacsql][emacsql]], a sqlite backend; which would be useful for CRM storage. + =app/crm= [[https://github.com/skeeto/emacsql][emacsql]], a sqlite backend; possibly useful for CRM storage.
+ =core= [[https://github.com/Wilfred/helpful][helpful]], a better help buffer; possible replacement for ~describe-function~. + =core= [[https://github.com/Wilfred/helpful][helpful]], a better help buffer; replacement for ~describe-function~?
+ *Planned modules:* + *Planned modules:*
+ =app/finance= -- ledger + org-mode.
+ =app/crm= -- Customer Relations Management, in Emacs, using org-mode. + =app/crm= -- Customer Relations Management, in Emacs, using org-mode.
+ =app/write= -- Make Emacs into a focused plaintext word processor (using markdown, org and rst) for writing papers and stories. + =app/write= -- Make Emacs into a focused plaintext word processor (using markdown, org and rst) for writing papers and stories.
+ =app/regex= -- PCRE IDE, with live buffer matching, search/replace support, and an export-to-code feature for various languages. + =app/regex= -- PCRE IDE, with live buffer matching, search/replace support, and an export-to-code feature for various languages.
@ -45,9 +43,9 @@
+ C++ (~regex reg(regexp, ...)~) + C++ (~regex reg(regexp, ...)~)
+ Syntax highlighter for ~+regex-mode~ (plus make it a major mode) + Syntax highlighter for ~+regex-mode~ (plus make it a major mode)
+ Optimize: communicate with perl process (with ~make-process~ instead of ~call-process~) + Optimize: communicate with perl process (with ~make-process~ instead of ~call-process~)
+ =lang/alda= -- Language support for [[https://github.com/alda-lang/alda][Alda]], the music programming language, using [[https://github.com/jgkamat/alda-mode][alda-mode]].
+ =org/org-publish= -- publishing org files to HTML (thanks to [[https://github.com/matthewgraybosch][matthewgraybosch]]) + =org/org-publish= -- publishing org files to HTML (thanks to [[https://github.com/matthewgraybosch][matthewgraybosch]])
+ =org/org-attach= -- my own, simpler attachment system with drag-drop image attachment support and centralized storage. + =org/org-attach= -- my own, simpler attachment system with drag-drop image attachment support and centralized storage.
+ =app/torrents= -- Emacs as a torrent client (powered by transmission.el)
+ =core-ui= Replace or fix ~winner-mode~ unreliability (will close windows trying to revive killed buffers). Perhaps make ~doom/kill-this-buffer~ only disassociate buffer from persp-mode or bury buffer if persp-mode is inactive. + =core-ui= Replace or fix ~winner-mode~ unreliability (will close windows trying to revive killed buffers). Perhaps make ~doom/kill-this-buffer~ only disassociate buffer from persp-mode or bury buffer if persp-mode is inactive.
+ =org= + =org=
+ Better shackle + org-agenda integration + Better shackle + org-agenda integration
@ -67,6 +65,16 @@
+ =core-popups= Add support for moving popup windows to the ~+evil/window-move-*~ commands #171 + =core-popups= Add support for moving popup windows to the ~+evil/window-move-*~ commands #171
* Unreleased (master) * Unreleased (master)
+ =doom=
+ Added new module: ~lang/ledger~, for editing ledger files.
+ Fixed ~make update~ to work even if Doom is installed somewhere other than ~\~/.emacs.d~ (see [[https://github.com/hlissner/doom-emacs/issues/190][#190]]).
+ =feature=
+ =hydra= Display a separator along the bottom of hydra windows for extra contrast.
+ =ui=
+ =doom-dashboard= Elements are now centered using window-local margins, which fixes discrepancies when multiple dashboards are visible in different sized windows and/or frames (see [[https://github.com/hlissner/doom-emacs/issues/192][#192]]).
+ =org=
+ If a table is under point when ~+org/toggle-fold~ is invoked, the table is realigned.
+ =org-capture= Fix a vestigial reference to a long-since-renamed function: ~doom/project-root~.
* 2.0.5 (Sep 03, 2017) * 2.0.5 (Sep 03, 2017)
+ =doom= + =doom=
@ -84,7 +92,7 @@
+ Added new function: ~doom|disable-vi-tilde-fringe~ for turning off vi-tilde-fringe in select buffers. + Added new function: ~doom|disable-vi-tilde-fringe~ for turning off vi-tilde-fringe in select buffers.
+ Added support for relative line numbers (see ~doom-line-numbers-style~), using nlinum-relative on Emacs <26, and display-line-numbers on Emacs 26+. + Added support for relative line numbers (see ~doom-line-numbers-style~), using nlinum-relative on Emacs <26, and display-line-numbers on Emacs 26+.
+ =feature= + =feature=
+ =File Templates= Added a file template for: + =file-templates= Added a file template for:
+ *.org files + *.org files
+ Module README.org files. + Module README.org files.
+ =jump= + =jump=
@ -92,6 +100,7 @@
+ Rewrote ~+jump/online~ to: + Rewrote ~+jump/online~ to:
+ Use the current selection, if active, or prompt for a query otherwise (with the thing at point as the initial input). + Use the current selection, if active, or prompt for a query otherwise (with the thing at point as the initial input).
+ Prompts for the provider (search engine) on first use, and reuses the last provider on consecutive uses. If the universal argument is supplied, force ~+jump/online~ to prompt for the provider anyway. + Prompts for the provider (search engine) on first use, and reuses the last provider on consecutive uses. If the universal argument is supplied, force ~+jump/online~ to prompt for the provider anyway.
+ =workspaces= Fix interactive renaming of workspaces, as well as the ability to save and load workspaces from files (see [[https://github.com/hlissner/doom-emacs/pull/200][#200]]).
+ =completion= + =completion=
+ Added all-the-icons support to ~ivy-switch-buffer~ and ~+ivy/switch-workspace-buffer~. Enable this with ~(setq +ivy-buffer-icons t)~. + Added all-the-icons support to ~ivy-switch-buffer~ and ~+ivy/switch-workspace-buffer~. Enable this with ~(setq +ivy-buffer-icons t)~.
+ =ui= + =ui=

View file

@ -98,8 +98,7 @@ a resource for others.
If you'd like to support my efforts, I welcome contributions of any kind: If you'd like to support my efforts, I welcome contributions of any kind:
+ I love pull requests and bug reports (read the [contribution + I love pull requests and bug reports, and elisp pointers are especially
guidelines][wiki-contribute] first though!), and elisp pointers are especially
welcome. Seriously, don't hesitate to [tell me my Elisp-fu welcome. Seriously, don't hesitate to [tell me my Elisp-fu
sucks][doom-new-issue]! sucks][doom-new-issue]!
+ I'm happy to discuss Emacs workflow, ideas or tooling. If you think I, Doom or + I'm happy to discuss Emacs workflow, ideas or tooling. If you think I, Doom or
@ -108,7 +107,6 @@ If you'd like to support my efforts, I welcome contributions of any kind:
[wiki]: /../../wiki [wiki]: /../../wiki
[wiki-contribute]: /../../wiki/Contribute
[wiki-conventions]: /../../wiki/Conventions [wiki-conventions]: /../../wiki/Conventions
[wiki-modules]: /../../wiki/Modules [wiki-modules]: /../../wiki/Modules
[wiki-customization]: /../../wiki/Customization [wiki-customization]: /../../wiki/Customization

View file

@ -210,7 +210,19 @@
"or just about anyone who knows more about computers than you do!")))) "or just about anyone who knows more about computers than you do!"))))
(log! "test-tls") (log! "test-tls")
(cond ((or (executable-find "gnutls-cli") (cond ((not (string-match-p "\\_<GNUTLS\\_>" system-configuration-features))
(warn! "Warning: You didn't install Emacs with gnutls support")
(explain!
"This may cause 'pecular error' errors with the Doom doctor, and is likely to "
"interfere with package management. Your mileage may vary."
(when (eq system-type 'darwin)
(concat "\nMacOS users are advised to install Emacs via homebrew with one of the following:\n"
" brew install emacs --with-gnutls"
" or"
" brew tap d12frosted/emacs-plus"
" brew install emacs-plus"))))
((or (executable-find "gnutls-cli")
(executable-find "openssl")) (executable-find "openssl"))
(let ((tls-checktrust t) (let ((tls-checktrust t)
(gnutls-verify-error t)) (gnutls-verify-error t))
@ -247,6 +259,7 @@
(when (getenv "DEBUG") (when (getenv "DEBUG")
(success! "Rejected %s (a good thing!)" url) (success! "Rejected %s (a good thing!)" url)
(explain! (pp-to-string ex)))))))) (explain! (pp-to-string ex))))))))
(t (t
(error! "Nope!"))) (error! "Nope!")))

View file

@ -256,10 +256,9 @@ If PROJECT-P, kill all buffers that belong to the current project."
(interactive "P") (interactive "P")
(let ((buffers (if project-p (doom-project-buffer-list) (doom-buffer-list)))) (let ((buffers (if project-p (doom-project-buffer-list) (doom-buffer-list))))
(mapc #'doom-kill-buffer-and-windows buffers) (mapc #'doom-kill-buffer-and-windows buffers)
(when (called-interactively-p 'interactive)
(unless (doom-real-buffer-p) (unless (doom-real-buffer-p)
(switch-to-buffer (doom-fallback-buffer))) (switch-to-buffer (doom-fallback-buffer)))
(message "Killed %s buffers" (length buffers))))) (message "Killed %s buffers" (length buffers))))
;;;###autoload ;;;###autoload
(defun doom/kill-other-buffers (&optional project-p) (defun doom/kill-other-buffers (&optional project-p)

View file

@ -228,7 +228,9 @@ This aggressively reloads core autoload files."
e.g '(:feature evil :lang emacs-lisp javascript java)" e.g '(:feature evil :lang emacs-lisp javascript java)"
(unless doom-modules (unless doom-modules
(setq doom-modules (make-hash-table :test #'equal :size (+ 5 (length modules))))) (setq doom-modules (make-hash-table :test #'equal
:size (+ 5 (length modules))
:rehash-threshold 1.0)))
(let (mode) (let (mode)
(dolist (m modules) (dolist (m modules)
(cond ((keywordp m) (cond ((keywordp m)

View file

@ -75,42 +75,43 @@
upload ; map local to remote projects via ssh/ftp upload ; map local to remote projects via ssh/ftp
:lang :lang
assembly ; assembly for fun or debugging ;assembly ; assembly for fun or debugging
cc ; C/C++/Obj-C madness ;cc ; C/C++/Obj-C madness
crystal ; ruby at the speed of c ;crystal ; ruby at the speed of c
csharp ; unity, .NET, and mono shenanigans ;csharp ; unity, .NET, and mono shenanigans
data ; config/data formats ;data ; config/data formats
elixir ; erlang done right ;elixir ; erlang done right
elm ; care for a cup of TEA? ;elm ; care for a cup of TEA?
emacs-lisp ; drown in parentheses emacs-lisp ; drown in parentheses
go ; the hipster dialect ;go ; the hipster dialect
haskell ; a language that's lazier than I am ;haskell ; a language that's lazier than I am
hy ; readability of scheme w/ speed of python ;hy ; readability of scheme w/ speed of python
java ; the poster child for carpal tunnel syndrome ;java ; the poster child for carpal tunnel syndrome
javascript ; all(hope(abandon(ye(who(enter(here)))))) ;javascript ; all(hope(abandon(ye(who(enter(here))))))
julia ; a better, faster MATLAB ;julia ; a better, faster MATLAB
latex ; writing papers in Emacs has never been so fun ;latex ; writing papers in Emacs has never been so fun
lua ; one-based indices? one-based indices ;ledger ; an accounting system in Emacs
markdown ; writing docs for people to ignore ;lua ; one-based indices? one-based indices
ocaml ; an objective camel ;markdown ; writing docs for people to ignore
perl ; write code no one else can comprehend ;ocaml ; an objective camel
php ; make php less awful to work with ;perl ; write code no one else can comprehend
plantuml ; diagrams for confusing people more ;php ; make php less awful to work with
purescript ; javascript, but functional ;plantuml ; diagrams for confusing people more
python ; beautiful is better than ugly ;purescript ; javascript, but functional
rest ; Emacs as a REST client ;python ; beautiful is better than ugly
ruby ; 1.step do {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"} ;rest ; Emacs as a REST client
rust ; Fe2O3.unwrap().unwrap().unwrap().unwrap() ;ruby ; 1.step do {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"}
scala ; java, but good ;rust ; Fe2O3.unwrap().unwrap().unwrap().unwrap()
sh ; she sells (ba|z)sh shells on the C xor ;scala ; java, but good
swift ; who asked for emoji variables? ;sh ; she sells (ba|z)sh shells on the C xor
typescript ; javascript, but better ;swift ; who asked for emoji variables?
web ; the tubes ;typescript ; javascript, but better
;web ; the tubes
:org :org
org ; organize your plain life in plain text org ; organize your plain life in plain text
org-babel ; executable code snippets in org-mode org-babel ; executable code snippets in org-mode
;org-attach ; FIXME my own, simpler attachment system org-attach ; a simpler attachment system
org-capture ; a better org-capture, in or outside of Emacs org-capture ; a better org-capture, in or outside of Emacs
org-export ; a custom, centralized export system org-export ; a custom, centralized export system
org-notebook ; org-mode as a notebook org-notebook ; org-mode as a notebook

View file

@ -4,10 +4,7 @@
;; by apps Reeder and Readkit. It can be invoked via `=rss'. Otherwise, if you ;; by apps Reeder and Readkit. It can be invoked via `=rss'. Otherwise, if you
;; don't care for the UI you can invoke elfeed directly with `elfeed'. ;; don't care for the UI you can invoke elfeed directly with `elfeed'.
(defvar +rss-org-dir (concat +org-dir "/rss/") (defvar +rss-elfeed-files (list "rss/elfeed.org")
"Where RSS org files are located.")
(defvar +rss-elfeed-files (list "elfeed.org")
"The files that configure `elfeed's rss feeds.") "The files that configure `elfeed's rss feeds.")
(defvar +rss-split-direction 'below (defvar +rss-split-direction 'below
@ -62,6 +59,6 @@
:after elfeed :after elfeed
:config :config
(setq rmh-elfeed-org-files (setq rmh-elfeed-org-files
(let ((default-directory +rss-org-dir)) (let ((default-directory +org-dir))
(mapcar #'expand-file-name +rss-elfeed-files))) (mapcar #'expand-file-name +rss-elfeed-files)))
(elfeed-org)) (elfeed-org))

View file

@ -295,7 +295,6 @@ the new algorithm is confusing, like in python or ruby."
:config :config
(global-evil-mc-mode +1) (global-evil-mc-mode +1)
(unless doom-init-p
;; Add custom commands to whitelisted commands ;; Add custom commands to whitelisted commands
(dolist (fn '(doom/deflate-space-maybe doom/inflate-space-maybe (dolist (fn '(doom/deflate-space-maybe doom/inflate-space-maybe
doom/backward-to-bol-or-indent doom/forward-to-last-non-comment-or-eol doom/backward-to-bol-or-indent doom/forward-to-last-non-comment-or-eol
@ -304,7 +303,7 @@ the new algorithm is confusing, like in python or ruby."
evil-mc-custom-known-commands)) evil-mc-custom-known-commands))
;; disable evil-escape in evil-mc; causes unwanted text on invocation ;; disable evil-escape in evil-mc; causes unwanted text on invocation
(push 'evil-escape-mode evil-mc-incompatible-minor-modes)) (push 'evil-escape-mode evil-mc-incompatible-minor-modes)
(defun +evil|escape-multiple-cursors () (defun +evil|escape-multiple-cursors ()
"Clear evil-mc cursors and restore state." "Clear evil-mc cursors and restore state."

View file

@ -3,6 +3,8 @@
(def-package! hydra (def-package! hydra
:commands (+hydra-zoom/body +hydra-window/body defhydra) :commands (+hydra-zoom/body +hydra-window/body defhydra)
:config :config
(setq lv-use-separator t)
(defhydra +hydra-zoom (:hint t :color red) (defhydra +hydra-zoom (:hint t :color red)
"zoom" "zoom"
("j" text-scale-increase "in") ("j" text-scale-increase "in")

View file

@ -0,0 +1,19 @@
;;; lang/ledger/config.el -*- lexical-binding: t; -*-
(def-package! ledger-mode
:mode "\\.ledger$"
:commands ledger-mode
:config
(setq ledger-clear-whole-transactions 1))
(def-package! evil-ledger
:when (featurep! :feature evil)
:after ledger-mode
:config
(add-hook 'ledger-mode-hook #'evil-ledger-mode))
(def-package! flycheck-ledger
:when (featurep! :feature syntax-checker)
:init (add-hook 'ledger-mode-hook #'flycheck-mode))

View file

@ -0,0 +1,10 @@
;; -*- no-byte-compile: t; -*-
;;; lang/ledger/packages.el
(package! ledger-mode)
(when (featurep! :feature evil)
(package! evil-ledger))
(when (featurep! :feature syntax-checker)
(package! flycheck-ledger))

View file

@ -1,33 +1,10 @@
;;; org/org-attach/autoload/evil.el -*- lexical-binding: t; -*- ;;; org/org-attach/autoload/evil.el -*- lexical-binding: t; -*-
;;;###autoload (autoload '+org-attach:dwim "org/org-attach/autoload/evil" nil t) ;; TODO +org-attach:find
(evil-define-command +org-attach:dwim (&optional uri)
"An evil ex interface to `+org-attach/dwim'." ;;;###autoload (autoload '+org-attach:uri "org/org-attach/autoload/evil" nil t)
(interactive "<a>") (evil-define-command +org-attach:uri (uri)
(unless (eq major-mode 'org-mode) "Downloads the file at URL and places an org link to it at the cursor."
(user-error "Not in an org-mode buffer")) (interactive "<f>")
(if uri (+org-attach/uri uri))
(let* ((rel-path (org-download--fullname uri))
(new-path (expand-file-name rel-path))
(image-p (image-type-from-file-name uri)))
(cond ((string-match-p (concat "^" (regexp-opt '("http" "https" "nfs" "ftp" "file")) ":/") uri)
(url-copy-file uri new-path))
(t (copy-file uri new-path)))
(unless new-path
(user-error "No file was provided"))
(if (evil-visual-state-p)
(org-insert-link nil (format "./%s" rel-path)
(concat (buffer-substring-no-properties (region-beginning) (region-end))
" " (org-attach--icon rel-path)))
(insert (if image-p
(format "[[./%s]] " rel-path)
(format "%s [[./%s][%s]] "
(org-attach--icon rel-path)
rel-path (file-name-nondirectory (directory-file-name rel-path))))))
(when (string-match-p (regexp-opt '("jpg" "jpeg" "gif" "png")) (file-name-extension rel-path))
(org-redisplay-inline-images)))
(let ((default-directory ".attach/"))
(if (file-exists-p default-directory)
(call-interactively 'find-file)
(user-error "No attachments")))))

View file

@ -13,43 +13,104 @@
((or "zip" "gz" "tar" "7z" "rar") ?) ((or "zip" "gz" "tar" "7z" "rar") ?)
(_ ?)))) (_ ?))))
;;;###autoload ;; (defun +org-attach-cleanup ()
(defun +org-attach-cleanup () ;; ;; "Deletes any attachments that are no longer present in the org-mode buffer."
;; "Deletes any attachments that are no longer present in the org-mode buffer." ;; (let* ((attachments-local (+org-attachments))
(let* ((attachments-local (+org-attachments)) ;; (attachments (directory-files org-attach-directory t "^[^.]" t))
(attachments (directory-files org-attach-directory t "^[^.]" t)) ;; (to-delete (cl-set-difference attachments-local attachments)))
(to-delete (cl-set-difference attachments-local attachments))) ;; ;; TODO
;; TODO ;; to-delete))
to-delete))
(defun +org-attachments () ;; (defun +org-attachments ()
"List all attachments in the current buffer." ;; "List all attachments in the current buffer."
;; (unless (eq major-mode 'org-mode)
;; (user-error "Not an org buffer"))
;; (org-save-outline-visibility nil
;; (let ((attachments '())
;; element)
;; (when (and (file-directory-p org-attach-directory)
;; (> (length (file-expand-wildcards (expand-file-name "*" org-attach-directory))) 0))
;; (save-excursion
;; (goto-char (point-min))
;; (while (progn (org-next-link) (not org-link-search-failed))
;; (setq element (org-element-context))
;; (when-let (file (and (eq (org-element-type element) 'link)
;; (expand-file-name (org-element-property :path element))))
;; (when (and (string= (org-element-property :type element) "file")
;; (string= (concat (file-name-base (directory-file-name (file-name-directory file))) "/")
;; org-attach-directory)
;; (file-exists-p file))
;; (push file attachments))))))
;; (cl-remove-duplicates attachments))))
;;;###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."
(interactive "sUri/file: ")
(unless (eq major-mode 'org-mode) (unless (eq major-mode 'org-mode)
(user-error "Not an org buffer")) (user-error "Not in an org buffer"))
(org-save-outline-visibility nil (require 'org-download)
(let ((attachments '()) (condition-case ex
element) (cond ((string-match-p "^data:image/png;base64," uri)
(when (and (file-directory-p org-attach-directory) (org-download-dnd-base64 uri nil))
(> (length (file-expand-wildcards (expand-file-name "*" org-attach-directory))) 0)) ((image-type-from-file-name uri)
(save-excursion (org-download-image uri))
(goto-char (point-min)) (t
(while (progn (org-next-link) (not org-link-search-failed)) (let ((new-path (expand-file-name (org-download--fullname uri))))
(setq element (org-element-context)) ;; Download the file
(when-let (file (and (eq (org-element-type element) 'link) (if (string-match-p (concat "^" (regexp-opt '("http" "https" "nfs" "ftp" "file")) ":/") uri)
(expand-file-name (org-element-property :path element)))) (url-copy-file uri new-path)
(when (and (string= (org-element-property :type element) "file") (copy-file uri new-path))
(string= (concat (file-name-base (directory-file-name (file-name-directory file))) "/") ;; insert the link
org-attach-directory) (org-download-insert-link uri new-path))))
(file-exists-p file)) (error
(push file attachments)))))) (user-error "Failed to attach file: %s" (error-message-string ex)))))
(cl-remove-duplicates attachments))))
;;;###autoload ;;;###autoload
(defun +org-attach-download-dnd (uri action) (defun +org-attach-download-dnd (uri action)
"TODO"
(if (eq major-mode 'org-mode) (if (eq major-mode 'org-mode)
(doom:org-attach uri) ;; FIXME (+org-attach:url uri)
(let ((dnd-protocol-alist (let ((dnd-protocol-alist
(rassq-delete-all '+org-attach-download-dnd (rassq-delete-all '+org-attach-download-dnd
(copy-alist dnd-protocol-alist)))) (copy-alist dnd-protocol-alist))))
(dnd-handle-one-url nil action uri)))) (dnd-handle-one-url nil action uri))))
;;;###autoload
(defun +org-attach*link-format (filename &optional ext)
(format "%s%s.%s"
(file-name-sans-extension filename)
(format-time-string org-download-timestamp)
(or ext (file-name-extension filename))))
;;;###autoload
(defun +org-attach*insert-link (link filename)
"TODO"
(if (looking-back "^[ \t]+" (line-beginning-position))
(delete-region (match-beginning 0) (match-end 0))
(newline))
(cond ((image-type-from-file-name filename)
(insert
(concat (if (= org-download-image-html-width 0)
""
(format "#+attr_html: :width %dpx\n" org-download-image-html-width))
(if (= org-download-image-latex-width 0)
""
(format "#+attr_latex: :width %dcm\n" org-download-image-latex-width))
(format org-download-link-format
(file-relative-name filename (file-name-directory buffer-file-name)))))
(org-display-inline-images))
(t
(insert
(format "%s [[./%s][%s]] "
(org-attach--icon filename)
(file-relative-name filename buffer-file-name)
(file-name-nondirectory (directory-file-name rel-path)))))))

View file

@ -4,46 +4,69 @@
"Where to store attachments (relative to current org file).") "Where to store attachments (relative to current org file).")
(add-hook '+org-init-hook #'+org|init-attach t) (add-hook 'org-load-hook #'+org-attach|init t)
;; FIXME This module is broken and needs to be rewritten.
;;
;; I believe Org's native attachment system is over-complicated and litters ;; I believe Org's native attachment system is over-complicated and litters
;; files with metadata I don't want. ;; files with metadata I don't want. So I wrote my own, which:
;; ;;
;; This installs my own attachment system. It: ;; + Causes attachments to be placed in a centralized location,
;; ;; + Adds drag-and-drop support for images (with inline image preview)
;; + Centralizes attachment in a global location, ;; + Adds drag-and-drop support for media files (pdfs, zips, etc) with a
;; + Adds drag-and-drop file support ;; filetype icon and short link.
;; + TODO ...with attachment icons, and
;; + TODO Offers an attachment management system. ;; + TODO Offers an attachment management system.
;; Some commands of interest:
;; + `org-download-screenshot'
;; + `+org-attach/file'
;; + `+org-attach/url'
;; + :org [FILE/URL]
(def-package! org-download (def-package! org-download
:commands (org-download-dnd org-download-dnd-base64)
:init
;; Add these myself, so that org-download is lazy-loaded...
(setq dnd-protocol-alist
`(("^\\(https?\\|ftp\\|file\\|nfs\\):" . +org-attach-download-dnd)
("^data:" . org-download-dnd-base64)
,@dnd-protocol-alist))
(advice-add #'org-download-enable :override #'ignore)
:config :config
(setq-default org-download-image-dir +org-attach-dir (setq-default org-download-image-dir +org-attach-dir
org-download-heading-lvl nil org-download-heading-lvl nil
org-download-timestamp "_%Y%m%d_%H%M%S") org-download-timestamp "_%Y%m%d_%H%M%S")
(setq org-download-screenshot-method (setq org-download-screenshot-method
(cond (IS-MAC "screencapture -i %s") (cond (IS-MAC "screencapture -i %s")
(IS-LINUX "maim --opengl -s %s"))) (IS-LINUX
(cond ((executable-find "maim")
"maim -s %s")
((executable-find "scrot")
"scrot -s %s")))))
;; Handle non-image files a little differently. Images should be inserted
;; as-is, as image previews. Other files, like pdfs or zips, should be linked
;; to, with an icon indicating the type of file.
(advice-add #'org-download-insert-link :override #'+org-attach*insert-link)
(defun +org-attach*download-subdir ()
(when (file-in-directory-p buffer-file-name +org-dir)
(file-relative-name buffer-file-name +org-dir)))
;; Write download paths relative to current file ;; Write download paths relative to current file
(defun +org-attach*download-fullname (path) (defun +org-attach*download-fullname (path)
(file-relative-name path (file-name-directory (buffer-file-name)))) (file-relative-name path (file-name-directory buffer-file-name)))
(advice-add #'org-download--dir-2 :override #'ignore) (advice-add #'org-download--dir-2 :override #'ignore)
(advice-add #'org-download--fullname (advice-add #'org-download--fullname
:filter-return #'+org-attach*download-fullname)) :filter-return #'+org-attach*download-fullname))
;; ;;
(defun +org-attach|init () (defun +org-attach|init ()
(setq org-attach-directory +org-attach-directory) (setq org-attach-directory +org-attach-dir)
(push +org-attach-dir projectile-globally-ignored-directories)
(push ".attach" projectile-globally-ignored-file-suffixes)
(after! recentf (after! recentf
(push (format "/%s.+$" (regexp-quote +org-attach-dir)) (push (format "%s.+$" (regexp-quote +org-attach-dir))
recentf-exclude)) recentf-exclude)))
(require 'org-download)
;; Add another drag-and-drop handler that will handle anything but image files
(push '("^\\(https?\\|ftp\\|file\\|nfs\\):\\(//\\)?" . +org-attach-download-dnd) dnd-protocol-alist))

View file

@ -17,8 +17,11 @@
(setq org-default-notes-file (concat +org-dir "notes.org") (setq org-default-notes-file (concat +org-dir "notes.org")
;; FIXME This is incomplete! ;; FIXME This is incomplete!
org-capture-templates org-capture-templates
'(;; TODO: New Task (todo) '(;; TODO: New vocabulary word
;; TODO: New vocabulary word
("t" "Todo" entry
(file+headline (expand-file-name "todo.org" +org-dir) "Inbox")
"* [ ] %?")
("c" "Changelog" entry ("c" "Changelog" entry
(file+headline (expand-file-name "CHANGELOG.org" (doom-project-root)) "Unreleased") (file+headline (expand-file-name "CHANGELOG.org" (doom-project-root)) "Unreleased")

View file

@ -13,10 +13,10 @@
;;;###autoload ;;;###autoload
(defun +org|realign-table-maybe () (defun +org|realign-table-maybe ()
"Auto-align table under cursor." "Auto-align table under cursor and re-calculate formulas."
(when (org-at-table-p) (when (org-at-table-p)
(save-excursion (save-excursion
(org-table-align)))) (quiet! (org-table-recalculate)))))
;;;###autoload ;;;###autoload
(defun +org|update-cookies () (defun +org|update-cookies ()
@ -26,55 +26,82 @@
;;;###autoload ;;;###autoload
(defun +org/dwim-at-point () (defun +org/dwim-at-point ()
"Do-what-I-mean at point. This includes following timestamp links, aligning "Do-what-I-mean at point.
tables, toggling checkboxes/todos, executing babel blocks, previewing latex
fragments, opening links, or refreshing images." If on a:
- checkbox list item or todo heading: toggle it.
- clock: update its time.
- headline: toggle latex fragments and inline images underneath.
- footnote definition: jump to the footnote
- table-row or a TBLFM: recalculate the table's formulas
- table-cell: clear it and go into insert mode. If this is a formula cell,
recaluclate it instead.
- babel-call: execute the source block
- statistics-cookie: update it.
- latex fragment: toggle it.
- link: follow it
- otherwise, refresh all inline images in current tree."
(interactive) (interactive)
(let* ((scroll-pt (window-start)) (let* ((scroll-pt (window-start))
(context (org-element-context)) (context (org-element-context))
(type (org-element-type context))) (type (org-element-type context)))
(cond (pcase type
((memq type '(planning timestamp)) ((guard (org-element-property :checkbox (org-element-lineage context '(item) t)))
(org-follow-timestamp-link))
((memq type '(table table-row))
(if (org-element-property :tblfm (org-element-property :parent context))
(org-table-recalculate t)
(org-table-align)))
((org-element-property :checkbox (org-element-lineage context '(item) t))
(let ((match (and (org-at-item-checkbox-p) (match-string 1)))) (let ((match (and (org-at-item-checkbox-p) (match-string 1))))
(org-toggle-checkbox (if (equal match "[ ]") '(16))))) (org-toggle-checkbox (if (equal match "[ ]") '(16)))))
((and (eq type 'headline) (`headline
(org-element-property :todo-type context)) (cond ((org-element-property :todo-type context)
(org-todo (org-todo
(if (eq (org-element-property :todo-type context) 'done) 'todo 'done))) (if (eq (org-element-property :todo-type context) 'done) 'todo 'done)))
((string= "ARCHIVE" (car-safe (org-get-tags)))
((and (eq type 'headline)
(string= "ARCHIVE" (car-safe (org-get-tags))))
(org-force-cycle-archived)) (org-force-cycle-archived))
(t
((eq type 'headline)
(org-remove-latex-fragment-image-overlays) (org-remove-latex-fragment-image-overlays)
(org-toggle-latex-fragment '(4))) (org-toggle-latex-fragment '(4)))))
((eq type 'babel-call) (`clock (org-clock-update-time-maybe))
(`footnote-definition
(goto-char (org-element-property :post-affiliated context))
(call-interactively #'org-footnote-action))
((or `planning `timestamp) (org-follow-timestamp-link))
((or `table `table-row)
(if (org-at-TBLFM-p)
(org-table-calc-current-TBLFM)
(ignore-errors
(save-excursion
(goto-char (org-element-property :contents-begin context))
(org-call-with-arg 'org-table-recalculate (or arg t))))))
(`table-cell
(org-table-blank-field)
(org-table-recalculate)
(when (and (string-empty-p (string-trim (org-table-get-field)))
(bound-and-true-p evil-mode))
(evil-change-state 'insert)))
(`babel-call
(org-babel-lob-execute-maybe)) (org-babel-lob-execute-maybe))
((memq type '(src-block inline-src-block)) (`statistics-cookie
(save-excursion (org-update-statistics-cookies nil)))
((or `src-block `inline-src-block)
(org-babel-execute-src-block)) (org-babel-execute-src-block))
((memq type '(latex-fragment latex-environment)) ((or `latex-fragment `latex-environment)
(org-toggle-latex-fragment)) (org-toggle-latex-fragment))
((eq type 'link) (`link
(let ((path (org-element-property :path (org-element-lineage context '(link) t)))) (let ((path (org-element-property :path (org-element-lineage context '(link) t))))
(if (and path (image-type-from-file-name path)) (if (and path (image-type-from-file-name path))
(+org/refresh-inline-images) (+org/refresh-inline-images)
(org-open-at-point)))) (org-open-at-point))))
(t (+org/refresh-inline-images))) (_ (+org/refresh-inline-images)))
(set-window-start nil scroll-pt))) (set-window-start nil scroll-pt)))
;;;###autoload ;;;###autoload
@ -232,11 +259,16 @@ wrong places)."
;;;###autoload ;;;###autoload
(defun +org/toggle-fold () (defun +org/toggle-fold ()
"Toggle the local fold at the point (as opposed to cycling through all levels "Toggle the local fold at the point (as opposed to cycling through all levels
with `org-cycle'). Also removes babel result blocks, if run from a code block." with `org-cycle'). Also:
+ If in a babel block, removes result blocks.
+ If in a table, realign it, if necessary."
(interactive) (interactive)
(save-excursion (save-excursion
(org-beginning-of-line) (org-beginning-of-line)
(cond ((org-in-src-block-p) (cond ((org-table-p)
(org-table-align))
((org-in-src-block-p)
(org-babel-remove-result)) (org-babel-remove-result))
((org-at-heading-p) ((org-at-heading-p)
(outline-toggle-children)) (outline-toggle-children))

View file

@ -117,6 +117,9 @@
org-startup-indented t org-startup-indented t
org-startup-with-inline-images nil org-startup-with-inline-images nil
org-tags-column 0 org-tags-column 0
org-todo-keywords '((sequence "[ ](t)" "[-](p)" "[?](m)" "|" "[X](d)")
(sequence "TODO(T)" "|" "DONE(D)")
(sequence "IDEA(i)" "NEXT(n)" "ACTIVE(a)" "WAITING(w)" "LATER(l)" "|" "CANCELLED(c)"))
org-use-sub-superscripts '{} org-use-sub-superscripts '{}
outline-blank-line t outline-blank-line t

View file

@ -116,15 +116,20 @@ whose dimensions may not be fully initialized by the time this is run."
(or (and (featurep! :ui doom-modeline) (or (and (featurep! :ui doom-modeline)
(doom-modeline 'project)) (doom-modeline 'project))
mode-line-format))) mode-line-format)))
(let ((old-pwd (or dir default-directory))) (let ((+doom-dashboard--width 80)
(with-current-buffer (doom-fallback-buffer) (old-pwd (or dir default-directory))
(fallback-buffer (doom-fallback-buffer)))
(dolist (win (get-buffer-window-list fallback-buffer nil t))
(set-window-fringes win 0 0)
(set-window-margins
win (max 0 (/ (- (window-total-width win) +doom-dashboard--width) 2))))
(with-current-buffer fallback-buffer
(with-silent-modifications (with-silent-modifications
(unless (eq major-mode '+doom-dashboard-mode) (unless (eq major-mode '+doom-dashboard-mode)
(+doom-dashboard-mode)) (+doom-dashboard-mode))
(erase-buffer) (erase-buffer)
(setq default-directory old-pwd) (setq default-directory old-pwd)
(let ((+doom-dashboard--width (window-width)) (let ((+doom-dashboard--height (window-height)))
(+doom-dashboard--height (window-height)))
(insert (make-string (max 0 (- (truncate (/ +doom-dashboard--height 2)) 16)) ?\n)) (insert (make-string (max 0 (- (truncate (/ +doom-dashboard--height 2)) 16)) ?\n))
(dolist (widget-name +doom-dashboard-widgets) (dolist (widget-name +doom-dashboard-widgets)
(funcall (intern (format "doom-dashboard-widget--%s" widget-name))) (funcall (intern (format "doom-dashboard-widget--%s" widget-name)))

View file

@ -255,9 +255,9 @@ If TRUNCATE-TAIL is t also truncate the parent directory of the file."
(basename (cdr dirs)) (basename (cdr dirs))
(dir-faces (or modified-faces (if active 'doom-modeline-project-root-dir))) (dir-faces (or modified-faces (if active 'doom-modeline-project-root-dir)))
(file-faces (or modified-faces (if active 'doom-modeline-buffer-file)))) (file-faces (or modified-faces (if active 'doom-modeline-buffer-file))))
(concat (propertize dirname (concat (propertize (concat dirname
'face (if dir-faces `(:inherit ,dir-faces))) (if truncate-tail (substring basename 0 1) basename)
(propertize (concat (if truncate-tail (substring basename 0 1) basename) "/") "/")
'face (if dir-faces `(:inherit ,dir-faces))) 'face (if dir-faces `(:inherit ,dir-faces)))
(propertize (file-name-nondirectory buffer-file-name) (propertize (file-name-nondirectory buffer-file-name)
'face (if file-faces `(:inherit ,file-faces))))))))) 'face (if file-faces `(:inherit ,file-faces)))))))))