Merge branch 'develop' into release-2.0.4

* develop: (45 commits)
  General cleanup
  Update changelog
  Refactor doom-get-packages
  Refactor doom-initialize-packages
  Refactor core.el
  Enable shackle-mode later in startup process
  Appease byte-compiler
  Bind e => debugger-eval-expression in debugger
  Less 'nowhere to go' spam on doom/kill-this-buffer
  Add display-line-numbers support in Emacs 26 #59
  Remove (interactive) from non-interactive funcs
  Refactor doom-popup-size (cond -> pcase)
  Refactor doom-popup-prop (cond -> pcase)
  Fix wrong-type-argument: bufferp error on ESC
  Revert 8edba655: disable undo persistence
  Refactor makefile
  Rename core + module byte-compilation make tasks
  doom/clean-compiled => doom/clean-compiled-files
  Rename doom/clean-cache => doom/reset (+ make reset)
  Rename bin/doctor => bin/doom-doctor
  ...
This commit is contained in:
Henrik Lissner 2017-07-14 15:25:30 +02:00
commit 0541e48370
36 changed files with 644 additions and 286 deletions

View file

@ -2,6 +2,7 @@
- [[#todo][Todo]]
- [[#unreleased-master][Unreleased (master)]]
- [[#204-jul-14-2017][2.0.4 (Jul 14, 2017)]]
- [[#203-jun-11-2017][2.0.3 (Jun 11, 2017)]]
- [[#202-may-13-2017][2.0.2 (May 13, 2017)]]
- [[#201-apr-8-2017][2.0.1 (Apr 8, 2017)]]
@ -21,7 +22,7 @@
+ =lang/latex= [[https://github.com/Malabarba/latex-extra][latex-extra]] (utility commands)
+ =lang/latex= [[**https://github.com/jsinglet/latex-preview-pane][latex-preview-pane]]
+ =lang/julia= [[ https://github.com/dennisog/julia-shell-mode][julia-shell]] (unsure if better than inferior-julia in julia-mode)
+ =lang/python= [[https://github.com/Wilfred/pyimport][pyimport]]
+ =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?)
+ =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.
@ -44,12 +45,12 @@
+ Syntax highlighter for ~+regex-mode~ (plus make it a major mode)
+ 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-attach= -- my own, simpler attachment system with drag-drop image attachment support and centralized storage.
+ *Bug fixes:*
+ =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.
+ =ui/doom-modeline= Fix ~0/0~ leftover panel in modeline (caused by lingering anzu state).
+ =lang/org=
+ Drag-drop image attachment (~org-download~) and central storage
+ Unified export system
+ =org=
+ Better shackle + org-agenda integration
+ Fix janky visual line motions (~evil-next-visual-line~, etc)
+ Fix janky cursor positioning when jumping between org-table cells from insert mode.
@ -64,13 +65,30 @@
+ Document best practices for customizing DOOM emacs.
+ =ui/doom-modeline= fix hardcoded spacing in between segments.
+ Rewrite main README.md to include more information about setting up, customizing, and troubleshooting DOOM Emacs.
+ Update =bin/org-capture= to read from stdin in the absence of arguments.
* Unreleased (master)
+ *New modules:*
+ =tools/password-store= -- Emacs as a password manager, using [[https://www.passwordstore.org/][pass]] as a backend (contributed by [[https://github.com/bandresen][brandresen]]).
+ =app/irc= -- Emacs as an IRC client, using circe (contributed by [[https://github.com/bandresen][brandresen]]).
* 2.0.4 (Jul 14, 2017)
+ *Module changes:*
+ Added =tools/password-store= -- Emacs as a password manager, using [[https://www.passwordstore.org/][pass]] as a backend (contributed by [[https://github.com/bandresen][brandresen]]).
+ Added =app/irc= -- Emacs as an IRC client, using circe (contributed by [[https://github.com/bandresen][brandresen]]).
+ ~+pass/ivy~ for ivy integration, with edit/copy field/open url actions.
+ ~helm-pass~ for helm integration.
+ Added =lang/hy= -- support for [[http://hylang.org][hylang]], a combination of Lisp and Python (thanks to [[https://github.com/bandresen][bandresen]]).
+ Added =lang/ocaml= -- support for [[https://ocaml.org/][OCAML]] (thanks to [[https://github.com/Ptival][Ptival]])
+ Added =lang/plantuml= -- drawing diagrams in plain text
+ Added =lang/perl= -- Perl6 support for Emacs
+ Added =ui/tabbar= -- add tabs to Doom via [[https://github.com/dholm/tabbar][tabbar]] (I don't recommend using it)
+ Removed =lang/org=
+ Added =org= -- a new module category for org and org extensions
+ Removed =app/present= (replaced mostly with =org/org-present=)
+ =org/org-babel= -- executable code snippets in org-mode, with support for a variety of languages.
+ =org/org-capture= -- a better org-capture, in or outside of Emacs.
+ =org/org-export= -- a centralized export system with more export backends.
+ =org/org-notebook= -- org-mode as a general notebook.
+ =org/org-present= -- org-mode for presentations.
+ Added =tools/impatient-mode= -- show off live buffers via HTTP.
+ =core=
+ New variable: ~doom-host-dir~, as a base path for ~doom-etc-dir~ and ~doom-cache-dir~.
+ New hooks: ~doom-init-hook~ and ~doom-post-init-hook~, which are run on ~emacs-startup-hook~. This is meant to simplify post-Emacs initialization hooks (~after-init-hook~, ~emacs-startup-hook~ and ~window-setup-hook~) into two unambiguous ones.
@ -78,20 +96,29 @@
+ Improve error handling across the board. Emacs should now report more helpful errors. Catastrophic errors will be less likely to inhibit later modules from being loaded.
+ Unit-tests have been moved to their respective modules (and =core/test/=).
+ Fix ~def-setting!~ to act more like ~defmacro~; don't aggressively evaluate its arguments on expansion.
+ New function: ~doom-set-buffer-real BUFFER FLAG~ -- makes Doom consider BUFFER real, no matter what.
+ Add ~INSTALLED-ONLY-P~ argument to ~doom-get-packages~ to filter packages that aren't installed.
+ =core-ui=
+ Add quit confirmation when trying to close a frame that contains real buffers.
+ Fix quit confirmations for clients connected to ~emacs --daemon~ with ~emacsclient~.
+ Brought back [[https://github.com/hlissner/emacs-nlinum-hl][nlinum-hl]], which offers some line number fixes for web-mode and markdown-mode.
+ Don't report the buffer modified when injecting (or deleting) trailing whitespace in ~doom|inject-trailing-whitespace~ and ~doom|init-highlight-indentation~.
+ [[https://github.com/domtronn/all-the-icons.el][all-the-icons]] now fails gracefully in the terminal.
+ New hook: ~doom-init-ui-hook~, run whenever the UI needs to be reloaded (and once at startup). Theme and font loading is also attached to this hook.
+ New variables for font and theme loading: ~doom-theme~, ~doom-font~, ~doom-variable-pitch-font~, and ~doom-unicode-font~.
+ New variables for customizing line numbers: ~doom-line-number-lpad~, ~doom-line-number-rpad~, and ~doom-line-number-pad-char~. These were added to facilitate custom whitespace characters in line numbers, e.g. /u2002 (a unicode character that looks like a space). Doing so fixes an issue where ~whitespace-mode~ with ~space-mark~ would replace all space characters indiscriminately, even in line numbers.
+ Add hooks ~doom-pre-reload-theme-hook~ and ~doom-post-reload-theme-hook~ to ~doom/reload-theme~ command.
+ =core-popups=
+ Fix an issue where more specific popup rules were being overriden by more general rules.
+ New command: ~doom/other-popup~ -- cycles between open popup windows and the original buffer that you originated from. Discussed in [[https://github.com/hlissner/.emacs.d/issues/141][#141]].
+ =core-editor=
+ Change what files recentf will ignore: everything in ~doom-host-dir~ is now ignored and anything else in ~doom-local-dir~ won't be.
+ New interactive command: ~doom/scratch-buffer~ (replaces ~+doom:scratch-buffer~ in =:ui doom=).
+ =core-packages=
+ Generalize ~doom-package-*-p~ functions into ~(doom-package-prop NAME PROPERTY)~.
+ Fix quelpa temporary files (in ~quelpa-build-dir~) not being removed when a quelpa package is uninstalled.
+ Fix quelpa temporary files (in ~quelpa-build-dir~) not being removed when a quelpa package was uninstalled.
+ New hook: ~doom-reload-hook~ (sort of). This has been around for a while, but now it is defined and documented. It runs when ~doom/reload~ is called (which gets called remotely if you run package management while an Emacs session is active).
+ ~load!~ can now accept a string as its first argument (the path).
+ =feature=
+ =feature/evil=
+ Remove =goto-last-change=, which conflicts with =goto-chg=, which is a dependency of evil (that does the exact same thing, but is what evil uses).
@ -102,25 +129,43 @@
+ ~:references~: lists all references of the symbol at point and lets you jump to them.
+ ~:documentation~: shows documentation for the symbol at point.
+ ~:xref-backend~: a function that serves as an xref backend; this replaces ~:definition~ and ~:references~.
+ =feature/workspaces=
+ New function: ~+workspace-contains-buffer-p &optional BUFFER PERSP~ -- return non-nil if BUFFER (defaults to current buffer) is in PERSP (defaults to current perspective).
+ Fix ~+workspace-p~ not detecting a perspective struct.
+ Fix ~+workspace-buffer-list~ not preserving buffer order (by recency).
+ =completion=
+ =completion/company=
+ Add ~company-dabbrev~ and ~company-ispell~ to the default Company backends. This ensures you have some completion available in buffers previously without any. This is especially useful for text-mode buffers. Discussed in [[https://github.com/hlissner/.emacs.d/issues/134][#134]].
+ =ui=
+ =ui/doom=
+ Vastly improve daemon and terminal support for doom-themes by reloading the theme when a new client is attached, or new terminal/daemon frame is created. This prevents incorrect colors from bleeding across face class barriers.
+ Removed evil command ~+doom:scratch-buffer~ (replaced with ~doom/scratch-buffer~ in =core-ui=).
+ Decoupled font and theme loading from this module. This has now been delegated to =core-ui=. These variables no longer exist: ~+doom-theme~, ~+doom-font~, ~+doom-variable-pitch-font~, ~+doom-unicode-font~. Discussed in [[https://github.com/hlissner/.emacs.d/issues/117][#117]].
+ =ui/doom-dashboard=
+ Fix dashboard not opening in emacsclient/daemon frames.
+ Add =gg= and =G= keybinds in dashboard for moving to the first and last button (respectively).
+ =ui/doom-modeline=
+ Reorganize order of modeline segments, placing the vc branch last. This minimizes the non-uniform spacing that all-the-icon icons cause.
+ Reorganize order of modeline segments, placing the vc branch last. This minimizes the non-uniform spacing caused by all-the-icon icons.
+ Fix blank mode-line caused by a nil buffer-file-name (used in vcs segment). For example, in org indirect buffers.
+ =tools=
+ =tools/neotree=
+ Fix neotree refusing to open when it was already open in another frame. This is especially frustrating when neotree is open in a (likely buried) terminal emacsclient session, and you're trying to open neotree in another.
+ =lang=
+ =lang/cc=
+ Add code completion to glsl-mode (powered by [[https://github.com/Kaali/company-glsl][company-glsl]]).
+ =lang/markdown=
+ Source blocks are now fontified natively, with the fontification of their native major-modes (see ~markdown-fontify-code-blocks-natively~).
+ =lang/org=
+ =lang/sh=
+ Fix fontification of command substitutions in double-quoted strings to help distinguish them from the rest of string literals.
+ =lang/web=
+ Fix HTML entity encoding/decoding functions.
+ =org=
+ =org/org=
+ Fix M-RET in plain lists not preserving indent level for new items.
+ Fix cursor jumping away when toggling folds or realigning org tables (pressing TAB).
+ =lang/sh=
+ Fix fontification of command substitutions in double-quoted strings to help distinguish them from the rest of the string literal.
+ Minimized keybindings into the bare necessities; most custom bindings have been moved to my private module.
+ =org/org-capture=
+ Start org-capture-mode in insert-mode (if evil is loaded).
* 2.0.3 (Jun 11, 2017)
+ *New modules*
@ -142,6 +187,9 @@
+ New variable: ~doom-ui-mode-names~ (alist) -- for changing ~mode-name~ of major-modes.
+ Fix left-over hl-line overlays when hl-line-mode is uncleanly killed (e.g. when the major-mode is changed).
+ Fix disappearing line numbers in nlinum (thanks to [[https://github.com/gilbertw1][gilbertw1]]).
+ Move theme/font bootstrap to core-ui.
+ New hook: ~doom-init-ui-hook~
+ New global minor-mode ~doom-big-font-mode~ and variable ~doom-big-font~.
+ =core-keybinds=
+ New property for ~map!~: ~:textobj~ -- for binding to evil text objects keymaps.
+ Fix ~:after~ & ~:map*~ properties in ~map!~ macro (wasn't working at all).
@ -176,16 +224,28 @@
+ Call ~recenter~ after using [[https://github.com/jacktasia/dumb-jump][dumb-jump]].
+ =feature/workspaces=
+ No longer saves session on quit if session was blank.
+ Fix persp-mode switching to main workspace if auto-resume is on.
+ Fix ~+workspace-get~ returning a non-nil "null perspective" on some occasions where NAME doesn't exist. This is because ~persp-get-by-name~ returns the value of ~persp-not-persp~ to signify null instead of actual nil.
+ Decouple workspace buffer-list functions from doom buffer library. Now, the workspaces module will explicitly advise ~doom-buffer-list~.
+ ~+workspace-list~ now returns a list of perspective structs, rather than a list of strings. ~+workspace-list-names~ was introduced for the latter.
+ =completion=
+ =completion/company=
+ Change ~:company-backends~ to accept a variadic list of backends to prepend to ~company-backends~. Its signature is now ~(set! :company-backends MODES &rest BACKENDS)~ ([[https://github.com/hlissner/.emacs.d/pull/125][#125]]).
+ =completion/ivy=
+ Flexible column width for ~+ivy/tasks~.
+ =ui=
+ =ui/doom=
+ New plugin: [[https://github.com/hlissner/emacs-solaire-mode][solaire-mode]] -- replaces ~doom-buffer-mode~; brightens source windows and dims transient, temporary, or popup windows.
+ BREAKING CHANGE: Decoupled theme and font loading from ui/doom. This has been moved to core-ui. The following variables have been renamed:
+ ~+doom-theme~ => ~doom-theme~
+ ~+doom-font~ => ~doom-font~
+ ~+doom-variable-pitch-font~ => ~doom-variable-pitch-font~
+ ~+doom-unicode-font~ => ~doom-unicode-font~
+ =ui/doom-modeline=
+ Reduce excess whitespace on right of flycheck segment.
+ Buffer-path and file-name segments now use different faces.
+ The vcs segment now uses a slightly darker color (in clean branches).
+ Fix blank mode-line when buffer-file-name is nil ([[https://github.com/hlissner/.emacs.d/pull/130][#130]])
+ =ui/nav-flash=
+ Fix over-aggressive nav-flash'ing on evil-multiedit or in eshell/term buffers.
+ =tools=
@ -201,6 +261,8 @@
+ Don't enable ~flycheck-mode~ in emacs.d files.
+ =lang/org=
+ Replace org-bullets source with more up-to-date fork.
+ =lang/scala=
+ Fix ~void-variable imenu-auto-rescan~ error caused by ~ensime--setup-imenu~ trying to use imenu variables before loading imenu.
+ =private/hlissner=
+ Add =gzz= binding (~+evil/mc-make-cursor-here~)
+ Add =:mc= ex command (~+evil:mc~)

View file

@ -5,9 +5,9 @@ EMACSI=emacs -q $(EMACS_FLAGS)
MODULES=$(patsubst modules/%, %, $(shell find modules/ -maxdepth 2 -type d))
# Tasks
all: autoloads autoremove install
## Package management
install: init.el .local/autoloads.el
@$(EMACS) -f doom/packages-install
@ -20,28 +20,40 @@ autoremove: init.el .local/autoloads.el
autoloads: init.el
@$(EMACS) -f doom/reload-autoloads
recompile: init.el
@$(EMACS) -f doom/recompile
## Byte compilation
# compile
# compile:core
# compile:module
# compile:module/submodule
compile: init.el clean
@$(EMACS) -f doom/compile
core: init.el clean
compile\:core: init.el clean
@$(EMACS) -f doom/compile -- init.el core
$(MODULES): init.el .local/autoloads.el
@rm -fv $(shell find modules/$@ -type f -name '*.elc')
@$(EMACS) -f doom/compile -- modules/$@
$(patsubst %, compile\:%, $(MODULES)): init.el .local/autoloads.el
@rm -fv $(shell find $(patsubst compile:%, modules/%, $@) -type f -name '*.elc')
@$(EMACS) -f doom/compile -- $(patsubst compile:%, modules/%, $@)
recompile: init.el
@$(EMACS) -f doom/recompile
clean:
@$(EMACS) -f doom/clean-compiled
clean-cache:
@$(EMACS) -f doom/clean-cache
@$(EMACS) -f doom/clean-compiled-files
clean-pcache:
@$(EMACS) -l persistent-soft --eval '(delete-directory pcache-directory t)'
reset:
@$(EMACS) -f doom/reset
## Unit tests
# test
# test:core
# test:module
# test:module/submodule
test: init.el .local/autoloads.el
@$(EMACS) -f doom-run-tests
@ -52,16 +64,19 @@ test\:core $(patsubst %, test\:%, $(MODULES)): init.el .local/autoloads.el
testi: init.el .local/autoloads.el
@$(EMACSI) -f doom-run-tests -f ert
# For running Emacs from a different folder than ~/.emacs.d
## Utility tasks
# Runs Emacs from a different folder than ~/.emacs.d
run:
@$(EMACSI) $(EMACS_FLAGS) -l init.el
@$(EMACSI) -l init.el
# Diagnoses potential OS/environment issues
doctor:
@./bin/doctor
@./bin/doom-doctor
#
## Internal tasks
init.el:
@[ -e init.el ] || $(error No init.el file; create one or copy init.example.el)
@$(error No init.el file; create one or copy init.example.el)
.local/autoloads.el:
@$(EMACS) -f doom-initialize-autoloads
@ -69,5 +84,4 @@ init.el:
%.elc: %.el
@$(EMACS) -f doom/compile -- $<
.PHONY: all test $(MODULES)
.PHONY: all compile test testi

View file

@ -16,6 +16,7 @@
(require 'pp)
;;
(defvar doom-init-p nil)
(defvar doom-errors 0)
(defmacro check! (cond &rest body)
(declare (indent defun))
@ -95,8 +96,25 @@
(when (boundp 'system-configuration-features)
(msg! "Compiled with:\n%s" (indented 2 (autofill system-configuration-features))))
(msg! "uname -a:\n%s" (indented 2 (autofill (shell-command-to-string "uname -a"))))
(msg! "----\n")
(let (doom-core-packages doom-debug-mode)
(condition-case ex
(progn
(let ((inhibit-message t))
(load "~/.emacs.d/core/core.el" nil t))
(doom-initialize-packages)
(doom|finalize)
(success! "Attempt to load DOOM: success! Loaded v%s" doom-version)
(when (executable-find "git")
(msg! "Revision %s"
(or (ignore-errors
(let ((default-directory user-emacs-directory))
(shell-command-to-string "git rev-parse HEAD")))
"\n"))))
('error (warn! "Attempt to load DOOM: failed\n %s\n"
(or (cdr-safe ex) (car ex))))))
(msg! "----\n")
;; --- is emacs set up properly? ------------------------------
@ -111,6 +129,15 @@
;; --- is the environment set up properly? --------------------
(when (boundp 'doom-font)
(cond ((fboundp 'find-font)
(unless (find-font doom-font)
(warn! "Warning: couldn't find %s font" (font-get doom-font :family))
(explain! "If you use a different font, you may ignore this warning.")))
(t
(warn! "Couldn't detect font!")
(explain! "This could indicate the incorrect version of Emacs is being used!"))))
;; gnutls-cli & openssl
(cond ((executable-find "gnutls-cli"))
((executable-find "openssl")
@ -217,21 +244,6 @@
(when (getenv "DEBUG")
(msg! "\n====\nHave some debug information:\n")
(let (doom-core-packages doom-debug-mode)
(condition-case ex
(progn
(let ((inhibit-message t))
(load "~/.emacs.d/core/core.el" nil t))
(doom-initialize-packages)
(success! " + Attempt to load DOOM: success! Loaded v%s" doom-version)
(when (executable-find "git")
(msg! " Revision %s"
(or (ignore-errors
(let ((default-directory user-emacs-directory))
(shell-command-to-string "git rev-parse HEAD")))
"\n"))))
('error (warn! " + Attempt to load DOOM: failed\n %s\n" (or (cdr-safe ex) (car ex))))))
(when (bound-and-true-p doom-modules)
(msg! " + enabled modules:\n%s"
(indented 4

View file

@ -6,6 +6,9 @@
(defvar doom-real-buffer-functions '()
"A list of functions that are run to determine if a buffer is real.")
(defvar-local doom-real-buffer-p nil
"If non-nil, this buffer should be considered real no matter what.")
;;;###autoload
(defvar doom-fallback-buffer "*scratch*"
"The name of the buffer to fall back to if no other buffers exist (will create
@ -122,7 +125,7 @@ buffers. If there's nothing left, switch to `doom-fallback-buffer'. See
;; `switch-to-prev-buffer' properly update buffer list order.
(cl-loop with move-func =
(if (> n 0) #'switch-to-next-buffer #'switch-to-prev-buffer)
for _i to 20
for i to 20
while (not (memq (current-buffer) buffers))
do
(dotimes (_i (abs n))
@ -136,7 +139,8 @@ buffers. If there's nothing left, switch to `doom-fallback-buffer'. See
"Returns t if BUFFER-OR-NAME is a 'real' buffer. Real means it a) isn't a
popup window/buffer and b) isn't a special buffer."
(let ((buf (window-normalize-buffer buffer-or-name)))
(or (run-hook-with-args-until-success 'doom-real-buffer-functions buf)
(or (buffer-local-value 'doom-real-buffer-p buf)
(run-hook-with-args-until-success 'doom-real-buffer-functions buf)
(not (or (doom-popup-p buf)
(minibufferp buf)
(string-match-p "^\\s-*\\*" (buffer-name buf))
@ -241,7 +245,7 @@ regex PATTERN. Returns the number of killed buffers."
(defun doom/kill-this-buffer ()
"Use `doom-kill-buffer' on the current buffer."
(interactive)
(when (and (doom-kill-buffer) (called-interactively-p 'interactive))
(when (and (not (doom-kill-buffer)) (called-interactively-p 'interactive))
(message "Nowhere left to go!")))
;;;###autoload
@ -295,3 +299,8 @@ project."
(when (called-interactively-p 'interactive)
(message "Cleaned up %s buffers" n))))
;;;###autoload
(defun doom-set-buffer-real (buffer flag)
"Forcibly mark a buffer's real property, no matter what."
(with-current-buffer buffer
(setq doom-real-buffer-p flag)))

View file

@ -80,7 +80,7 @@ list of the package."
(plist-get (cdr (assq name doom-packages)) prop))
;;;###autoload
(defun doom-get-packages ()
(defun doom-get-packages (&optional installed-only-p)
"Retrieves a list of explicitly installed packages (i.e. non-dependencies).
Each element is a cons cell, whose car is the package symbol and whose cdr is
the quelpa recipe (if any).
@ -89,13 +89,17 @@ BACKEND can be 'quelpa or 'elpa, and will instruct this function to return only
the packages relevant to that backend.
Warning: this function is expensive; it re-evaluates all of doom's config files.
Be careful not to use it in a loop."
Be careful not to use it in a loop.
If INSTALLED-ONLY-P, only return packages that are installed."
(doom-initialize-packages t)
(cl-loop with packages = (append doom-core-packages (mapcar #'car doom-packages))
for sym in (cl-delete-duplicates packages)
if (or (assq sym doom-packages)
if (and (or (not installed-only-p)
(package-installed-p sym))
(or (assq sym doom-packages)
(and (assq sym package-alist)
(list sym)))
(list sym))))
collect it))
;;;###autoload
@ -121,7 +125,7 @@ If INCLUDE-FROZEN-P is non-nil, check frozen packages as well.
Used by `doom/packages-update'."
(let (quelpa-pkgs elpa-pkgs)
;; Separate quelpa from elpa packages
(dolist (pkg (doom-get-packages))
(dolist (pkg (doom-get-packages t))
(let ((sym (car pkg)))
(when (and (or (not (doom-package-prop sym :freeze))
include-frozen-p)

View file

@ -1,5 +1,7 @@
;;; core/autoload/popups.el -*- lexical-binding: t; -*-
(defvar doom-popup-remember-history)
;;;###autoload
(defun doom-popup-p (&optional target)
"Return TARGET (a window) if TARGET (a window or buffer) is a popup. Uses
@ -47,7 +49,7 @@ possible rules."
;;;###autoload
(defun doom-popup-windows ()
"Get a list of open pop up windows."
(cl-remove-if-not #'doom-popup-p (window-list)))
(cl-remove-if-not #'doom-popup-p doom-popup-windows))
;;;###autoload
(defun doom/popup-restore ()
@ -129,7 +131,7 @@ only close popups that have an :autoclose property in their rule (see
(delete-window)))
;;;###autoload
(defun doom/popup ()
(defun doom/popup-this-buffer ()
"Display currently selected buffer in a popup window."
(interactive)
(doom-popup-buffer (current-buffer) :align t :autokill t))
@ -146,14 +148,15 @@ only close popups that have an :autoclose property in their rule (see
(defun doom-popup-prop (prop &optional window)
"Returns a `doom-popup-rules' PROPerty from WINDOW."
(or (plist-get (or (if window
(buffer-local-value 'doom-popup-rules (window-buffer window))
(ignore-errors
(buffer-local-value 'doom-popup-rules
(window-buffer window)))
doom-popup-rules)
(window-parameter window 'popup))
prop)
(cond ((eq prop :size)
shackle-default-size)
((eq prop :align)
shackle-default-alignment))))
(pcase prop
(:size shackle-default-size)
(:align shackle-default-alignment))))
;;;###autoload
(defun doom-popup-side (&optional window)
@ -168,11 +171,9 @@ only close popups that have an :autoclose property in their rule (see
;;;###autoload
(defun doom-popup-size (&optional window)
"Return the size of a popup WINDOW."
(let ((side (doom-popup-side window)))
(cond ((memq side '(left right))
(window-width window))
((memq side '(above below))
(window-height window)))))
(pcase (doom-popup-side window)
((or 'left 'right) (window-width window))
((or 'above 'below) (window-height window))))
(defun doom--popup-data (window)
(when-let (buffer (window-buffer window))
@ -183,9 +184,26 @@ only close popups that have an :autoclose property in their rule (see
;;;###autoload
(defmacro with-popup-rules! (rules &rest body)
"TODO"
(declare (indent defun))
`(let ((old-shackle-rules shackle-rules))
,@(cl-loop for rule in rules
collect `(set! :popup ,@rule))
,@body
(setq shackle-rules old-shackle-rules)))
;;;###autoload
(defun doom/other-popup (count)
"Cycle through popup windows. Like `other-window', but for popups."
(interactive "p")
(if-let (popups (if (doom-popup-p)
(cdr (memq (selected-window) doom-popup-windows))
(setq doom-popup-other-window (selected-window))
doom-popup-windows))
(select-window (nth (mod (1- count) (length popups)) popups))
(unless (eq (selected-window) doom-popup-other-window)
(when doom-popup-other-window
(select-window doom-popup-other-window t)
(cl-decf count))
(when (/= count 0)
(other-window count)))))

View file

@ -21,14 +21,14 @@ command line args following a double dash (each arg should be in the
'module/submodule' format).
If neither is available, run all tests in all enabled modules."
(interactive) ;; TODO Add completing-read selection of tests
(interactive) ; must be interactive to be run from batch
;; FIXME Refactor this
(condition-case-unless-debug ex
(let (targets)
;; ensure DOOM is initialized
(unload-feature 'core t)
(let (noninteractive)
(load (expand-file-name "core/core.el" user-emacs-directory) nil t))
(load (expand-file-name "init.el" user-emacs-directory) nil t))
(remove-hook 'doom-init-hook #'doom--display-benchmark)
;; collect targets
(cond ((and command-line-args-left
(equal (car command-line-args-left) "--"))

View file

@ -13,7 +13,9 @@
(defun doom/toggle-line-numbers (&optional arg)
"Toggle `linum-mode'."
(interactive "P")
(cond ((featurep 'nlinum)
(cond ((boundp 'display-line-numbers)
(setq display-line-numbers (not display-line-numbers)))
((featurep 'nlinum)
(nlinum-mode (or arg (if nlinum-mode -1 +1))))
((featurep 'linum)
(linum-mode (or arg (if linum-mode -1 +1))))

View file

@ -89,6 +89,45 @@ fundamental-mode) for performance sake."
(fundamental-mode))))
(add-hook 'find-file-hook #'doom|check-large-file)
;; Automatic minor modes
(defvar doom-auto-minor-mode-alist '()
"Alist mapping filename patterns to corresponding minor mode functions, like
`auto-mode-alist'. All elements of this alist are checked, meaning you can
enable multiple minor modes for the same regexp.")
(defun doom|enable-minor-mode-maybe ()
"Check file name against `doom-auto-minor-mode-alist'."
(when buffer-file-name
(let ((name buffer-file-name)
(remote-id (file-remote-p buffer-file-name))
(alist doom-auto-minor-mode-alist))
;; Remove backup-suffixes from file name.
(setq name (file-name-sans-versions name))
;; Remove remote file name identification.
(when (and (stringp remote-id)
(string-match-p (regexp-quote remote-id) name))
(setq name (substring name (match-end 0))))
(while (and alist (caar alist) (cdar alist))
(if (string-match-p (caar alist) name)
(funcall (cdar alist) 1))
(setq alist (cdr alist))))))
(add-hook 'find-file-hook #'doom|enable-minor-mode-maybe)
;; ensure indirect buffers have buffer-file-name
(defun doom*set-indirect-buffer-filename (orig-fn base-buffer name &optional clone)
"In indirect buffers, `buffer-file-name' is nil, which can cause problems
with functions that require it (like modeline segments)."
(let ((file-name (buffer-file-name base-buffer))
(buffer (funcall orig-fn base-buffer name clone)))
(when (and file-name buffer)
(with-current-buffer buffer
(unless buffer-file-name
(setq buffer-file-name file-name
buffer-file-truename (file-truename file-name)))))
buffer))
(advice-add #'make-indirect-buffer :around #'doom*set-indirect-buffer-filename)
;;
;; Built-in plugins
@ -205,16 +244,13 @@ fundamental-mode) for performance sake."
(def-package! undo-tree
:demand t
:config
(global-undo-tree-mode +1)
;; persistent undo history is known to cause undo history corruption, which
;; can be very destructive! So disable it!
(setq undo-tree-auto-save-history nil
undo-tree-history-directory-alist
(list (cons "." (concat doom-cache-dir "undo-tree-hist/"))))
(defun doom*silence-undo-tree-load (orig-fn &rest args)
"Silence undo-tree load errors."
(quiet! (apply orig-fn args)))
(advice-add #'undo-tree-load-history-hook :around #'doom*silence-undo-tree-load))
(list (cons "." (concat doom-cache-dir "undo-tree-hist/")))))
;;

View file

@ -4,11 +4,18 @@
;; together `use-package', `quelpa' and package.el to create my own,
;; rolling-release, lazily-loaded package management system for Emacs.
;;
;; The three key commands are `doom/packages-install', `doom/packages-update'
;; and `doom/packages-autoremove', which can be called via 'make' on the command
;; line (make {install,update,autoremove}). These read packages.el files in each
;; activated module in `doom-modules-dir' (and one in `doom-core-dir') which
;; tell DOOM what plugins to install and where from.
;; The three key commands are:
;;
;; + `make install` or `doom/packages-install': Installs packages that are
;; wanted, but not installed.
;; + `make update` or `doom/packages-update': Updates packages that are
;; out-of-date.
;; + `make autoremove` or `doom/packages-autoremove': Uninstalls packages that
;; are no longer needed.
;;
;; This system reads packages.el files located in each activated module (and one
;; in `doom-core-dir'). These contain `package!` blocks that tell DOOM what
;; plugins to install and where from.
;;
;; Why all the trouble? Because:
;; 1. Scriptability: I live in the command line. I want a programmable
@ -178,7 +185,7 @@ to speed up startup."
(unless (file-exists-p doom-autoload-file)
(quiet! (doom/reload-autoloads))))
(defun doom-initialize-packages (&optional force-p load-p)
(defun doom-initialize-packages (&optional force-p)
"Crawls across your emacs.d to fill `doom-modules' (from init.el) and
`doom-packages' (from packages.el files), if they aren't set already.
@ -186,6 +193,7 @@ If FORCE-P is non-nil, do it even if they are.
This aggressively reloads core autoload files."
(doom-initialize force-p)
(unwind-protect
(let ((noninteractive t)
(load-fn
(lambda (file &optional noerror)
@ -195,24 +203,16 @@ This aggressively reloads core autoload files."
(error (format "(doom-initialize-packages) %s in %s: %s"
(car ex)
(file-relative-name file doom-emacs-dir)
(error-message-string ex))
:error))))))
(error-message-string ex))))))))
(when (or force-p (not doom-modules))
(setq doom-modules nil)
(funcall load-fn (expand-file-name "init.el" doom-emacs-dir))
(funcall load-fn (doom-module-path :private user-login-name "init.el") t)
(when load-p
(cl-loop for file
in (append (nreverse (file-expand-wildcards (expand-file-name "core*.el" doom-core-dir)))
(file-expand-wildcards (expand-file-name "autoload/*.el" doom-core-dir))
(doom--module-paths "config.el"))
do (funcall load-fn file t)))
(doom|finalize))
(funcall load-fn (expand-file-name "init.el" doom-emacs-dir)))
(when (or force-p (not doom-packages))
(setq doom-packages nil)
(funcall load-fn (expand-file-name "packages.el" doom-core-dir))
(dolist (file (doom--module-paths "packages.el"))
(funcall load-fn file t)))))
(funcall load-fn file t))))
(doom|finalize)))
(defun doom-initialize-modules (modules)
"Adds MODULES to `doom-modules'. MODULES must be in mplist format.
@ -305,6 +305,12 @@ MODULES is an malformed plist of modules to load."
(setq doom-modules ',doom-modules)
(unless noninteractive
(require 'core-ui) ; draw me like one of your French editors
(require 'core-popups) ; taming sudden yet inevitable windows
(require 'core-editor) ; baseline configuration for text editing
(require 'core-projects) ; making Emacs project-aware
(require 'core-keybinds) ; centralized keybind system + which-key
(load ,(doom-module-path :private user-login-name "init") t t)
,@(cl-loop for (module . submodule) in (doom--module-pairs)
collect `(require! ,module ,submodule t))
@ -563,7 +569,7 @@ If ONLY-RECOMPILE-P is non-nil, only recompile out-of-date files."
(interactive "P")
;; Ensure all relevant config files are loaded and up-to-date. This way we
;; don't need eval-when-compile and require blocks scattered all over.
(doom-initialize-packages t noninteractive)
(doom-initialize-packages t)
(let ((targets
(cond ((equal (car command-line-args-left) "--")
(cl-loop for file in (cdr command-line-args-left)
@ -614,18 +620,19 @@ If ONLY-RECOMPILE-P is non-nil, only recompile out-of-date files."
"Recompile any out-of-date compiled *.el files in your Emacs configuration."
(interactive)
(doom/compile nil :recompile)
;; In case `load-path' has changed (e.g. after an update)
;; Forcibly recompile core.el in case `load-path' has changed
(byte-recompile-file (expand-file-name "core.el" doom-core-dir) t))
(defun doom/clean-cache ()
(defun doom/reset ()
"Clear the local cache completely (in `doom-cache-dir').
You must restart Emacs for some components to feel its effects."
This resets Emacs to a blank slate. You must restart Emacs for some components
to feel its effects."
(interactive)
(delete-directory doom-cache-dir t)
(make-directory doom-cache-dir t))
(defun doom/clean-compiled ()
(defun doom/clean-compiled-files ()
"Delete all compiled elc files in your Emacs configuration.
This excludes compiled packages in `doom-packages-dir'."

View file

@ -28,6 +28,9 @@
(defvar doom-popup-no-fringes t
"If non-nil, disable fringes in popup windows.")
(defvar doom-popup-windows ()
"A list of open popup windows.")
(defvar-local doom-popup-rules nil
"The shackle rule that caused this buffer to be recognized as a popup.")
@ -94,7 +97,7 @@ recognized by DOOM's popup system. They are:
("^ \\*" :regexp t :size 12 :noselect t :autokill t :autoclose t)))
:config
(add-hook 'doom-init-hook #'shackle-mode)
(add-hook 'doom-post-init-hook #'shackle-mode)
(defun doom*shackle-always-align (plist)
"Ensure popups are always aligned and selected by default. Eliminates the need
@ -215,6 +218,7 @@ and setting `doom-popup-rules' within it. Returns the window."
(setcar args (clone-indirect-buffer (buffer-name (car args)) nil t)))
(unless (setq window (apply orig-fn args))
(error "No popup window was found for %s: %s" (car args) plist))
(cl-pushnew window doom-popup-windows :test #'eq)
(with-selected-window window
(unless (eq plist t)
(setq-local doom-popup-rules plist))
@ -241,6 +245,7 @@ prevent the popup(s) from messing up the UI (or vice versa)."
properties."
(let ((window (or window (selected-window))))
(when (doom-popup-p window)
(setq doom-popup-windows (delq window doom-popup-windows))
(when doom-popup-remember-history
(setq doom-popup-history (list (doom--popup-data window))))
(let ((autokill-p (plist-get doom-popup-rules :autokill)))
@ -407,12 +412,7 @@ the command buffer."
(advice-add #'helm-ag--edit :around #'doom*helm-ag-edit)))
(after! help-mode
;; Help buffers use `other-window' to decide where to open followed links,
;; which can be unpredictable. It should *only* replace the original buffer we
;; opened the popup from. To fix this these three button types need to be
;; redefined to set aside the popup before following a link.
(defsubst doom--switch-from-popup (location)
(defsubst doom--switch-from-popup (location)
(doom/popup-close)
(switch-to-buffer (car location) nil t)
(if (not (cdr location))
@ -420,6 +420,11 @@ the command buffer."
(goto-char (cdr location))
(recenter)))
(after! help-mode
;; Help buffers use `other-window' to decide where to open followed links,
;; which can be unpredictable. It should *only* replace the original buffer we
;; opened the popup from. To fix this these three button types need to be
;; redefined to set aside the popup before following a link.
(define-button-type 'help-function-def
:supertype 'help-xref
'help-function
@ -553,6 +558,18 @@ you came from."
(advice-add #'xref-goto-xref :around #'doom*xref-follow-and-close))
;;
;; Major modes
;;
(after! plantuml-mode
(defun doom*plantuml-preview-in-popup-window (orig-fn &rest args)
(save-window-excursion
(apply orig-fn args))
(pop-to-buffer plantuml-preview-buffer))
(advice-add #'plantuml-preview-string
:around #'doom*plantuml-preview-in-popup-window))
;; Ensure these settings are attached to org-load-hook as late as possible,
;; giving other modules a chance to add their own hooks.
(defun doom|init-org-popups ()

View file

@ -108,7 +108,6 @@ like a space that `whitespace-mode' won't affect.")
(defun doom-quit-p (&optional prompt)
"Return t if this session should be killed. Prompts the user for
confirmation."
(interactive)
(if (ignore-errors (doom-real-buffer-list))
(or (yes-or-no-p (format " %s" (or prompt "Quit Emacs?")))
(ignore (message "Aborted")))
@ -257,6 +256,13 @@ local value, whether or not it's permanent-local. Therefore, we cycle
(add-hook! '(doom-post-init-hook minibuffer-setup-hook)
#'doom|no-fringes-in-minibuffer)
;; line numbers in newer version of Emacs
(when (boundp 'display-line-numbers)
(defun doom|init-line-numbers ()
(unless (eq major-mode 'org-mode)
(setq display-line-numbers t)))
(add-hook! (prog-mode text-mode) #'doom|init-line-numbers))
;;
;; Plugins
@ -319,8 +325,10 @@ local value, whether or not it's permanent-local. Therefore, we cycle
(add-hook 'evil-visual-state-exit-hook #'hl-line-mode)))
;; Line number column. A faster (or equivalent, in the worst case) line number
;; plugin than the built-in `linum'.
;; plugin than the built-in `linum'. This will be ignored if you're using Emacs
;; 26.1+, which has native line number support.
(def-package! nlinum
:unless (boundp 'display-line-numbers)
:commands nlinum-mode
:init
(defun doom|init-nlinum-mode ()
@ -358,6 +366,7 @@ local value, whether or not it's permanent-local. Therefore, we cycle
;; Fixes disappearing line numbers in nlinum and other quirks
(def-package! nlinum-hl
:unless (boundp 'display-line-numbers)
:after nlinum
:config
;; With `markdown-fontify-code-blocks-natively' enabled in `markdown-mode',

View file

@ -53,10 +53,10 @@ config files that are stable (i.e. it should be unlikely that you need to delete
them if something goes wrong).")
(defvar doom-cache-dir (concat doom-host-dir "/cache/")
"Host-namespaced directory for volatile storage. Deleted when
`doom/clean-cache' is called. Use this for transient files that are generated on
the fly like caches and temporary files. Anything that may need to be cleared if
there are problems.")
"Host-namespaced directory for volatile storage. Deleted when `doom/reset' is
called. Use this for transient files that are generated on the fly like caches
and temporary files. Anything that may need to be cleared if there are
problems.")
(defvar doom-packages-dir (concat doom-local-dir "packages/")
"Where package.el and quelpa plugins (and their caches) are stored.")
@ -146,30 +146,18 @@ ability to invoke the debugger in debug mode."
(car ex) fn (error-message-string ex))))
nil)
;; Automatic minor modes
(defvar doom-auto-minor-mode-alist '()
"Alist mapping filename patterns to corresponding minor mode functions, like
`auto-mode-alist'. All elements of this alist are checked, meaning you can
enable multiple minor modes for the same regexp.")
(defun doom|finalize ()
(unless doom-init-p
(dolist (hook '(doom-init-hook doom-post-init-hook))
(run-hook-wrapped hook #'doom-try-run-hook hook))
(setq doom-init-p t))
(defun doom|enable-minor-mode-maybe ()
"Check file name against `doom-auto-minor-mode-alist'."
(when buffer-file-name
(let ((name buffer-file-name)
(remote-id (file-remote-p buffer-file-name))
(alist doom-auto-minor-mode-alist))
;; Remove backup-suffixes from file name.
(setq name (file-name-sans-versions name))
;; Remove remote file name identification.
(when (and (stringp remote-id)
(string-match-p (regexp-quote remote-id) name))
(setq name (substring name (match-end 0))))
(while (and alist (caar alist) (cdar alist))
(if (string-match-p (caar alist) name)
(funcall (cdar alist) 1))
(setq alist (cdr alist))))))
(add-hook 'find-file-hook #'doom|enable-minor-mode-maybe)
;; Don't keep gc-cons-threshold too high. It helps to stave off the GC while
;; Emacs starts up, but afterwards it causes stuttering and random freezes. So
;; reset it to a reasonable default.
(setq gc-cons-threshold 16777216
gc-cons-percentage 0.1
file-name-handler-alist doom--file-name-handler-alist))
;;;
@ -190,26 +178,6 @@ enable multiple minor modes for the same regexp.")
(setq load-path (eval-when-compile load-path)
doom--package-load-path (eval-when-compile doom--package-load-path))
(defun doom|finalize ()
;; Don't keep gc-cons-threshold too high. It helps to stave off the GC while
;; Emacs starts up, but afterwards it causes stuttering and random freezes. So
;; reset it to a reasonable default.
(setq gc-cons-threshold 16777216
gc-cons-percentage 0.1)
(unless doom-init-p
(dolist (hook '(doom-init-hook doom-post-init-hook))
(run-hook-wrapped hook #'doom-try-run-hook hook))
(setq file-name-handler-alist doom--file-name-handler-alist
doom-init-p t)))
(add-hook! '(emacs-startup-hook doom-reload-hook)
#'doom|finalize)
;;;
;; Bootstrap
(load! core-os) ; consistent behavior across OSes
(condition-case-unless-debug ex
(require 'autoloads doom-autoload-file t)
@ -218,12 +186,8 @@ enable multiple minor modes for the same regexp.")
"%s in autoloads.el -> %s"
(car ex) (error-message-string ex))))
(unless noninteractive
(load! core-ui) ; draw me like one of your French editors
(load! core-popups) ; taming sudden yet inevitable windows
(load! core-editor) ; baseline configuration for text editing
(load! core-projects) ; making Emacs project-aware
(load! core-keybinds)) ; centralized keybind system + which-key
(add-hook! '(emacs-startup-hook doom-reload-hook)
#'doom|finalize)
(provide 'core)
;;; core.el ends here

View file

@ -17,8 +17,9 @@
(package! fringe-helper)
(package! highlight-indentation)
(package! highlight-numbers)
(package! nlinum)
(package! nlinum-hl)
(unless (boundp 'display-line-numbers)
(package! nlinum)
(package! nlinum-hl))
(package! rainbow-delimiters)
(package! vi-tilde-fringe)
(package! visual-fill-column)

View file

@ -18,6 +18,14 @@ affects your Emacs packages)."
(package-initialize)
,@forms))
(defmacro -with-packages! (packages package-descs &rest body)
`(let ((doom-packages ,packages)
(package-alist ,package-descs)
doom-core-packages)
(cl-letf (((symbol-function 'doom-initialize-packages) (lambda (&rest _)))
((symbol-function 'package-installed-p) (lambda (name &rest _) (assq name package-alist))))
,@body)))
;;
;; Tests
@ -31,45 +39,40 @@ affects your Emacs packages)."
(should (eq (doom-package-backend 'doom-quelpa-dummy) 'quelpa))))
(def-test! elpa-outdated-detection
(cl-letf (((symbol-function 'package-refresh-contents) (lambda (&rest _))))
(let* ((doom--last-refresh (current-time))
(package-alist
`((doom-dummy ,(-new-package 'doom-dummy '(20160405 1234)))))
(package-archive-contents
`((doom-dummy ,(-new-package 'doom-dummy '(20170405 1234)))))
(outdated (doom-package-outdated-p 'doom-dummy)))
(should outdated)
(should (equal outdated '(doom-dummy (20160405 1234) (20170405 1234)))))))
`((doom-dummy ,(-new-package 'doom-dummy '(20170405 1234))))))
(cl-letf (((symbol-function 'package-refresh-contents) (lambda (&rest _))))
(should (equal (doom-package-outdated-p 'doom-dummy)
'(doom-dummy (20160405 1234) (20170405 1234)))))))
;; TODO quelpa-outdated-detection
(def-test! get-packages
(let ((quelpa-initialized-p t)
(doom-packages '((doom-dummy)))
(package-alist
`((doom-dummy nil)
(doom-dummy-dep nil)))
doom-core-packages)
(cl-letf (((symbol-function 'doom-initialize-packages) (lambda (&rest _))))
(let ((quelpa-initialized-p t))
(-with-packages!
'((doom-dummy))
'((doom-dummy nil)
(doom-dummy-unwanted nil)
(doom-dummy-dep nil))
(should (equal (doom-get-packages) '((doom-dummy)))))))
(def-test! orphaned-packages
"Test `doom-get-orphaned-packages', which gets a list of packages that are
no longer enabled or depended on."
(let ((doom-packages '((doom-dummy)))
(package-alist
(-with-packages!
'((doom-dummy))
`((doom-dummy ,(-new-package 'doom-dummy '(20160405 1234) '((doom-dummy-dep (1 0)))))
(doom-dummy-unwanted ,(-new-package 'doom-dummy-unwanted '(20160601 1234)))
(doom-dummy-dep ,(-new-package 'doom-dummy-dep '(20160301 1234)))))
doom-core-packages)
(cl-letf (((symbol-function 'doom-initialize-packages) (lambda (&rest _))))
(should (equal (doom-get-orphaned-packages) '(doom-dummy-unwanted))))))
(doom-dummy-dep ,(-new-package 'doom-dummy-dep '(20160301 1234))))
(should (equal (doom-get-orphaned-packages) '(doom-dummy-unwanted)))))
(def-test! missing-packages
"Test `doom-get-missing-packages, which gets a list of enabled packages that
aren't installed."
(let ((doom-packages '((doom-dummy) (doom-dummy-installed)))
(package-alist `((doom-dummy-installed ,(-new-package 'doom-dummy-installed '(20160405 1234)))))
doom-core-packages)
(cl-letf (((symbol-function 'doom-initialize-packages) (lambda (&rest _))))
(should (equal (doom-get-missing-packages) '((doom-dummy)))))))
(-with-packages!
'((doom-dummy) (doom-dummy-installed))
`((doom-dummy-installed ,(-new-package 'doom-dummy-installed '(20160405 1234))))
(should (equal (doom-get-missing-packages) '((doom-dummy))))))

View file

@ -42,7 +42,7 @@
;debug ; FIXME stepping through code, to help you add bugs
:completion
company ; code completion backend
company ; the ultimate code completion backend
ivy ; a search engine for love and life
;helm ; the *other* search engine for love and life
;ido ; the other *other* search engine...
@ -91,7 +91,9 @@
lua ; one-based indices? one-based indices
markdown ; writing docs for people to ignore
ocaml ; an objective camel
perl ; write code no one else can comprehend
php ; make php less awful to work with
plantuml ; diagrams for confusing people more
purescript ; javascript, but functional
python ; beautiful is better than ugly
rest ; Emacs as a REST client
@ -115,9 +117,10 @@
;org-publish ; TODO org + blogs
;; Applications are complex and opinionated modules that transform Emacs
;; toward a specific purpose. They should be loaded last.
;; toward a specific purpose. They may have additional dependencies and
;; should be loaded last.
:app
email ; Emacs as an email client
email ; emacs as an email client
irc ; how neckbeards socialize
rss ; emacs as an RSS reader
twitter ; twitter client https://twitter.com/vnought

View file

@ -2,8 +2,18 @@
(require 'core (concat user-emacs-directory "core/core"))
(doom! :feature evil
:completion company
:tools password-store
:lang web
:private hlissner)
(doom! :feature
evil
workspaces
:completion
company
:tools
password-store
:lang
web
:private
hlissner)

View file

@ -163,6 +163,6 @@ These are /not/ loaded automatically. Use ~load!~ to do so.
+ ~doom/reload-autoloads~
+ ~doom/compile~
+ ~doom/recompile~
+ ~doom/clean-cache~
+ ~doom/reset~
+ ~doom/clean-compiled~

View file

@ -140,7 +140,7 @@ default/fallback account."
mu4e-marks)
;; This hook correctly modifies gmail flags on emails when they are marked.
;; Without it refiling (archiving), trashing, and flagging (starring) email
;; Without it, refiling (archiving), trashing, and flagging (starring) email
;; won't properly result in the corresponding gmail action, since the marks
;; are ineffectual otherwise.
(defun +email|gmail-fix-flags (mark msg)

View file

@ -20,10 +20,10 @@
(defvar +ivy--file-search-all-files-p nil)
(defun +ivy--file-search (engine beg end query &optional directory)
(let* ((directory (or directory (doom-project-root)))
(let* ((project-root (doom-project-root))
(directory (or directory project-root))
(recursion-p +ivy--file-search-recursion-p)
(all-files-p +ivy--file-search-all-files-p)
(project-root (doom-project-root))
(query
(or query
(and beg end
@ -40,13 +40,13 @@
(t
(file-relative-name directory project-root))))))
(setq +ivy--file-last-search query)
(cond ((eq engine 'ag)
(pcase engine
('ag
(let ((args (concat
(if all-files-p " -a")
(unless recursion-p " -n"))))
(counsel-ag query directory args (format prompt args))))
((eq engine 'rg)
('rg
;; smart-case instead of case-insensitive flag
(let ((counsel-rg-base-command
(replace-regexp-in-string " -i " " -S " counsel-rg-base-command))
@ -54,10 +54,8 @@
(if all-files-p " -uu")
(unless recursion-p " --maxdepth 0"))))
(counsel-rg query directory args (format prompt args))))
((eq engine 'pt)) ; TODO pt search engine (necessary?)
(t (error "No search engine specified")))))
('pt) ;; TODO pt search engine (necessary?)
(_ (error "No search engine specified")))))
;;;###autoload (autoload '+ivy:ag "completion/ivy/autoload/evil" nil t)
(evil-define-operator +ivy:ag (beg end query &optional all-files-p directory)

View file

@ -3,9 +3,8 @@
;; Show more information in ivy-switch-buffer; and only display
;; workgroup-relevant buffers.
(defun +ivy--get-buffers (&optional buffer-list)
(when-let (buffer-list (or buffer-list (doom-buffer-list)))
(let* ((buffer-list (or buffer-list (doom-buffer-list)))
(min-name
(when-let (buffer-list (delq (current-buffer) (or buffer-list (doom-buffer-list))))
(let* ((min-name
(+ 5 (cl-loop for buf in buffer-list
maximize (length (buffer-name buf)))))
(min-mode
@ -38,35 +37,39 @@
(defun +ivy--select-buffer-action (buffer)
(ivy--switch-buffer-action
(s-chop-suffix
(string-remove-suffix
"[+]"
(substring buffer 0 (string-match-p (regexp-quote " ") buffer)))))
(defun +ivy--select-buffer-other-window-action (buffer)
(ivy--switch-buffer-other-window-action
(s-chop-suffix
(string-remove-suffix
"[+]"
(substring buffer 0 (string-match-p (regexp-quote " ") buffer)))))
;;;###autoload
(defun +ivy/switch-workspace-buffer (&optional other-window-p)
"Switch to an open buffer in the current workspace."
"Switch to an open buffer in the current workspace.
If OTHER-WINDOW-P (universal arg), then open target in other window."
(interactive "P")
(+ivy/switch-buffer other-window-p t))
;;;###autoload
(defun +ivy/switch-buffer (&optional other-window-p workspace-only-p)
"Switch to an open buffer in the global buffer list. If WORKSPACE-ONLY-P,
limit to buffers in the current workspace."
"Switch to an open buffer in the global buffer list.
If OTHER-WINDOW-P (universal arg), then open target in other window.
If WORKSPACE-ONLY-P (universal arg), limit to buffers in the current workspace."
(interactive "P")
(ivy-read (format "%s buffers: " (if workspace-only-p "Workspace" "Global"))
(+ivy--get-buffers (unless workspace-only-p (buffer-list)))
:action (if other-window-p
'+ivy--select-buffer-other-window-action
'+ivy--select-buffer-action)
:matcher 'ivy--switch-buffer-matcher
#'+ivy--select-buffer-other-window-action
#'+ivy--select-buffer-action)
:matcher #'ivy--switch-buffer-matcher
:keymap ivy-switch-buffer-map
:caller '+ivy/switch-workspace-buffer))
:caller #'+ivy/switch-workspace-buffer))
(defun +ivy--tasks-candidates (tasks)
"Generate a list of task tags (specified by `+ivy-task-tags') for

View file

@ -13,8 +13,8 @@
;;;###autoload (autoload '+evil/mc-make-cursor-here "feature/evil/autoload/evil-mc" nil t)
(evil-define-command +evil/mc-make-cursor-here ()
"Create a cursor at point. If in visual block or line mode, then create
cursors in column beneath+above the point on each line. Otherwise pauses
cursors."
cursors on each line of the selection, on the column of the cursor. Otherwise
pauses cursors."
:repeat nil
:keep-visual nil
:evil-mc t

View file

@ -29,25 +29,28 @@
(defun +workspace-buffer-list (&optional persp)
"Return a list of buffers in PERSP (defaults to the current perspective).
The buffer list is ordered by recency (same as `buffer-list').
PERSP can be a string (name of a workspace) or a perspective hash (satisfies
`+workspace-p').
If PERSP is t, then return a list of orphaned buffers associated with no
perspectives."
(cond ((not persp)
(persp-buffer-list-restricted))
((eq persp t)
(cl-remove-if #'persp--buffer-in-persps (doom-buffer-list)))
((+workspace-p persp)
(safe-persp-buffers persp))
((stringp persp)
(safe-persp-buffers (+workspace-get persp t)))))
(unless persp
(setq persp (get-current-persp)))
(if (eq persp t)
(cl-remove-if #'persp--buffer-in-persps (buffer-list))
(when (stringp persp)
(setq persp (+workspace-get persp t)))
(cl-loop for buf in (buffer-list)
if (persp-contain-buffer-p buf persp)
collect buf)))
;;;###autoload
(defun +workspace-p (obj)
"Return t if OBJ is a perspective hash table."
(and obj
(hash-table-p obj)
(cl-struct-p obj)
(perspective-p obj)))
;;;###autoload
@ -70,11 +73,21 @@ perspectives."
(error "%s is not an available workspace" name))
persp)))
;;;###autoload
(defalias '+workspace-current #'get-current-persp)
;;;###autoload
(defun +workspace-current-name ()
"Get the name of the currently active workspace."
(safe-persp-name (get-current-persp)))
;;;###autoload
(defun +workspace-contains-buffer-p (&optional buffer workspace)
"Return non-nil if buffer is in workspace (defaults to current workspace)."
(unless workspace
(setq workspace (+workspace-current)))
(persp-contain-buffer-p buffer workspace nil))
;;;###autoload
(defun +workspace-load (name)
"Loads and inserts a single workspace (named NAME) into the current session.

View file

@ -55,16 +55,20 @@ renamed.")
;; only auto-save when real buffers are present
(advice-add #'persp-asave-on-exit :around #'+workspaces*autosave-real-buffers)
(defun +workspaces|on-persp-mode ()
;; Remap `buffer-list' to current workspace's buffers in `doom-buffer-list'
(if persp-mode
(advice-add #'doom-buffer-list :override #'+workspace-buffer-list)
(advice-remove #'doom-buffer-list #'+workspace-buffer-list)))
(add-hook 'persp-mode-hook #'+workspaces|on-persp-mode)
;; Defer delayed warnings even further, so they appear after persp-mode is
;; started and the main workspace is ready to display them. Otherwise, warning
;; buffers will be hidden on startup.
(remove-hook 'delayed-warnings-hook #'display-delayed-warnings)
(defun +workspaces|init (&optional frame)
(unless persp-mode
(persp-mode +1)
;; Remap `buffer-list' to current workspace's buffers in
;; `doom-buffer-list'
(advice-add #'doom-buffer-list :override #'+workspace-buffer-list))
(persp-mode +1))
(let ((frame (or frame (selected-frame))))
(unless noninteractive
;; The default perspective persp-mode makes (defined by

View file

@ -0,0 +1,89 @@
;;; feature/workspaces/test/autoload-workspaces.el -*- lexical-binding: t; -*-
(require! :feature workspaces)
(defmacro -with-workspace! (buffer-args &rest body)
(declare (indent defun))
(let ((buffers
(cl-loop for bsym in buffer-args
collect `(,bsym (get-buffer-create ,(symbol-name bsym))))))
`(let (noninteractive)
(+workspaces|init)
(save-window-excursion
(let* (,@buffers)
(cl-loop with persp = (get-current-persp)
for buf in (list ,@(mapcar #'car buffers))
do (persp-add-buffer buf persp)
do (with-current-buffer buf
(setq buffer-file-name (make-temp-file "workspaces-test-"))))
,@body
(dolist (buf (list ,@(mapcar #'car buffers)))
(persp-remove-buffer buf)
(kill-buffer buf))))
(persp-mode -1)
(setq *persp-hash* nil
persp-buffer-props-hash nil))))
;;
(def-test! init
(-with-workspace! ()
(should (equal (+workspace-current-name) +workspaces-main))))
(def-test! advice
(should (advice-member-p #'+workspaces*auto-add-buffer #'switch-to-buffer)))
(def-test! current
(-with-workspace! ()
(should (equal (+workspace-current-name) +workspaces-main))
(should (+workspace-exists-p +workspaces-main))
(let ((workspace (+workspace-get +workspaces-main))
(current-workspace (+workspace-current)))
(should workspace)
(should (+workspace-p workspace))
(should (+workspace-p current-workspace))
(should (equal workspace current-workspace)))))
(def-test! workspace-list
(-with-workspace! ()
(should (equal (+workspace-list-names)
(list (+workspace-current-name))))
(should (equal (+workspace-list)
(list (+workspace-current))))))
(def-test! workspace-crud
"Creating, reading, updating and deleting workspaces."
(-with-workspace! ()
(let ((new-workspace-name "*new-test*")
(renamed-workspace-name "*old-test*"))
(should (+workspace-new new-workspace-name))
(should (seq-contains (+workspace-list-names) new-workspace-name))
(should (equal new-workspace-name
(+workspace-rename new-workspace-name renamed-workspace-name)))
(should-not (seq-contains (+workspace-list-names) new-workspace-name))
(should (seq-contains (+workspace-list-names) renamed-workspace-name))
(should (= (length (+workspace-list-names)) 2))
(+workspace-delete renamed-workspace-name)
(should (= (length (+workspace-list-names)) 1)))))
(def-test! workspace-switch
(-with-workspace! ()
(let ((new-workspace-name "*new-test*"))
(should-error (+workspace-switch new-workspace-name))
(should (+workspace-switch new-workspace-name t))
(should (equal (+workspace-current-name) new-workspace-name)))))
(def-test! buffer-list
(-with-workspace! (a b)
(let ((c (get-buffer-create "c"))
(d (get-buffer-create "d")))
(should (+workspace-contains-buffer-p a))
(should (+workspace-contains-buffer-p b))
(should-not (+workspace-contains-buffer-p c))
;; New (and real) buffers should be added to workspace buffer list.
(doom-set-buffer-real c t)
(switch-to-buffer "c")
(should (+workspace-contains-buffer-p c))
;; unreal buffers shouldn't
(switch-to-buffer "d")
(should-not (+workspace-contains-buffer-p d)))))

View file

@ -145,18 +145,6 @@
(def-package! disaster :commands disaster)
;;
;; Plugins
;;
(when (featurep! :completion company)
(def-package! company-cmake :after cmake-mode)
(def-package! company-irony :after irony)
(def-package! company-irony-c-headers :after company-irony))
;;
;; Major modes
;;
@ -166,8 +154,6 @@
:config
(set! :company-backend 'cmake-mode '(company-cmake company-yasnippet)))
(def-package! glsl-mode :mode ("\\.glsl$" "\\.vert$" "\\.frag$" "\\.geom$"))
(def-package! cuda-mode :mode "\\.cuh?$")
(def-package! opencl-mode :mode "\\.cl$")
@ -175,3 +161,29 @@
(def-package! demangle-mode
:commands demangle-mode
:init (add-hook 'llvm-mode-hook #'demangle-mode))
(def-package! glsl-mode
:mode "\\.glsl$"
:mode "\\.vert$"
:mode "\\.frag$"
:mode "\\.geom$")
;;
;; Plugins
;;
(when (featurep! :completion company)
(def-package! company-cmake :after cmake-mode)
(def-package! company-irony :after irony)
(def-package! company-irony-c-headers :after company-irony)
(def-package! company-glsl
:when (featurep! :completion company)
:after glsl-mode
:config
(if (executable-find "glslangValidator")
(warn "glsl-mode: couldn't find glslangValidator, disabling company-glsl")
(set! :company-backend 'glsl-mode '(company-glsl)))))

View file

@ -15,6 +15,7 @@
(package! flycheck-irony))
(when (featurep! :completion company)
(package! company-glsl :recipe (:fetcher github :repo "Kaali/company-glsl"))
(package! company-irony)
(package! company-irony-c-headers))

View file

@ -0,0 +1,15 @@
;;; lang/perl/config.el -*- lexical-binding: t; -*-
;; There's also `perl-mode' for perl < 6, which is already set up.
(when (featurep! :feature syntax-checker)
(add-hook 'perl-mode-hook #'flycheck-mode))
(def-package! perl6-mode
:init (require 'perl6-detect))
(def-package! flycheck-perl6
:after perl6-mode
:when (featurep! :feature syntax-checker)
:config (add-hook 'perl6-mode-hook #'flycheck-mode))

View file

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

View file

@ -0,0 +1,10 @@
;;; lang/plantuml/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +plantuml/install ()
"Install plantuml.jar."
(interactive)
(unless (file-exists-p plantuml-jar-path)
(user-error "plantuml.jar already installed"))
(url-copy-file "https://kent.dl.sourceforge.net/project/plantuml/plantuml.jar"
plantuml-jar-path))

View file

@ -0,0 +1,18 @@
;;; lang/plantuml/config.el -*- lexical-binding: t; -*-
(def-package! plantuml-mode
:mode "\\.p\\(lant\\)?uml$"
:config
(setq plantuml-jar-path (concat doom-etc-dir "plantuml.jar"))
(set! :popup "*PLANTUML Preview*" :size 25 :noselect t :autokill t)
(unless (executable-find "java")
(warn "plantuml-mode: can't find java, preview disabled."))
(unless (file-exists-p plantuml-jar-path)
(warn "plantuml-mode: can't find plantuml.jar; run M-x +plantuml/install.")))
(def-package! flycheck-plantuml
:when (featurep! :feature syntax-checker)
:after plantuml-mode
:config (flycheck-plantuml-setup))

View file

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

View file

@ -50,6 +50,6 @@
:when (featurep! :completion company)
:after sh-script
:config
(set! :company-backend 'sh-mode '(company-shell))
(set! :company-backend 'sh-mode '(company-shell company-files))
(setq company-shell-delete-duplicates t))

View file

@ -190,6 +190,11 @@ between the two."
:i "C-H" #'+org/table-previous-field
:i "C-K" #'+org/table-previous-row
:i "C-J" #'+org/table-next-row
;; Expand tables (or shiftmeta move)
:ni "C-S-l" #'+org/table-append-field-or-shift-right
:ni "C-S-h" #'+org/table-prepend-field-or-shift-left
:ni "C-S-k" #'+org/table-prepend-row-or-shift-up
:ni "C-S-j" #'+org/table-append-row-or-shift-down
:n [tab] #'+org/toggle-fold
:i [tab] #'+org/indent-or-next-field-or-yas-expand

View file

@ -66,6 +66,9 @@
:m "A-j" #'+hlissner:multi-next-line
:m "A-k" #'+hlissner:multi-previous-line
(:prefix "C-x"
"p" #'doom/other-popup)
;; --- <leader> -------------------------------------
(:leader
@ -628,6 +631,7 @@
;; For elisp debugging
:map debugger-mode-map
:n "RET" #'debug-help-follow
:n "e" #'debugger-eval-expression
:n "n" #'debugger-step-through
:n "c" #'debugger-continue)
@ -695,7 +699,7 @@
(evilem-default-keybindings prefix)
(evilem-define (kbd (concat prefix " n")) #'evil-ex-search-next)
(evilem-define (kbd (concat prefix " N")) #'evil-ex-search-previous)
(evilem-define (kbd (concat prefix " s")) 'evil-snipe-repeat
(evilem-define (kbd (concat prefix " s")) #'evil-snipe-repeat
:pre-hook (save-excursion (call-interactively #'evil-snipe-s))
:bind ((evil-snipe-scope 'buffer)
(evil-snipe-enable-highlight)
@ -748,7 +752,9 @@
(:after org-mode
(:map org-mode-map
:i [remap doom/inflate-space-maybe] #'org-self-insert-command))
:i [remap doom/inflate-space-maybe] #'org-self-insert-command
:i "C-e" #'org-end-of-line
:i "C-a" #'org-beginning-of-line))
;; Make ESC quit all the things
(:map (minibuffer-local-map

View file

@ -57,7 +57,7 @@
(ex! "k[ill]o" #'doom/kill-other-buffers)
(ex! "l[ast]" #'doom/popup-restore)
(ex! "m[sg]" #'view-echo-area-messages)
(ex! "pop[up]" #'doom/popup) ; open current buffer in popup
(ex! "pop[up]" #'doom/popup-this-buffer)
;; Project navigation
(ex! "a" #'projectile-find-other-file)