Rewrite core libraries (WIP)

This commit is contained in:
Henrik Lissner 2017-01-16 23:15:48 -05:00
parent 83c852e11f
commit 50ea98319f
68 changed files with 1892 additions and 5345 deletions

View file

@ -1,87 +0,0 @@
;;; core-autoinsert.el
(use-package autoinsert
:after yasnippet
:config
(setq auto-insert-query nil ; Don't prompt before insertion
auto-insert-alist '()) ; Tabula rasa
(auto-insert-mode 1)
(mapc (lambda (rule)
(define-auto-insert
(nth 0 rule)
(vector `(lambda () (doom/auto-insert-snippet ,(nth 1 rule) ',(nth 2 rule) ,(nth 3 rule))))))
`(;; General
("/\\.gitignore$" "__" gitignore-mode)
("/Dockerfile$" "__" dockerfile-mode)
("/docker-compose.yml$" "__" yaml-mode)
;; Org-mode
("\\.org$" "__" org-mode)
("/Work/.+\\.org$" "__project.org" org-mode)
("/Invoices/.+\\.org$" "__invoice.org" org-mode)
("/Contacts/.+\\.org$" "__contact.org" org-mode)
;; C/C++
("/Makefile$" "__" makefile-gmake-mode)
("/main\\.\\(cc\\|cpp\\)$" "__main.cpp" c++-mode)
("/win32_\\.\\(cc\\|cpp\\)$" "__winmain.cpp" c++-mode)
("\\.h\\(h\\|pp|xx\\)$" "__hpp" c++-mode)
("\\.\\(cc\\|cpp\\)$" "__cpp" c++-mode)
("\\.h$" "__h" c-mode)
("\\.c$" "__c" c-mode)
;; Elisp
("-test\\.el$" "__" emacs-ert-mode)
("/.+\\.el$" "__initfile" emacs-lisp-mode)
("\\(\\.emacs\\.d\\|doom-emacs\\)/private/\\(snippets\\|templates\\)/.+$"
"__" snippet-mode)
;; Go
("/main\\.go$" "__main.go" go-mode t)
("\\.go$" "__.go" go-mode)
;; HTML
("\\.html$" "__.html" web-mode)
;; java
("/src/.+/.+\\.java$" "__" java-mode)
("/main\\.java$" "__main" java-mode)
("/build\\.gradle$" "__build.gradle" android-mode)
;; Javascript
("\\.lbaction/.+/Info.plist$" "__Info.plst" lb6-mode)
("\\.lbaction/.+/\\(default\\|suggestions\\)\\.js$" "__default.js" lb6-mode)
("/package\\.json$" "__package.json" json-mode)
("/bower\\.json$" "__bower.json" json-mode)
("\\.\\(json\\|jshintrc\\)$" "__" json-mode)
("/gulpfile\\.js$" "__gulpfile.js" js-mode)
;; Lua
("/main\\.lua$" "__main.lua" love-mode)
("/conf\\.lua$" "__conf.lua" love-mode)
;; Markdown
("\\.md$" "__" markdown-mode)
;; PHP
("\\.class\\.php$" "__.class.php" php-mode)
("\\.php$" "__" php-mode)
;; Python
;;("tests?/test_.+\\.py$" "__" nose-mode)
;;("/setup\\.py$" "__setup.py" python-mode)
("\\.py$" "__" python-mode)
;; Ruby
("/\\.rspec$" "__.rspec" rspec-mode)
("/spec_helper\\.rb$" "__helper" rspec-mode t)
("_spec\\.rb$" "__" rspec-mode t)
("/Rakefile$" "__Rakefile" ruby-mode t)
("/Gemfile$" "__Gemfile" ruby-mode t)
("\\.gemspec$" "__.gemspec" ruby-mode t)
("/lib/.+\\.rb$" "__module" ruby-mode t)
("\\.rb$" "__" ruby-mode)
;; Rust
("/Cargo.toml$" "__Cargo.toml" rust-mode)
("/main\\.rs$" "__main.rs" rust-mode)
;; SCSS
("/master\\.scss$" "__master.scss" scss-mode)
("/normalize\\.scss$" "__normalize.scss" scss-mode)
("\\.scss$" "__" scss-mode)
;; Slim
("/\\(index\\|main\\)\\.slim$" "__" slim-mode)
;; Shell scripts
("\\.z?sh$" "__" sh-mode)
)))
(provide 'core-autoinsert)
;;; core-autoinsert.el ends here

6
core/core-autoload.el Normal file
View file

@ -0,0 +1,6 @@
;;; core-autoload.el
(provide 'core-autoload)
;;; core-autoload.el ends here

View file

@ -1,55 +0,0 @@
;;; core-company.el
(use-package company
:commands (company-mode global-company-mode company-complete
company-complete-common company-manual-begin company-grab-line)
:init
(setq company-idle-delay nil
company-minimum-prefix-length 2
company-tooltip-limit 10
company-dabbrev-downcase nil
company-dabbrev-ignore-case nil
company-dabbrev-code-other-buffers t
company-tooltip-align-annotations t
company-require-match 'never
company-global-modes '(not eshell-mode comint-mode erc-mode message-mode help-mode)
company-frontends '(company-pseudo-tooltip-frontend company-echo-metadata-frontend)
company-backends '(company-capf company-yasnippet)
company-quickhelp-delay nil
company-statistics-file (concat doom-temp-dir "/company-stats-cache.el"))
:config
(require 'company-capf)
(require 'company-yasnippet)
;; Rewrites evil-complete to use company-dabbrev
(setq evil-complete-next-func 'doom/company-evil-complete-next
evil-complete-previous-func 'doom/company-evil-complete-previous)
(push 'company-sort-by-occurrence company-transformers)
(define-key company-active-map "\C-w" nil)
(global-company-mode +1)
;; NOTE: Doesn't look pretty outside of emacs-mac
(require 'company-quickhelp)
(company-quickhelp-mode +1)
(require 'company-statistics)
(company-statistics-mode +1))
(use-package company-dabbrev :commands company-dabbrev)
(use-package company-dabbrev-code :commands company-dabbrev-code)
(use-package company-etags :commands company-etags)
(use-package company-elisp :commands company-elisp)
(use-package company-files :commands company-files)
(use-package company-gtags :commands company-gtags)
(use-package company-ispell :commands company-ispell)
(use-package company-dict
:commands company-dict
:config (setq company-dict-dir (concat doom-private-dir "/dict")))
(provide 'core-company)
;;; core-company.el ends here

124
core/core-completion.el Normal file
View file

@ -0,0 +1,124 @@
;;; core-completion.el --- auto-completion, for the lazy typist
(package! company
:commands (company-mode company-complete company-complete-common company-manual-begin)
:init
(setq company-idle-delay nil
company-minimum-prefix-length 2
company-tooltip-limit 10
company-dabbrev-downcase nil
company-dabbrev-ignore-case nil
company-dabbrev-code-other-buffers t
company-tooltip-align-annotations t
company-require-match 'never
company-global-modes '(not eshell-mode comint-mode erc-mode message-mode help-mode)
company-frontends '(company-pseudo-tooltip-frontend company-echo-metadata-frontend)
company-backends '(company-capf company-yasnippet)
company-quickhelp-delay nil
company-statistics-file (concat doom-temp-dir "company-stats-cache.el"))
;; vim-like omni-complete
(map! :i "C-SPC" 'doom/company-complete
(:prefix "C-x"
:i "C-l" 'doom/company-whole-lines
:i "C-k" 'doom/company-dict-or-keywords
:i "C-f" 'company-files
:i "C-]" 'company-tags
:i "s" 'company-ispell
:i "C-s" 'company-yasnippet
:i "C-o" 'company-capf
:i "C-n" 'company-dabbrev-code
:i "C-p" (λ! (let ((company-selection-wrap-around t))
(call-interactively 'company-dabbrev-code)
(company-select-previous-or-abort)))))
:config
(require 'company-capf)
(require 'company-yasnippet)
(push 'company-sort-by-occurrence company-transformers)
;; Don't interfere with insert mode binding for `evil-delete-backward-word'
(define-key company-active-map "\C-w" nil)
(map! (:map company-active-map
"C-o" 'company-search-kill-others
"C-n" 'company-select-next
"C-p" 'company-select-previous
"C-h" 'company-quickhelp-manual-begin
"C-S-h" 'company-show-doc-buffer
"C-S-s" 'company-search-candidates
"C-s" 'company-filter-candidates
"C-SPC" 'company-complete-common
[tab] 'company-complete-common-or-cycle
[backtab] 'company-select-previous
[escape] (λ! (company-abort) (evil-normal-state 1))
[C-return] 'counsel-company)
(:map company-search-map
"C-n" 'company-search-repeat-forward
"C-p" 'company-search-repeat-backward
[escape] 'company-search-abort))
(global-company-mode +1))
(package! company-dict
:commands company-dict
:config (setq company-dict-dir (concat doom-private-dir "dict")))
;; NOTE: Doesn't look pretty on OSX without emacs-mac
(package! company-quickhelp
:after company
:config (company-quickhelp-mode +1))
(package! company-statistics
:after company
:config (company-statistics-mode +1))
;;
(autoload 'company-dabbrev "company-dabbrev" nil t)
(autoload 'company-dabbrev-code "company-dabbrev-code" nil t)
(autoload 'company-etags "company-etags" nil t)
(autoload 'company-elisp "company-elisp" nil t)
(autoload 'company-files "company-files" nil t)
(autoload 'company-gtags "company-gtags" nil t)
(autoload 'company-ispell "company-ispell" nil t)
;;
;; Defuns
;;
(defun doom/company-complete ()
"Bring up the completion popup. If only one result, complete it."
(interactive)
(require 'company)
(when (and (company-manual-begin)
(= company-candidates-length 1))
(company-complete-common)))
(defun doom/company-whole-lines (command &optional arg &rest ignored)
"`company-mode' completion backend that completes whole-lines, akin to vim's
C-x C-l."
(interactive (list 'interactive))
(require 'company)
(unless (bound-and-true-p company-mode) (company-mode))
(let ((lines (split-string
(replace-regexp-in-string
"^[\t\s]+" ""
(concat (buffer-substring-no-properties (point-min) (line-beginning-position))
(buffer-substring-no-properties (line-end-position) (point-max))))
"\\(\r\n\\|[\n\r]\\)" t)))
(cl-case command
(interactive (company-begin-backend 'doom/company-whole-lines))
(prefix (company-grab-line "^[\t\s]*\\(.+\\)" 1))
(candidates (all-completions arg lines)))))
(defun doom/company-dict-or-keywords ()
"`company-mode' completion combining `company-dict' and `company-keywords'."
(interactive)
(require 'company-dict)
(require 'company-keywords)
(let ((company-backends '((company-keywords company-dict))))
(call-interactively 'company-complete)))
(provide 'core-completion)
;;; core-completion.el ends here

33
core/core-dashboard.el Normal file
View file

@ -0,0 +1,33 @@
;;; core-dashboard.el
(setq initial-major-mode 'doom-mode
initial-scratch-message "\n Loading..."
inhibit-startup-screen t
;; shuts up emacs at startup
inhibit-startup-echo-area-message user-login-name)
(define-derived-mode doom-mode special-mode
(concat "v" doom-version)
"Major mode for DOOM buffers.")
(define-derived-mode doom-dashboard-mode doom-mode
(concat "v" doom-version)
"Major mode for DOOM buffers.")
(defvar doom-dashboard-buffer value
"")
(defvar doom-dashboard-buffer-name " *doom*"
"")
(defvar doom-dashboard--edited nil
"")
(defvar doom-dashboard-inhibit-reload nil
"")
(defvar doom-dashboard-mode-line-format (assq 'minimal doom-modeline-formats)
"")
(provide 'core-dashboard)
;;; core-dashboard.el ends here

View file

@ -1,429 +0,0 @@
;;; core-defuns.el
;; Bootstrap macro
(defmacro doom (&rest packages)
"Bootstrap DOOM emacs and initialize PACKAGES"
`(let (file-name-handler-alist)
;; Local settings
(load "~/.emacs.local.el" t t)
;; Bootstrap
(unless noninteractive
,@(mapcar (lambda (pkg)
(let ((lib-path (locate-library (symbol-name pkg))))
(unless lib-path
(error "Initfile not found: %s" pkg))
`(require ',pkg ,(file-name-sans-extension lib-path))))
packages)
(when window-system
(require 'server)
(unless (server-running-p)
(server-start)))
;; Prevent any auto-displayed text + benchmarking
(advice-add 'display-startup-echo-area-message :override 'ignore)
(message ""))
(setq-default gc-cons-threshold 4388608
gc-cons-percentage 0.4)))
;; Backwards compatible `with-eval-after-load'
(unless (fboundp 'with-eval-after-load)
(defmacro with-eval-after-load (file &rest body)
`(eval-after-load ,file (lambda () ,@body))))
(defmacro λ! (&rest body)
"A shortcut for inline keybind lambdas."
`(lambda () (interactive) ,@body))
(defmacro shut-up! (&rest body)
"Silence message output from code."
(declare (indent defun))
`(let (message-log-max) ,@body (message "")))
(defmacro after! (feature &rest forms)
"A smart wrapper around `with-eval-after-load', that supresses warnings
during compilation."
(declare (indent defun) (debug t))
`(,(if (or (not (boundp 'byte-compile-current-file))
(not byte-compile-current-file)
(if (symbolp feature)
(require feature nil :no-error)
(load feature :no-message :no-error)))
'progn
(message "after: cannot find %s" feature)
'with-no-warnings)
(with-eval-after-load ',feature ,@forms)))
(defmacro noop! (name &optional args)
`(defun ,name ,args (interactive) (error "%s not implemented!" name)))
(defmacro add-hook! (hook &rest func-or-forms)
"A convenience macro for `add-hook'.
HOOK can be one hook or a list of hooks. If the hook(s) are not quoted, -hook is
appended to them automatically. If they are quoted, they are used verbatim.
FUNC-OR-FORMS can be a quoted symbol, a list of quoted symbols, or forms. Forms will be
wrapped in a lambda. A list of symbols will expand into a series of add-hook calls.
Examples:
(add-hook! 'some-mode-hook 'enable-something)
(add-hook! some-mode '(enable-something and-another))
(add-hook! '(one-mode-hook second-mode-hook) 'enable-something)
(add-hook! (one-mode second-mode) 'enable-something)
(add-hook! (one-mode second-mode) (setq v 5) (setq a 2))"
(declare (indent defun) (debug t))
(unless func-or-forms
(error "add-hook!: FUNC-OR-FORMS is empty"))
(let* ((val (car func-or-forms))
(quoted (eq (car-safe hook) 'quote))
(hook (if quoted (cadr hook) hook))
(funcs (if (eq (car-safe val) 'quote)
(if (cdr-safe (cadr val))
(cadr val)
(list (cadr val)))
(list func-or-forms)))
(forms '()))
(mapc
(lambda (f)
(let ((func (cond ((symbolp f) `(quote ,f))
(t `(lambda (&rest _) ,@func-or-forms)))))
(mapc
(lambda (h)
(push `(add-hook ',(if quoted h (intern (format "%s-hook" h))) ,func) forms))
(-list hook)))) funcs)
`(progn ,@forms)))
(defmacro associate! (mode &rest rest)
"Associate a major or minor mode to certain patterns and project files."
(declare (indent 1))
(let ((minor (plist-get rest :minor))
(in (plist-get rest :in))
(match (plist-get rest :match))
(files (plist-get rest :files))
(pred (plist-get rest :when)))
`(progn
(,@(cond ((or files in pred)
(when (and files (not (or (listp files) (stringp files))))
(user-error "associate! :files expects a string or list of strings"))
(let ((hook-name (intern (format "doom--init-mode-%s" mode))))
`(progn
(defun ,hook-name ()
(when (and ,(if match `(if buffer-file-name (string-match-p ,match buffer-file-name)) t)
(or ,(not files)
(and (boundp ',mode)
(not ,mode)
(doom/project-has-files ,@(-list files))))
(or (not ,pred)
(funcall ,pred buffer-file-name)))
(,mode 1)))
,@(if (and in (listp in))
(mapcar (lambda (h) `(add-hook ',h ',hook-name))
(mapcar (lambda (m) (intern (format "%s-hook" m))) in))
`((add-hook 'find-file-hook ',hook-name))))))
(match
`(add-to-list ',(if minor 'doom-auto-minor-mode-alist 'auto-mode-alist)
(cons ,match ',mode)))
(t (user-error "associate! invalid rules for mode [%s] (in %s) (match %s) (files %s)"
mode in match files)))))))
(defmacro def-project-type! (name lighter &rest body)
"Define a minor mode for a specific framework, library or project type."
(declare (indent 2))
(let* ((mode-name (format "%s-project-mode" name))
(mode (intern mode-name))
(mode-map (intern (format "%s-map" mode-name)))
(mode-hook-sym (intern (format "%s-hook" mode-name)))
(mode-init-sym (intern (format "doom--init-project-%s" mode-name))))
(let ((modes (plist-get body :modes))
(pred (plist-get body :when))
(match (plist-get body :match))
(files (plist-get body :files))
(build (plist-get body :build))
(bind (plist-get body :bind))
elem)
(while (keywordp (car body))
(pop body)
(pop body))
`(progn
(define-minor-mode ,mode
"Auto-generated by `def-project-type!'"
:init-value nil
:lighter ,(concat " " lighter)
:keymap (make-sparse-keymap))
(after! yasnippet
(add-hook ',mode-hook-sym
(lambda ()
(if ,mode
(yas-activate-extra-mode ',mode)
(yas-deactivate-extra-mode ',mode)))))
,(when bind `(map! :map ,mode-map ,bind))
(associate! ,mode
:minor t
:in ,modes
:match ,match
:files ,files
:when ,pred)
(defun ,mode-init-sym ()
(after! company-dict
(push ',mode company-dict-minor-mode-list))
,(when build
(let ((cmd build) file)
(when (and (not (functionp build)) (listp build))
(setq cmd (car-safe (cdr-safe build))
file (cdr-safe (cdr-safe build))))
`(def-builder! ,mode ,cmd ,file)))
,@body
(remove-hook ',mode-hook-sym ',mode-init-sym))
(add-hook ',mode-hook-sym ',mode-init-sym)
',mode))))
(after! evil
(defalias 'ex! 'evil-ex-define-cmd)
;; NOTE evil-mode doesn't read local `evil-ex-commands', and will not
;; autocomplete local commands.
(defun ex-local! (cmd fn)
"Define a buffer-local ex command."
(unless (local-variable-p 'evil-ex-commands)
(setq-local evil-ex-commands (copy-alist evil-ex-commands)))
(evil-ex-define-cmd cmd fn))
;; Register keywords for proper indentation (see `map!')
(put ':prefix 'lisp-indent-function 'defun)
(put ':map 'lisp-indent-function 'defun)
(put ':map* 'lisp-indent-function 'defun)
(put ':after 'lisp-indent-function 'defun)
(put ':when 'lisp-indent-function 'defun)
(put ':unless 'lisp-indent-function 'defun)
(put ':leader 'lisp-indent-function 'defun)
(put ':localleader 'lisp-indent-function 'defun)
(defmacro map! (&rest rest)
"A nightmare of a key-binding macro that will use `evil-define-key',
`evil-define-key*', `define-key' and `global-set-key' depending on context and
plist key flags. It was designed to make binding multiple keys more concise,
like in vim.
Yes, it tries to do too much. Yes, I only did it to make the \"frontend\" config
that little bit more concise. Yes, I could simply have used the above functions.
But it takes a little insanity to custom write your own emacs.d, so what else
were you expecting?
States
:n normal
:v visual
:i insert
:e emacs
:o operator
:m motion
:r replace
:L local
These can be combined (order doesn't matter), e.g. :nvi will apply to
normal, visual and insert mode. The state resets after the following
key=>def pair.
Capitalize the state flag to make it a local binding.
If omitted, the keybind will be defined globally.
Flags
:unset [KEY] ; unset key
(:map [KEYMAP] [...]) ; apply inner keybinds to KEYMAP
(:map* [KEYMAP] [...]) ; apply inner keybinds to KEYMAP (deferred)
(:prefix [PREFIX] [...]) ; assign prefix to all inner keybindings
(:after [FEATURE] [...]) ; apply keybinds when [FEATURE] loads
Conditional keybinds
(:when [CONDITION] [...])
(:unless [CONDITION] [...])
Example
(map! :map magit-mode-map
:m \"C-r\" 'do-something ; assign C-r in motion state
:nv \"q\" 'magit-mode-quit-window ; assign to 'q' in normal and visual states
\"C-x C-r\" 'a-global-keybind
(:when IS-MAC
:n \"M-s\" 'some-fn
:i \"M-o\" (lambda (interactive) (message \"Hi\"))))"
(let ((keymaps (if (boundp 'keymaps) keymaps))
(state-map '(("n" . normal)
("v" . visual)
("i" . insert)
("e" . emacs)
("o" . operator)
("m" . motion)
("r" . replace)))
(prefix (if (boundp 'prefix) prefix))
(defer (if (boundp 'defer) defer))
local key def states forms)
(while rest
(setq key (pop rest))
(push
(reverse
(cond
;; it's a sub expr
((listp key)
`(,(macroexpand `(map! ,@key))))
;; it's a flag
((keywordp key)
(when (memq key '(:leader :localleader))
(push (cond ((eq key :leader)
doom-leader)
((eq key :localleader)
doom-localleader))
rest)
(setq key :prefix))
(pcase key
(:prefix (setq prefix (concat prefix (kbd (pop rest)))) nil)
(:map (setq keymaps (-list (pop rest))) nil)
(:map* (setq defer t keymaps (-list (pop rest))) nil)
(:unset `(,(macroexpand `(map! ,(kbd (pop rest)) nil))))
(:after (prog1 `((after! ,(pop rest) ,(macroexpand `(map! ,@rest)))) (setq rest '())))
(:when (prog1 `((if ,(pop rest) ,(macroexpand `(map! ,@rest)))) (setq rest '())))
(:unless (prog1 `((if (not ,(pop rest)) ,(macroexpand `(map! ,@rest)))) (setq rest '())))
(otherwise ; might be a state prefix
(mapc (lambda (letter)
(cond ((assoc letter state-map)
(push (cdr (assoc letter state-map)) states))
((string= letter "L")
(setq local t))
(t (user-error "Invalid mode prefix %s in key %s" letter key))))
(split-string (substring (symbol-name key) 1) "" t))
(unless states
(user-error "Unrecognized keyword %s" key))
(when (assoc "L" states)
(cond ((= (length states) 1)
(user-error "local keybinding for %s must accompany another state" key))
((> (length keymaps) 0)
(user-error "local keybinding for %s cannot accompany a keymap" key))))
nil)))
;; It's a key-def pair
((or (stringp key)
(characterp key)
(vectorp key))
(when (stringp key)
(setq key (kbd key)))
(when prefix
(setq key (cond ((vectorp key) (vconcat prefix key))
(t (concat prefix key)))))
(unless (> (length rest) 0)
(user-error "Map has no definition for %s" key))
(setq def (pop rest))
(let (out-forms)
(cond ((and keymaps states)
(mapc (lambda (keymap)
(push `(,(if defer 'evil-define-key 'evil-define-key*)
',states ,keymap ,key ,def)
out-forms))
keymaps))
(keymaps
(mapc (lambda (keymap) (push `(define-key ,keymap ,key ,def) out-forms))
keymaps))
(states
(mapc (lambda (state)
(push `(define-key
(evil-state-property ',state ,(if local :local-keymap :keymap) t)
,key ,def)
out-forms))
states))
(t (push `(,(if local 'local-set-key 'global-set-key)
,key ,def)
out-forms)))
(setq states '()
local nil)
out-forms))
(t (user-error "Invalid key %s" key))))
forms))
`(progn ,@(apply #'nconc (delete nil (delete (list nil) (reverse forms))))))))
(defmacro def-repeat! (command next-func prev-func)
"Repeat motions with SPC/S-SPC"
`(defadvice ,command
(before ,(intern (format "doom-space--%s" (symbol-name command))) activate)
(define-key evil-motion-state-map (kbd "SPC") ',next-func)
(define-key evil-motion-state-map (kbd "S-SPC") ',prev-func)))
;;
;; Global Defuns
;;
(defsubst --subdirs (path &optional include-self)
"Get list of subdirectories in PATH, including PATH is INCLUDE-SELF is
non-nil."
(let ((result (if include-self (list path) (list))))
(mapc (lambda (file)
(when (file-directory-p file)
(push file result)))
(ignore-errors (directory-files path t "^[^.]" t)))
result))
(defun doom-reload ()
"Reload `load-path' and `custom-theme-load-path', in case you updated cask
while emacs was open!"
(interactive)
(let* ((-packages-path (--subdirs doom-packages-dir))
(-load-path
(append (list doom-private-dir doom-core-dir doom-modules-dir doom-packages-dir)
(--subdirs doom-core-dir t)
(--subdirs doom-modules-dir t)
-packages-path
(--subdirs (expand-file-name (format "../../%s/bootstrap" emacs-version)
doom-packages-dir))
doom--load-path))
(-custom-theme-load-path
(append (--subdirs doom-themes-dir t)
custom-theme-load-path)))
(setq load-path -load-path
custom-theme-load-path -custom-theme-load-path)
(if (called-interactively-p 'interactive)
(message "Reloaded!")
(list -load-path
-custom-theme-load-path
(mapcar '--subdirs -packages-path)))))
(defun doom-reload-autoloads ()
"Regenerate and reload autoloads.el."
(interactive)
(let ((generated-autoload-file (concat doom-core-dir "/autoloads.el")))
(when (file-exists-p generated-autoload-file)
(delete-file generated-autoload-file)
(message "Deleted old autoloads.el"))
(mapc (lambda (dir)
(update-directory-autoloads (concat dir "/defuns"))
(message "Scanned: %s" dir))
(list doom-core-dir doom-modules-dir))
(when (called-interactively-p 'interactive)
(load "autoloads"))
(message "Done!")))
(defun doom-byte-compile (&optional minimal)
"Byte compile the core and library .el files in ~/.emacs.d. If MINIMAL is nil,
only byte compile a few important files. If t, compile all files too. If 'basic,
only compile defun libraries."
(interactive)
(mapc (lambda (f) (byte-compile-file (concat doom-emacs-dir "/" f) t))
'("init.el" "core/core.el" "core/core-defuns.el" "core/core-ui.el"
"core/core-modeline.el" "core/core-os.el" "core/core-os-osx.el"
"core/core-os-win32.el" "core/core-os-linux.el"
"private/my-commands.el" "private/my-bindings.el"))
(unless (eq minimal 'basic)
(unless minimal
(byte-recompile-directory doom-core-dir 0 t)
(byte-recompile-directory doom-modules-dir 0 t))
(when minimal
(byte-recompile-directory (concat doom-core-dir "/defuns") 0 t)
(byte-recompile-directory (concat doom-modules-dir "/defuns") 0 t)))
(message "Compiled!"))
(provide 'core-defuns)
;;; core-defuns.el ends here

View file

@ -1,42 +0,0 @@
;;; core-docs.el
(use-package dash-at-point
:when IS-MAC
:commands (dash-at-point dash-at-point-with-docset dash-at-point-run-search
dash-at-point-guess-docset)
:init
(defun doom-docs-lookup (&optional search all)
(let ((docset (unless all (dash-at-point-guess-docset))))
(dash-at-point-run-search search docset))))
(use-package zeal-at-point
:when (not IS-MAC)
:commands (zeal-at-point zeal-at-point-set-docset)
:init
(defun doom-docs-lookup (&optional search all)
(let ((zeal-at-point-docset (if all "" zeal-at-point-docset)))
(zeal-at-point search))))
(defmacro def-docset! (mode docset)
`(add-hook! ,mode
(setq-local ,(if IS-MAC 'dash-at-point-docset 'zeal-at-point-docset)
,docset)))
(use-package google-this
:commands (google-this-search
google-this-lucky-and-insert-url
google-this-lucky-search
google-this-string
google-this-line
google-this-ray
google-this-word
google-this-symbol
google-this-region
google-this
google-this-noconfirm
google-this-error
google-this-cpp-reference
google-this-forecast))
(provide 'core-docs)
;;; core-docs.el ends here

View file

@ -1,58 +1,58 @@
;;; core-editor.el
;;; core-editor.el --- filling the editor shaped hole in the Emacs OS
(global-auto-revert-mode 1) ; revert buffers for changed files
;; Enable syntax highlighting for older emacs
(unless (bound-and-true-p global-font-lock-mode)
(global-font-lock-mode t))
;; Bookmarks
(setq bookmark-default-file (concat doom-temp-dir "/bookmarks")
bookmark-save-flag t)
(setq-default
;; Formatting
delete-trailing-lines nil
;; Formatting
(setq delete-trailing-lines nil
fill-column 80
;; Spaces, not tabs
indent-tabs-mode nil
require-final-newline t
tab-always-indent t
tab-width 4
;; Wrapping
truncate-lines t
truncate-partial-width-windows 50
visual-fill-column-center-text nil
word-wrap t
;; Scrolling
hscroll-margin 1
sentence-end-double-space nil)
;; Scrolling
(setq hscroll-margin 1
hscroll-step 1
scroll-conservatively 1001
scroll-margin 0
scroll-preserve-screen-position t
;; Regions
shift-select-mode t
;; Whitespace
tabify-regexp "^\t* [ \t]+"
scroll-preserve-screen-position t)
;; Whitespace (see `editorconfig')
(setq indent-tabs-mode nil
require-final-newline t
tab-always-indent t
tab-width 4
tabify-regexp "^\t* [ \t]+" ; for :retab
whitespace-line-column fill-column
whitespace-style '(face tabs tab-mark
trailing indentation lines-tail)
whitespace-style
'(face tabs tab-mark trailing indentation lines-tail)
whitespace-display-mappings
'((tab-mark ?\t [? ?\t])
(newline-mark 10 [36 10])))
'((tab-mark ?\t [? ?\t]) (newline-mark 10 [36 10])))
;; Wrapping
(setq truncate-lines t
truncate-partial-width-windows 50
visual-fill-column-center-text nil
word-wrap t)
;; Regions
(setq shift-select-mode t)
;; Save point across sessions
(require 'saveplace)
(setq-default
save-place-file (concat doom-temp-dir "/saveplace")
(setq save-place-file (concat doom-temp-dir "saveplace")
save-place t)
(when (>= emacs-major-version 25)
(save-place-mode +1))
;; Save history across sessions
(require 'savehist)
(setq savehist-file (concat doom-temp-dir "/savehist")
(setq savehist-file (concat doom-temp-dir "savehist")
savehist-save-minibuffer-history t
savehist-additional-variables
'(kill-ring search-ring regexp-search-ring))
(savehist-mode 1)
;; Remove text property cruft from history
;; Remove text-property cruft from history
(defun unpropertize-savehist ()
(mapc (lambda (list)
(when (boundp list)
@ -65,7 +65,7 @@
;; Keep track of recently opened files
(require 'recentf)
(setq recentf-save-file (concat doom-temp-dir "/recentf")
(setq recentf-save-file (concat doom-temp-dir "recentf")
recentf-exclude '("/tmp/" "/ssh:" "\\.?ido\\.last$" "\\.revive$" "/TAGS$"
"emacs\\.d/private/cache/.+" "emacs\\.d/workgroups/.+$"
"wg-default" "/company-statistics-cache.el$"
@ -76,18 +76,21 @@
recentf-filename-handlers '(abbreviate-file-name))
(recentf-mode 1)
;; window config undo/redo
(setq winner-dont-bind-my-keys t)
(require 'winner)
;; Ignore all special buffers
(advice-add 'winner-window-list :filter-return 'doom*winner-window-list)
(defun doom*winner-window-list (windows)
(-remove (lambda (win) (string-match-p "^\\s-*\\*" (buffer-name (window-buffer win))))
windows))
(winner-mode 1)
;; Ediff
(add-hook! ediff-load
(setq ediff-diff-options "-w"
ediff-split-window-function 'split-window-horizontally
ediff-window-setup-function 'ediff-setup-windows-plain)) ; no extra frames
;; Let editorconfig handle global whitespace settings
(use-package editorconfig :demand t
;; revert buffers for changed files
(global-auto-revert-mode +1)
;;
;; Plugins
;;
(package! editorconfig :demand t
:mode ("\\.?editorconfig$" . editorconfig-conf-mode)
:config (editorconfig-mode +1)
(push 'doom-mode editorconfig-exclude-modes)
@ -95,164 +98,15 @@
(add-hook! 'editorconfig-custom-hooks
(if indent-tabs-mode (whitespace-mode +1))))
;;
;; Hooks 'n hacks
;;
(associate! makefile-gmake-mode :match "/Makefile$")
(add-hook! special-mode (setq truncate-lines nil))
;; If file is oversized...
(add-hook! find-file
(when (> (buffer-size) 1048576)
(setq buffer-read-only t)
(buffer-disable-undo)
(fundamental-mode)
(visual-line-mode)))
(defadvice delete-trailing-whitespace
(around delete-trailing-whitespace-ignore-line activate)
"Don't delete trailing whitespace on current line, if in insert mode."
(let ((spaces (1- (current-column)))
(linestr (buffer-substring-no-properties
(line-beginning-position)
(line-end-position))))
ad-do-it
(when (and (evil-insert-state-p)
(string-match-p "^[\s\t]*$" linestr))
(insert linestr))))
;; Disable by default, please
(electric-indent-mode -1)
;; Smarter, keyword-based electric-indent (see `def-electric!')
(defvar doom-electric-indent-p nil)
(defvar-local doom-electric-indent-words '())
(setq electric-indent-chars '(?\n ?\^?))
(push (lambda (c)
(when (and (eolp) doom-electric-indent-words)
(save-excursion
(backward-word)
(looking-at-p
(concat "\\<" (regexp-opt doom-electric-indent-words))))))
electric-indent-functions)
;;
;; Plugins
;;
(use-package ace-window
:commands ace-window
:config (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)
aw-scope 'frame
aw-background t))
(use-package ace-link :commands (ace-link-help ace-link-org))
(use-package avy
:commands (avy-goto-char-2 avy-goto-line)
:config (setq avy-all-windows nil
avy-background t))
(use-package command-log-mode
:commands (clm/command-log-buffer command-log-mode global-command-log-mode)
:config (setq command-log-mode-is-global t))
(use-package dumb-jump
:commands (dumb-jump-go dumb-jump-quick-look dumb-jump-back)
:config
(setq dumb-jump-default-project doom-emacs-dir)
(dumb-jump-mode +1))
(use-package emr
:commands (emr-show-refactor-menu emr-declare-command)
:config
(emr-initialize)
(define-key popup-menu-keymap [escape] 'keyboard-quit))
(use-package expand-region
:commands (er/expand-region er/contract-region er/mark-symbol er/mark-word))
(use-package goto-last-change :commands goto-last-change)
(use-package hideshow
:commands (hs-minor-mode hs-toggle-hiding hs-already-hidden-p)
:config (setq hs-isearch-open t)
(package! smartparens :demand t
:init
(defun doom*load-hs-minor-mode ()
(hs-minor-mode 1)
(advice-remove 'evil-toggle-fold 'doom-load-hs-minor-mode))
(advice-add 'evil-toggle-fold :before 'doom*load-hs-minor-mode)
;; Prettify code folding in emacs
(define-fringe-bitmap 'hs-marker [16 48 112 240 112 48 16] nil nil 'center)
(defface hs-face '((t (:background "#ff8")))
"Face to hightlight the ... area of hidden regions"
:group 'hideshow)
(defface hs-fringe-face '((t (:foreground "#888")))
"Face used to highlight the fringe on folded regions"
:group 'hideshow)
(setq hs-set-up-overlay
(lambda (ov)
(when (eq 'code (overlay-get ov 'hs))
(let* ((marker-string "*")
(display-string (concat " " (all-the-icons-octicon "ellipsis" :v-adjust 0) " "))
(len (length display-string)))
(put-text-property 0 1 'display
(list 'right-fringe 'hs-marker 'hs-fringe-face)
marker-string)
(put-text-property 0 1 'face 'hs-face display-string)
(put-text-property (1- len) len 'face 'hs-face display-string)
(put-text-property 1 (1- len)
'face `(:inherit hs-face :family ,(all-the-icons-octicon-family) :height 1.1)
display-string)
(overlay-put ov 'before-string marker-string)
(overlay-put ov 'display display-string))))))
(use-package help-fns+ ; Improved help commands
:commands (describe-buffer describe-command describe-file
describe-keymap describe-option describe-option-of-type))
(use-package imenu-list
:commands imenu-list-minor-mode
:config
(setq imenu-list-mode-line-format nil
imenu-list-position 'right
imenu-list-size 32)
(map! :map imenu-list-major-mode-map
:n [escape] 'doom/imenu-list-quit
:n "RET" 'imenu-list-goto-entry
:n "SPC" 'imenu-list-display-entry
:n [tab] 'hs-toggle-hiding))
(use-package re-builder
:commands (re-builder reb-mode-buffer-p)
:init (add-hook 'reb-mode-hook 'doom|reb-cleanup)
:config
(evil-set-initial-state 'reb-mode 'insert)
(setq reb-re-syntax 'string)
(map! (:map* rxt-help-mode-map
:n [escape] 'kill-buffer-and-window)
(:map* reb-mode-map
:n "C-g" 'reb-quit
:n [escape] 'reb-quit
:n [backtab] 'reb-change-syntax)))
(use-package pcre2el :commands (rxt-quote-pcre))
(use-package rotate-text
:commands (rotate-text rotate-text-backward)
:config (push '("true" "false") rotate-text-words))
(use-package smart-forward
:commands (smart-up smart-down smart-backward smart-forward))
(use-package smartparens
:config
(setq sp-autowrap-region nil ; let evil-surround handle this
sp-highlight-pair-overlay nil
sp-cancel-autoskip-on-backward-movement nil
sp-show-pair-delay 0
sp-max-pair-length 3)
:config
(smartparens-global-mode 1)
(require 'smartparens-config)
;; Smartparens interferes with Replace mode
@ -275,15 +129,74 @@
(sp-with-modes '(xml-mode nxml-mode php-mode)
(sp-local-pair "<!--" "-->" :post-handlers '(("| " "SPC")))))
(use-package smex
:commands (smex smex-major-mode-commands)
;;
;; Autoloaded Plugins
;;
(package! ace-link :commands (ace-link-help ace-link-org))
(package! ace-window
:commands ace-window
:config (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)
aw-scope 'frame
aw-background t))
(package! avy
:commands (avy-goto-char-2 avy-goto-line)
:config (setq avy-all-windows nil
avy-background t))
(package! command-log-mode
:commands (clm/command-log-buffer command-log-mode global-command-log-mode)
:config (setq command-log-mode-is-global t))
(package! emr
:commands (emr-show-refactor-menu emr-declare-command)
:config
(setq smex-save-file (concat doom-temp-dir "/smex-items"))
(smex-initialize))
(emr-initialize)
(define-key popup-menu-keymap [escape] 'keyboard-quit))
(use-package swiper :commands (swiper swiper-all))
(package! expand-region :commands (er/expand-region er/contract-region er/mark-symbol er/mark-word))
(use-package wgrep
(package! goto-last-change :commands goto-last-change)
(package! help-fns+ ; Improved help commands
:commands (describe-buffer describe-command describe-file
describe-keymap describe-option describe-option-of-type))
(package! imenu-anywhere
:commands (ido-imenu-anywhere ivy-imenu-anywhere helm-imenu-anywhere))
(package! imenu-list :commands imenu-list-minor-mode)
(package! pcre2el :commands rxt-quote-pcre)
(package! re-builder
:commands (re-builder reb-mode-buffer-p)
:init (add-hook 'reb-mode-hook 'doom|reb-cleanup)
:config
(evil-set-initial-state 'reb-mode 'insert)
(setq reb-re-syntax 'string)
;; (map! (:map* rxt-help-mode-map
;; :n [escape] 'kill-buffer-and-window)
;; (:map* reb-mode-map
;; :n "C-g" 'reb-quit
;; :n [escape] 'reb-quit
;; :n [backtab] 'reb-change-syntax))
)
(package! rotate-text
:quelpa (rotate-text :fetcher github :repo "debug-ito/rotate-text.el")
:commands (rotate-text rotate-text-backward)
:config (push '("true" "false") rotate-text-words))
(package! smart-forward
:commands (smart-up smart-down smart-backward smart-forward))
(package! swiper :commands (swiper swiper-all))
(package! wgrep
:commands (wgrep-setup wgrep-change-to-wgrep-mode)
:config
(def-popup! "^\\*ivy-occur counsel-ag" :align below :size 25 :select t :regexp t)
@ -291,97 +204,5 @@
(advice-add 'wgrep-abort-changes :after 'doom/popup-close)
(advice-add 'wgrep-finish-edit :after 'doom/popup-close))
;;
;; Keybinding fixes
;;
;; This section is dedicated to bindings that "fix" certain keys so that they
;; behave more like vim (or how I like it).
;; Line-wise mouse selection on margin
(map! "<left-margin> <down-mouse-1>" 'doom/mouse-drag-line
"<left-margin> <mouse-1>" 'doom/mouse-select-line
"<left-margin> <drag-mouse-1>" 'doom/mouse-select-line)
;; Restores "dumb" indentation to the tab key. This rustles a lot of peoples'
;; jimmies, apparently, but it's how I like it.
(map! :i "<tab>" 'doom/dumb-indent
:i "<backtab>" 'doom/dumb-dedent
:i "<C-tab>" 'indent-for-tab-command
:i "<A-tab>" (λ! (insert "\t"))
;; No dumb-tab for lisp
(:map* lisp-mode-map :i [remap doom/dumb-indent] 'indent-for-tab-command)
(:map* emacs-lisp-mode-map :i [remap doom/dumb-indent] 'indent-for-tab-command)
;; Highjacks space/backspace to:
;; a) eat spaces on either side of the cursor, if present ( | ) -> (|)
;; b) allow backspace to delete space-indented blocks intelligently
;; c) but do none of this when inside a string
:i "SPC" 'doom/inflate-space-maybe
:i [remap delete-backward-char] 'doom/deflate-space-maybe
:i [remap newline] 'doom/newline-and-indent
;; Smarter move-to-beginning-of-line
:i [remap move-beginning-of-line] 'doom/move-to-bol
;; Restore bash-esque keymaps in insert mode; C-w and C-a already exist
:i "C-e" 'doom/move-to-eol
:i "C-u" 'doom/backward-kill-to-bol-and-indent
;; Fixes delete
:i "<kp-delete>" 'delete-char
;; Fix osx keymappings and then some
:i "<M-left>" 'doom/move-to-bol
:i "<M-right>" 'doom/move-to-eol
:i "<M-up>" 'beginning-of-buffer
:i "<M-down>" 'end-of-buffer
:i "<C-up>" 'smart-up
:i "<C-down>" 'smart-down
;; Fix emacs motion keys
:i "A-b" 'evil-backward-word-begin
:i "A-w" 'evil-forward-word-begin
:i "A-e" 'evil-forward-word-end
;; Textmate-esque insert-line before/after
:i [M-return] 'evil-open-below
:i [S-M-return] 'evil-open-above
;; insert lines in-place)
:n [M-return] (λ! (save-excursion (evil-insert-newline-below)))
:n [S-M-return] (λ! (save-excursion (evil-insert-newline-above)))
;; Make ESC quit all the things
(:map (minibuffer-local-map
minibuffer-local-ns-map
minibuffer-local-completion-map
minibuffer-local-must-match-map
minibuffer-local-isearch-map)
[escape] 'abort-recursive-edit
"C-r" 'evil-paste-from-register)
(:map (evil-ex-search-keymap read-expression-map)
"C-w" 'backward-kill-word
"C-u" 'backward-kill-sentence
"C-b" 'backward-word)
(:map evil-ex-completion-map "C-a" 'move-beginning-of-line)
(:after view
(:map view-mode-map "<escape>" 'View-quit-all))
(:after help-mode
(:map help-map
;; Remove slow/annoying help subsections
"h" nil
"g" nil)))
(map! :map key-translation-map
;; Fix certain keys in the terminal
(:unless window-system "TAB" [tab])
;; Common unicode characters
:i "A-o" (kbd "ø")
:i "A-O" (kbd "Ø")
:i "A--" (kbd "")
:i "A-_" (kbd "")
:i "A-8" (kbd "")
:i "A-*" (kbd "°")
:i "A-p" (kbd "π"))
(provide 'core-editor)
;;; core-editor.el ends here

View file

@ -1,49 +0,0 @@
;;; core-eval.el
;; + Running inline code + REPLs (using `quickrun' + `repl-toggle')
;; + Simple code navigation (using `dump-jump' and `imenu-list')
;; remove ellipsis when printing sexp in message buffer
(setq eval-expression-print-length nil
eval-expression-print-level nil)
(use-package quickrun
:commands (quickrun
quickrun-region
quickrun-with-arg
quickrun-shell
quickrun-compile-only
quickrun-replace-region)
:init (add-hook 'quickrun/mode-hook 'linum-mode)
:config
(setq quickrun-focus-p nil)
(def-popup! "*quickrun*" :align below :size 10)
;;; Popup hacks
(advice-add 'quickrun :before 'doom*quickrun-close-popup)
(advice-add 'quickrun-region :before 'doom*quickrun-close-popup)
;; Ensures window is scrolled to BOF
(add-hook 'quickrun-after-run-hook 'doom|quickrun-after-run))
(use-package repl-toggle
:commands (rtog/toggle-repl rtog/add-repl)
:preface (defvar rtog/mode-repl-alist nil)
:init
(defvar doom-repl-buffer nil "The current REPL buffer.")
(add-hook! repl-toggle-mode (evil-initialize-state 'emacs))
:config
(def-popup!
(:custom (lambda (b &rest _)
(when (and (featurep 'repl-toggle)
(string-prefix-p "*" (buffer-name (get-buffer b))))
(buffer-local-value 'repl-toggle-mode b))))
:popup t :align below :size 16 :select t)
(map! :map repl-toggle-mode-map
:ei "C-n" 'comint-next-input
:ei "C-p" 'comint-previous-input
:ei "<down>" 'comint-next-input
:ei "<up>" 'comint-previous-input))
(provide 'core-eval)
;;; core-eval.el ends here

View file

@ -1,6 +1,19 @@
;;; core-evil.el --- the root of all evil
;;; core-evil.el --- Come to the dark side, we have cookies
(use-package evil
;; TODO Document
(defvar doom-evil-leader ","
"docstring")
(defvar doom-evil-localleader "\\"
"docstring")
;;
;; Packages
;;
(package! evil :demand t
:init
(setq evil-magic t
evil-want-C-u-scroll t
@ -19,288 +32,16 @@
evil-emacs-state-tag "E"
evil-operator-state-tag "O"
evil-motion-state-tag "M"
evil-replace-state-tag "R"
;; Set cursor colors
evil-default-cursor (face-attribute 'cursor :background nil t)
evil-normal-state-cursor 'box
evil-emacs-state-cursor `(,(face-attribute 'warning :foreground nil nil) box)
evil-insert-state-cursor 'bar
evil-visual-state-cursor 'hollow)
;; highlight matching delimiters where it's important
(defun show-paren-mode-off () (show-paren-mode -1))
(add-hook 'evil-insert-state-entry-hook 'show-paren-mode)
(add-hook 'evil-insert-state-exit-hook 'show-paren-mode-off)
(add-hook 'evil-visual-state-entry-hook 'show-paren-mode)
(add-hook 'evil-visual-state-exit-hook 'show-paren-mode-off)
(add-hook 'evil-operator-state-entry-hook 'show-paren-mode)
(add-hook 'evil-operator-state-exit-hook 'show-paren-mode-off)
(add-hook 'evil-normal-state-entry-hook 'show-paren-mode-off)
;; Disable highlights on insert-mode
(add-hook 'evil-insert-state-entry-hook 'evil-ex-nohighlight)
evil-replace-state-tag "R")
:config
(evil-mode 1)
(evil-select-search-module 'evil-search-module 'evil-search)
(evil-mode +1)
(evil-select-search-module 'evil-search-module 'evil-search))
(mapc (lambda (r) (evil-set-initial-state (car r) (cdr r)))
'((compilation-mode . normal)
(help-mode . normal)
(message-mode . normal)
(debugger-mode . normal)
(image-mode . normal)
(doc-view-mode . normal)
(eww-mode . normal)
(tabulated-list-mode . emacs)
(profile-report-mode . emacs)
(Info-mode . emacs)
(view-mode . emacs)
(comint-mode . emacs)
(cider-repl-mode . emacs)
(term-mode . emacs)
(calendar-mode . emacs)
(Man-mode . emacs)
(grep-mode . emacs)))
;; Popups
(def-popup! "*evil-registers*" :align below :size 0.3)
(def-popup! "*Command Line*" :align below :size 8 :select t)
;;; Evil hacks
;; Don't interfere with neotree + auto move to new split
(advice-add 'evil-window-split :around 'doom*evil-window-split)
(advice-add 'evil-window-vsplit :around 'doom*evil-window-vsplit)
;; Integrate evil's command window into shackle
(advice-add 'evil-command-window :override 'doom*evil-command-window)
(add-hook 'evil-command-window-mode-hook 'doom-hide-mode-line-mode)
;; Close popups, disable search highlights and quit the minibuffer if open
(advice-add 'evil-force-normal-state :after 'doom*evil-esc-quit)
;; Fix harmless (yet disruptive) error reporting w/ hidden buffers caused by
;; workgroups killing windows
;; TODO Delete timer on dead windows?
(defadvice evil-ex-hl-do-update-highlight
(around evil-ex-hidden-buffer-ignore-errors activate)
(ignore-errors ad-do-it))
;; Hide keystroke display while isearch is active
(add-hook! isearch-mode (setq echo-keystrokes 0))
(add-hook! isearch-mode-end (setq echo-keystrokes 0.02))
(def-repeat! evil-ex-search-next evil-ex-search-next evil-ex-search-previous)
(def-repeat! evil-ex-search-previous evil-ex-search-next evil-ex-search-previous)
(def-repeat! evil-ex-search-forward evil-ex-search-next evil-ex-search-previous)
(def-repeat! evil-ex-search-backward evil-ex-search-next evil-ex-search-previous)
;; monkey patch `evil-ex-replace-special-filenames' to add most of vim's file
;; ex substitution flags to evil-mode
(advice-add 'evil-ex-replace-special-filenames
:override 'doom*evil-ex-replace-special-filenames)
;; Extra argument types for highlight buffer (or global) regexp matches
(evil-ex-define-argument-type buffer-match :runner doom/evil-ex-buffer-match)
(evil-ex-define-argument-type global-match :runner doom/evil-ex-global-match)
(evil-define-interactive-code "<//>"
:ex-arg buffer-match
(list (when (evil-ex-p) evil-ex-argument)))
(evil-define-interactive-code "<g//>"
:ex-arg global-match
(when (evil-ex-p) (evil-ex-parse-global evil-ex-argument)))
(evil-define-operator doom:evil-ex-global (beg end pattern command &optional invert)
"Rewritten :g[lobal] that will highlight buffer matches. Takes the same arguments."
:motion mark-whole-buffer :move-point nil
(interactive "<r><g//><!>")
(evil-ex-global beg end pattern command invert))
(evil-define-operator doom:align (&optional beg end bang pattern)
"Ex interface to `align-regexp'. Accepts vim-style regexps."
(interactive "<r><!><//>")
(align-regexp
beg end
(concat "\\(\\s-*\\)"
(if bang
(regexp-quote pattern)
(evil-transform-vim-style-regexp pattern)))
1 1)))
;; evil plugins
(use-package evil-numbers
:commands (evil-numbers/inc-at-pt evil-numbers/dec-at-pt))
(use-package evil-anzu
:defer t
:init
;; evil-anzu is strangely slow on startup. Byte compiling doesn't help. We use
;; this to lazy load it instead.
(defun doom*evil-search (&rest _)
(require 'evil-anzu)
(advice-remove 'evil-ex-start-search 'doom*evil-search))
(advice-add 'evil-ex-start-search :before 'doom*evil-search)
:config
(setq anzu-cons-mode-line-p nil
anzu-minimum-input-length 1
anzu-search-threshold 250))
(use-package evil-args
:commands (evil-inner-arg evil-outer-arg evil-forward-arg evil-backward-arg evil-jump-out-args)
:init (def-text-obj! "a" 'evil-inner-arg 'evil-outer-arg))
(use-package evil-commentary
:commands (evil-commentary evil-commentary-yank evil-commentary-line)
:config (evil-commentary-mode 1))
(use-package evil-exchange
:commands evil-exchange
:config (advice-add 'evil-force-normal-state :after 'doom*evil-exchange-off))
(use-package evil-multiedit
:commands (evil-multiedit-match-all
evil-multiedit-match-and-next
evil-multiedit-match-and-prev
evil-multiedit-match-symbol-and-next
evil-multiedit-match-symbol-and-prev
evil-multiedit-toggle-or-restrict-region
evil-multiedit-next
evil-multiedit-prev
evil-multiedit-abort
evil-multiedit-ex-match)
:config (evil-multiedit-default-keybinds))
(use-package evil-indent-plus
:commands (evil-indent-plus-i-indent
evil-indent-plus-a-indent
evil-indent-plus-i-indent-up
evil-indent-plus-a-indent-up
evil-indent-plus-i-indent-up-down
evil-indent-plus-a-indent-up-down)
:init
(def-text-obj! "i" 'evil-indent-plus-i-indent 'evil-indent-plus-a-indent)
(def-text-obj! "I" 'evil-indent-plus-i-indent-up 'evil-indent-plus-a-indent-up)
(def-text-obj! "J" 'evil-indent-plus-i-indent-up-down 'evil-indent-plus-a-indent-up-down))
(use-package evil-matchit
:commands (evilmi-jump-items evilmi-text-object global-evil-matchit-mode)
:config (global-evil-matchit-mode 1)
:init (def-text-obj! "%" 'evilmi-text-object))
(use-package evil-textobj-anyblock
:commands (evil-textobj-anyblock-inner-block evil-textobj-anyblock-a-block)
:init (def-text-obj! "B" 'evil-textobj-anyblock-inner-block 'evil-textobj-anyblock-a-block))
(use-package evil-search-highlight-persist
:config
(global-evil-search-highlight-persist t)
(advice-add 'evil-force-normal-state :after 'evil-search-highlight-persist-remove-all))
(use-package evil-easymotion
:defer 1
:init (defvar doom--evil-snipe-repeat-fn)
:config
(evilem-default-keybindings "g SPC")
(evilem-define (kbd "g SPC n") 'evil-ex-search-next)
(evilem-define (kbd "g SPC N") 'evil-ex-search-previous)
(evilem-define "gs" 'evil-snipe-repeat
:pre-hook (save-excursion (call-interactively #'evil-snipe-s))
:bind ((evil-snipe-scope 'buffer)
(evil-snipe-enable-highlight)
(evil-snipe-enable-incremental-highlight)))
(evilem-define "gS" 'evil-snipe-repeat-reverse
:pre-hook (save-excursion (call-interactively #'evil-snipe-s))
:bind ((evil-snipe-scope 'buffer)
(evil-snipe-enable-highlight)
(evil-snipe-enable-incremental-highlight)))
(setq doom--evil-snipe-repeat-fn
(evilem-create 'evil-snipe-repeat
:bind ((evil-snipe-scope 'whole-buffer)
(evil-snipe-enable-highlight)
(evil-snipe-enable-incremental-highlight)))))
(use-package evil-snipe
:init
(setq-default
evil-snipe-smart-case t
evil-snipe-repeat-keys nil ; using space to repeat
evil-snipe-scope 'line
evil-snipe-repeat-scope 'visible
evil-snipe-override-evil-repeat-keys nil ; causes problems with remapped ;
evil-snipe-char-fold t
evil-snipe-aliases '((?\[ "[[{(]")
(?\] "[]})]")
(?\; "[;:]")))
:config
(evil-snipe-mode 1)
(evil-snipe-override-mode 1)
(define-key evil-snipe-parent-transient-map (kbd "C-;") 'doom/evil-snipe-easymotion)
(def-repeat! evil-snipe-f evil-snipe-repeat evil-snipe-repeat-reverse)
(def-repeat! evil-snipe-F evil-snipe-repeat evil-snipe-repeat-reverse)
(def-repeat! evil-snipe-t evil-snipe-repeat evil-snipe-repeat-reverse)
(def-repeat! evil-snipe-T evil-snipe-repeat evil-snipe-repeat-reverse)
(def-repeat! evil-snipe-s evil-snipe-repeat evil-snipe-repeat-reverse)
(def-repeat! evil-snipe-S evil-snipe-repeat evil-snipe-repeat-reverse)
(def-repeat! evil-snipe-x evil-snipe-repeat evil-snipe-repeat-reverse)
(def-repeat! evil-snipe-X evil-snipe-repeat evil-snipe-repeat-reverse))
(use-package evil-surround
:commands (global-evil-surround-mode
evil-surround-edit
evil-Surround-edit
evil-surround-region)
:config
(global-evil-surround-mode 1))
(use-package evil-embrace
:after evil-surround
:config
(setq evil-embrace-show-help-p nil)
(evil-embrace-enable-evil-surround-integration)
(push (cons ?\\ (make-embrace-pair-struct
:key ?\\
:read-function 'doom/embrace-escaped
:left-regexp "\\[[{(]"
:right-regexp "\\[]})]"))
(default-value 'embrace--pairs-list))
(add-hook 'LaTeX-mode-hook 'embrace-LaTeX-mode-hook)
(add-hook 'org-mode-hook 'embrace-org-mode-hook)
(add-hook! emacs-lisp-mode
(embrace-add-pair ?\` "`" "'"))
(add-hook! (emacs-lisp-mode lisp-mode)
(embrace-add-pair-regexp ?f "([^ ]+ " ")" 'doom/embrace-elisp-fn))
(add-hook! (org-mode latex-mode)
(embrace-add-pair-regexp ?l "\\[a-z]+{" "}" 'doom/embrace-latex)))
(use-package evil-visualstar
:commands (global-evil-visualstar-mode
evil-visualstar/begin-search
evil-visualstar/begin-search-forward
evil-visualstar/begin-search-backward)
:config
(global-evil-visualstar-mode 1)
(def-repeat! evil-visualstar/begin-search-forward
evil-ex-search-next evil-ex-search-previous)
(def-repeat! evil-visualstar/begin-search-backward
evil-ex-search-previous evil-ex-search-next))
(use-package evil-escape
:config
(setq evil-escape-key-sequence "jk"
evil-escape-delay 0.25)
(push 'neotree-mode evil-escape-excluded-major-modes)
;; evil-escape causes noticable lag in commands that start with j, so we
;; enable it only where we need it.
(defun doom|evil-escape-disable () (evil-escape-mode -1))
(defun doom|evil-escape-enable () (evil-escape-mode +1))
(add-hook 'evil-insert-state-entry-hook 'doom|evil-escape-enable)
(add-hook 'evil-insert-state-exit-hook 'doom|evil-escape-disable)
(add-hook 'evil-replace-state-entry-hook 'doom|evil-escape-enable)
(add-hook 'evil-replace-state-exit-hook 'doom|evil-escape-disable))
;;
;; Autoloaded Packages
;;
(provide 'core-evil)
;;; core-evil.el ends here

View file

@ -1,180 +0,0 @@
;;; core-helm.el
(use-package helm
:init
(setq helm-quick-update t
;; Speedier without fuzzy matching
helm-mode-fuzzy-match nil
helm-buffers-fuzzy-matching nil
helm-apropos-fuzzy-match nil
helm-M-x-fuzzy-match nil
helm-recentf-fuzzy-match nil
helm-projectile-fuzzy-match nil
;; Display extraineous helm UI elements
helm-display-header-line nil
helm-ff-auto-update-initial-value nil
helm-find-files-doc-header nil
;; Don't override evil-ex's completion
helm-mode-handle-completion-in-region nil
helm-candidate-number-limit 50
;; Don't wrap item cycling
helm-move-to-line-cycle-in-source t)
:config
(defvar helm-global-prompt " ")
(map! "M-x" 'helm-M-x
"A-x" 'helm-M-x
"M-X" 'helm-apropos
"A-X" 'helm-apropos
"A-X" 'helm-apropos
"M-o" 'helm-find-files
(:map helm-map
"C-S-n" 'helm-next-source
"C-S-p" 'helm-previous-source
"C-u" 'helm-delete-minibuffer-contents
"C-w" 'backward-kill-word
"M-v" 'clipboard-yank
"C-r" 'evil-paste-from-register ; Evil registers in helm! Glorious!
"C-b" 'backward-word
"<left>" 'backward-char
"<right>" 'forward-char
"<escape>" 'helm-keyboard-quit
"ESC" 'helm-keyboard-quit
[escape] 'helm-keyboard-quit
"<tab>" 'helm-execute-persistent-action)
(:map* helm-generic-files-map
:e "ESC" 'helm-keyboard-quit))
;;; Popup setup
(def-popup! "\\` ?\\*[hH]elm.*?\\*\\'" :align below :size 14 :select t :regexp t)
;;; Helm hacks
(defconst doom-helm-header-fg (face-attribute 'helm-source-header :foreground))
;; Shrink source headers if there is only one source
(add-hook 'helm-after-initialize-hook 'doom*helm-hide-source-header-maybe)
;; A simpler prompt: see `helm-global-prompt'
(advice-add 'helm :filter-args 'doom*helm-replace-prompt)
;; Hide mode-line in helm windows
(advice-add 'helm-display-mode-line :override 'doom*helm-hide-header)
(require 'helm-mode)
(helm-mode +1))
(use-package helm-locate
:defer t
:init
(defvar helm-generic-files-map (make-sparse-keymap)
"Generic Keymap for files.")
:config (set-keymap-parent helm-generic-files-map helm-map))
(use-package helm-buffers
:commands (helm-buffers-list helm-mini)
:config (advice-add 'helm-buffer-list :override 'helm*buffer-list))
(use-package helm-tags
:commands (helm-tags-get-tag-file helm-etags-select))
(use-package helm-bookmark
:commands (helm-bookmarks helm-filtered-bookmarks)
:config (setq-default helm-bookmark-show-location t))
(use-package helm-projectile
:commands (helm-projectile-find-other-file
helm-projectile-switch-project
helm-projectile-find-file
helm-projectile-find-dir)
:init
(defvar helm-projectile-find-file-map (make-sparse-keymap))
:config
(set-keymap-parent helm-projectile-find-file-map helm-map)
(setq projectile-completion-system 'helm))
(use-package helm-files
:commands (helm-browse-project helm-find helm-find-files helm-for-files helm-multi-files helm-recentf)
:config
(map! :map helm-find-files-map
"C-w" 'helm-find-files-up-one-level
"TAB" 'helm-execute-persistent-action)
(mapc (lambda (r) (push r helm-boring-file-regexp-list))
(list "\\.projects$" "\\.DS_Store$")))
(use-package helm-ag
:commands (helm-ag
helm-ag-mode
helm-do-ag
helm-do-ag-this-file
helm-do-ag-project-root
helm-do-ag-buffers
helm-ag-project-root
helm-ag-pop-stack
helm-ag-buffers
helm-ag-clear-stack)
:config
(map! :map helm-ag-map
"<backtab>" 'helm-ag-edit
:map helm-ag-edit-map
"<escape>" 'helm-ag--edit-abort
:n "zx" 'helm-ag--edit-abort))
(use-package helm-css-scss ; https://github.com/ShingoFukuyama/helm-css-scss
:commands (helm-css-scss
helm-css-scss-multi
helm-css-scss-insert-close-comment)
:config
(setq helm-css-scss-split-direction 'split-window-vertically
helm-css-scss-split-with-multiple-windows t))
(use-package helm-swoop ; https://github.com/ShingoFukuyama/helm-swoop
:defines (helm-swoop-last-prefix-number)
:commands (helm-swoop helm-multi-swoop helm-multi-swoop-all)
:config
(setq helm-swoop-use-line-number-face t
helm-swoop-candidate-number-limit 200
helm-swoop-speed-or-color t
helm-swoop-pre-input-function (lambda () "")))
(use-package helm-describe-modes :commands helm-describe-modes)
(use-package helm-ring :commands helm-show-kill-ring)
(use-package helm-semantic :commands helm-semantic-or-imenu)
(use-package helm-elisp :commands helm-apropos)
(use-package helm-command :commands helm-M-x)
;; Popup hacks
(after! helm
;; This is a good alternative to either popwin or shackle, specifically for
;; helm. If either fail me (for the last time), this is where I'll turn.
;;(add-to-list 'display-buffer-alist
;; `(,(rx bos "*helm" (* not-newline) "*" eos)
;; (display-buffer-in-side-window)
;; (inhibit-same-window . t)
;; (window-height . 0.4)))
;; Helm tries to clean up after itself, but shackle has already done this.
;; This fixes that. To reproduce, add a helm rule in `shackle-rules', open two
;; splits side-by-side, move to the buffer on the right and invoke helm. It
;; will close all but the left-most buffer.
(setq-default helm-reuse-last-window-split-state t
helm-split-window-in-side-p t))
(after! helm-swoop
(setq helm-swoop-split-window-function (lambda (b) (doom/popup-buffer b))))
(after! helm-ag
;; This prevents helm-ag from switching between windows and buffers.
(defadvice helm-ag--edit-abort (around helm-ag-edit-abort-popup-compat activate)
(cl-letf (((symbol-function 'select-window) 'ignore)) ad-do-it)
(doom/popup-close nil t))
(defadvice helm-ag--edit-commit (around helm-ag-edit-commit-popup-compat activate)
(cl-letf (((symbol-function 'select-window) 'ignore)) ad-do-it)
(doom/popup-close nil t))
(defadvice helm-ag--edit (around helm-ag-edit-popup-compat activate)
(cl-letf (((symbol-function 'other-window) 'ignore)
((symbol-function 'switch-to-buffer) 'doom/popup-buffer))
ad-do-it)))
(provide 'core-helm)
;;; core-helm.el ends here

View file

@ -1,43 +0,0 @@
;;; core-ivy.el
;; see defuns/defuns-ivy.el
(use-package ivy
:init
(setq projectile-completion-system 'ivy
ivy-height 14
ivy-do-completion-in-region nil
ivy-wrap t
;; fontify until EOL
ivy-format-function 'ivy-format-function-line)
:config
(ivy-mode +1)
(map! :map ivy-minibuffer-map
[escape] 'keyboard-escape-quit
"C-r" 'evil-paste-from-register
"M-v" 'clipboard-yank
"C-w" 'backward-kill-word
"C-u" 'backward-kill-sentence
"C-b" 'backward-word
"C-f" 'forward-word)
(after! magit (setq magit-completing-read-function 'ivy-completing-read))
(after! smex (setq smex-completion-method 'ivy))
(after! yasnippet (push 'doom/yas-ivy-prompt yas-prompt-functions))
;;
(require 'counsel)
(add-hook! doom-popup-mode
(when (eq major-mode 'ivy-occur-grep-mode)
(ivy-wgrep-change-to-wgrep-mode)))
(advice-add 'counsel-ag-function :override 'doom*counsel-ag-function)
(define-key counsel-ag-map [backtab] 'doom/counsel-ag-occur)
(setq counsel-find-file-ignore-regexp "\\(?:^[#.]\\)\\|\\(?:[#~]$\\)\\|\\(?:^Icon?\\)"))
(use-package counsel-projectile :after projectile)
(provide 'core-ivy)
;;; core-ivy.el ends here

247
core/core-lib.el Normal file
View file

@ -0,0 +1,247 @@
;;; core-lib.el
(defmacro λ! (&rest body)
"A shortcut for inline keybind lambdas."
`(lambda () (interactive) ,@body))
(defmacro after! (feature &rest forms)
"A smart wrapper around `with-eval-after-load', that supresses warnings
during compilation."
(declare (indent defun) (debug t))
`(,(if (or (not (boundp 'byte-compile-current-file))
(not byte-compile-current-file)
(if (symbolp feature)
(require feature nil :no-error)
(load feature :no-message :no-error)))
'progn
(message "after: cannot find %s" feature)
'with-no-warnings)
(with-eval-after-load ',feature ,@forms)))
(defmacro add-hook! (hook &rest func-or-forms)
"A convenience macro for `add-hook'.
HOOK can be one hook or a list of hooks. If the hook(s) are not quoted, -hook is
appended to them automatically. If they are quoted, they are used verbatim.
FUNC-OR-FORMS can be a quoted symbol, a list of quoted symbols, or forms. Forms will be
wrapped in a lambda. A list of symbols will expand into a series of add-hook calls.
Examples:
(add-hook! 'some-mode-hook 'enable-something)
(add-hook! some-mode '(enable-something and-another))
(add-hook! '(one-mode-hook second-mode-hook) 'enable-something)
(add-hook! (one-mode second-mode) 'enable-something)
(add-hook! (one-mode second-mode) (setq v 5) (setq a 2))"
(declare (indent defun) (debug t))
(unless func-or-forms
(error "add-hook!: FUNC-OR-FORMS is empty"))
(let* ((val (car func-or-forms))
(quoted (eq (car-safe hook) 'quote))
(hook (if quoted (cadr hook) hook))
(funcs (if (eq (car-safe val) 'quote)
(if (cdr-safe (cadr val))
(cadr val)
(list (cadr val)))
(list func-or-forms)))
(forms '()))
(mapc (lambda (f)
(let ((func (if (symbolp f) `(quote ,f) `(lambda (&rest _) ,@func-or-forms))))
(mapc (lambda (h)
(push `(add-hook ',(if quoted h (intern (format "%s-hook" h))) ,func) forms))
(-list hook))))
funcs)
(macroexp-progn forms)))
;; TODO
(defmacro add-lambda-hook! (hooks func-name &rest forms))
;; TODO
(defmacro remove-hooks! (hooks &rest funcs))
(defmacro associate! (mode &rest rest)
"Associate a major or minor mode to certain patterns and project files."
(declare (indent 1))
(let ((minor (plist-get rest :minor))
(in (plist-get rest :in))
(match (plist-get rest :match))
(files (plist-get rest :files))
(pred (plist-get rest :when)))
`(progn
(,@(cond ((or files in pred)
(when (and files (not (or (listp files) (stringp files))))
(user-error "associate! :files expects a string or list of strings"))
(let ((hook-name (intern (format "doom--init-mode-%s" mode))))
`(progn
(defun ,hook-name ()
(when (and ,(if match `(if buffer-file-name (string-match-p ,match buffer-file-name)) t)
(or ,(not files)
(and (boundp ',mode)
(not ,mode)
(doom-project-has-files ,@(-list files))))
(or (not ,pred)
(funcall ,pred buffer-file-name)))
(,mode 1)))
,@(if (and in (listp in))
(mapcar (lambda (h) `(add-hook ',h ',hook-name))
(mapcar (lambda (m) (intern (format "%s-hook" m))) in))
`((add-hook 'find-file-hook ',hook-name))))))
(match
`(add-to-list ',(if minor 'doom-auto-minor-mode-alist 'auto-mode-alist)
(cons ,match ',mode)))
(t (user-error "associate! invalid rules for mode [%s] (in %s) (match %s) (files %s)"
mode in match files)))))))
;; Register keywords for proper indentation (see `map!')
(put ':prefix 'lisp-indent-function 'defun)
(put ':map 'lisp-indent-function 'defun)
(put ':map* 'lisp-indent-function 'defun)
(put ':after 'lisp-indent-function 'defun)
(put ':when 'lisp-indent-function 'defun)
(put ':unless 'lisp-indent-function 'defun)
(put ':leader 'lisp-indent-function 'defun)
(put ':localleader 'lisp-indent-function 'defun)
(defmacro map! (&rest rest)
"A nightmare of a key-binding macro that will use `evil-define-key',
`evil-define-key*', `define-key' and `global-set-key' depending on context and
plist key flags. It was designed to make binding multiple keys more concise,
like in vim.
Yes, it tries to do too much. Yes, I only did it to make the \"frontend\" config
that little bit more concise. Yes, I could simply have used the above functions.
But it takes a little insanity to custom write your own emacs.d, so what else
were you expecting?
States
:n normal
:v visual
:i insert
:e emacs
:o operator
:m motion
:r replace
:L local
These can be combined (order doesn't matter), e.g. :nvi will apply to
normal, visual and insert mode. The state resets after the following
key=>def pair.
Capitalize the state flag to make it a local binding.
If omitted, the keybind will be defined globally.
Flags
:unset [KEY] ; unset key
(:map [KEYMAP] [...]) ; apply inner keybinds to KEYMAP
(:map* [KEYMAP] [...]) ; apply inner keybinds to KEYMAP (deferred)
(:prefix [PREFIX] [...]) ; assign prefix to all inner keybindings
(:after [FEATURE] [...]) ; apply keybinds when [FEATURE] loads
Conditional keybinds
(:when [CONDITION] [...])
(:unless [CONDITION] [...])
Example
(map! :map magit-mode-map
:m \"C-r\" 'do-something ; assign C-r in motion state
:nv \"q\" 'magit-mode-quit-window ; assign to 'q' in normal and visual states
\"C-x C-r\" 'a-global-keybind
(:when IS-MAC
:n \"M-s\" 'some-fn
:i \"M-o\" (lambda (interactive) (message \"Hi\"))))"
(let ((keymaps (if (boundp 'keymaps) keymaps))
(defer (if (boundp 'defer) defer))
(prefix (if (boundp 'prefix) prefix))
(state-map '(("n" . normal)
("v" . visual)
("i" . insert)
("e" . emacs)
("o" . operator)
("m" . motion)
("r" . replace)))
local key def states forms)
(while rest
(setq key (pop rest))
(push
(reverse
(cond
;; it's a sub expr
((listp key)
`(,(macroexpand `(map! ,@key))))
;; it's a flag
((keywordp key)
(when (cond ((eq key :leader)
(push doom-evil-leader rest))
((eq key :localleader)
(push doom-evil-localleader rest)))
(setq key :prefix))
(pcase key
(:prefix (setq prefix (concat prefix (kbd (pop rest)))) nil)
(:map (setq keymaps (-list (pop rest))) nil)
(:map* (setq defer t keymaps (-list (pop rest))) nil)
(:unset `(,(macroexpand `(map! ,(kbd (pop rest)) nil))))
(:after (prog1 `((after! ,(pop rest) ,(macroexpand `(map! ,@rest)))) (setq rest '())))
(:when (prog1 `((if ,(pop rest) ,(macroexpand `(map! ,@rest)))) (setq rest '())))
(:unless (prog1 `((if (not ,(pop rest)) ,(macroexpand `(map! ,@rest)))) (setq rest '())))
(otherwise ; might be a state prefix
(mapc (lambda (letter)
(cond ((assoc letter state-map)
(push (cdr (assoc letter state-map)) states))
((string= letter "L")
(setq local t))
(t (user-error "Invalid mode prefix %s in key %s" letter key))))
(split-string (substring (symbol-name key) 1) "" t))
(unless states
(user-error "Unrecognized keyword %s" key))
(when (assoc "L" states)
(cond ((= (length states) 1)
(user-error "local keybinding for %s must accompany another state" key))
((> (length keymaps) 0)
(user-error "local keybinding for %s cannot accompany a keymap" key))))
nil)))
;; It's a key-def pair
((or (stringp key)
(characterp key)
(vectorp key))
(when (stringp key)
(setq key (kbd key)))
(when prefix
(setq key (cond ((vectorp key) (vconcat prefix key))
(t (concat prefix key)))))
(unless (> (length rest) 0)
(user-error "Map has no definition for %s" key))
(setq def (pop rest))
(let (out-forms)
(cond ((and keymaps states)
(mapc (lambda (keymap)
(push `(,(if defer 'evil-define-key 'evil-define-key*)
',states ,keymap ,key ,def)
out-forms))
keymaps))
(keymaps
(mapc (lambda (keymap) (push `(define-key ,keymap ,key ,def) out-forms))
keymaps))
(states
(mapc (lambda (state)
(push `(define-key
(evil-state-property ',state ,(if local :local-keymap :keymap) t)
,key ,def)
out-forms))
states))
(t (push `(,(if local 'local-set-key 'global-set-key)
,key ,def)
out-forms)))
(setq states '()
local nil)
out-forms))
(t (user-error "Invalid key %s" key))))
forms))
`(progn ,@(apply #'nconc (delete nil (delete (list nil) (reverse forms)))))))
(provide 'core-lib)
;;; core-lib.el ends here

View file

@ -1,6 +1,6 @@
;;; core-modeline.el
;;; core-modeline.el --- make mode-lines sexy again
;; This file tries to be an almost self-contained configuration of my mode-line.
;; This file tries to be a self-contained configuration of my mode-line.
;;; These are the invisible dependencies
;; Required
@ -17,22 +17,25 @@
;;(require 'iedit)
;;(require 'evil-multiedit)
(require 'powerline)
(require 'all-the-icons)
(package! powerline)
(package! all-the-icons :demand t)
(package! eldoc-eval :demand t
:config
(setq eldoc-in-minibuffer-show-fn 'doom-eldoc-show-in-mode-line)
(eldoc-in-minibuffer-mode +1))
;; all-the-icons doesn't work in the terminal, so we "disable" it.
(unless window-system
(defun all-the-icons-octicon (&rest _) "" "")
(defun all-the-icons-faicon (&rest _) "" "")
(defun all-the-icons-fileicon (&rest _) "" "")
(defun all-the-icons-wicon (&rest _) "" "")
(defun all-the-icons-alltheicon (&rest _) "" ""))
;;
;; Variables
;;
(defvar doom-modeline-formats '()
"")
(defvar doom-modeline-height 29
"How tall the mode-line should be (only respected in GUI emacs).")
@ -44,30 +47,37 @@
;; Custom faces
;;
(defface doom-modeline-buffer-path '((t (:inherit mode-line :bold t)))
(defface doom-modeline-buffer-path
'((t (:inherit mode-line :bold t)))
"Face used for the dirname part of the buffer path.")
(defface doom-modeline-buffer-project
'((t (:inherit doom-modeline-buffer-path :bold nil)))
"Face used for the filename part of the mode-line buffer path.")
(defface doom-modeline-buffer-modified '((t (:inherit highlight :background nil)))
(defface doom-modeline-buffer-modified
'((t (:inherit highlight :background nil)))
"Face used for the 'unsaved' symbol in the mode-line.")
(defface doom-modeline-buffer-major-mode '((t (:inherit mode-line :bold t)))
(defface doom-modeline-buffer-major-mode
'((t (:inherit mode-line :bold t)))
"Face used for the major-mode segment in the mode-line.")
(defface doom-modeline-highlight '((t (:inherit mode-line)))
(defface doom-modeline-highlight
'((t (:inherit mode-line)))
"Face for bright segments of the mode-line.")
(defface doom-modeline-panel '((t (:inherit mode-line)))
(defface doom-modeline-panel
'((t (:inherit mode-line)))
"Face for 'X out of Y' segments, such as `*anzu', `*evil-substitute' and
`iedit'")
(defface doom-modeline-info `((t (:inherit success)))
(defface doom-modeline-info
`((t (:inherit success)))
"Face for info-level messages in the modeline. Used by `*vc'.")
(defface doom-modeline-warning `((t (:inherit warning)))
(defface doom-modeline-warning
`((t (:inherit warning)))
"Face for warnings in the modeline. Used by `*flycheck'")
(defface doom-modeline-urgent `((t (:inherit error)))
@ -86,37 +96,41 @@ active.")
;;
;; Functions
;; Bootstrap
;;
;; Where (py|rb)env version strings will be stored
(defvar-local doom-ml--env-version nil)
(defvar-local doom-ml--env-command nil)
;; all-the-icons doesn't work in the terminal, so we "disable" it.
(unless window-system
(defun all-the-icons-octicon (&rest _) "" "")
(defun all-the-icons-faicon (&rest _) "" "")
(defun all-the-icons-fileicon (&rest _) "" "")
(defun all-the-icons-wicon (&rest _) "" "")
(defun all-the-icons-alltheicon (&rest _) "" ""))
(add-hook 'focus-in-hook 'doom-ml|env-update)
(add-hook 'find-file-hook 'doom-ml|env-update)
(defmacro modeline! (name &rest def)
(declare (indent defun))) ;; TODO
(defun doom-ml|env-update ()
"Update (py|rb)env version string in `doom-ml--env-version', generated with
`doom-ml--env-command'."
(when doom-ml--env-command
(let* ((default-directory (doom/project-root))
(defvar-local doom-modeline-env-version nil)
(defvar-local doom-modeline-env-command nil)
(add-hook 'focus-in-hook 'doom-modeline|update-env)
(add-hook 'find-file-hook 'doom-modeline|update-env)
(defun doom-modeline|update-env ()
(when doom-modeline-env-command
(let* ((default-directory (doom-project-root))
(s (shell-command-to-string doom-ml--env-command)))
(setq doom-ml--env-version (if (string-match "[ \t\n\r]+\\'" s)
(setq doom-modeline-env-version (if (string-match "[ \t\n\r]+\\'" s)
(replace-match "" t t s)
s)))))
(defmacro def-version-cmd! (mode command)
"Define a COMMAND for MODE that will set `doom-ml--env-command' when that mode
is activated, which should return the version number of the current environment.
It is used by `doom-ml|env-update' to display a version number in the modeline.
For instance:
(doom-define-setting 'env
"Command used to set the interpreter version in the current buffer."
:type '(stringp functionp)
:hook (lambda (command) (setq doom-modeline-env-command x)))
(def-version-cmd! ruby-mode \"ruby --version | cut -d' ' -f2\")
;; (set! python-mode :env "python --version 2>&1 | cut -d' ' -f2")
;; (set! ruby-mode :env "ruby --version 2>&1 | cut -d' ' -f2")
This will display the ruby version in the modeline in ruby-mode buffers. It is
cached the first time."
`(add-hook ',mode (lambda () (setq doom-ml--env-command ,command))))
(defsubst active() (eq (selected-window) powerline-selected-window))
(defun doom-ml-flycheck-count (state)
"Return flycheck information for the given error type STATE."
@ -127,6 +141,9 @@ cached the first time."
(defun doom-make-xpm (color height width)
"Create an XPM bitmap."
(unless (featurep 'powerline)
(require 'powerline)
(pl/memoize 'doom-make-xpm))
(when window-system
(propertize
" " 'display
@ -140,7 +157,7 @@ cached the first time."
project root). Excludes the file basename. See `doom-buffer-name' for that."
(if buffer-file-name
(let* ((default-directory (f-dirname buffer-file-name))
(buffer-path (f-relative buffer-file-name (doom/project-root)))
(buffer-path (f-relative buffer-file-name (doom-project-root)))
(max-length (truncate (* (window-body-width) 0.4))))
(when (and buffer-path (not (equal buffer-path ".")))
(if (> (length buffer-path) max-length)
@ -159,16 +176,35 @@ project root). Excludes the file basename. See `doom-buffer-name' for that."
buffer-path)))
"%b"))
(defsubst active () (eq (selected-window) powerline-selected-window))
;; Memoize for optimization
(pl/memoize 'doom-make-xpm)
(pl/memoize 'face-background)
(pl/memoize 'all-the-icons-octicon)
(defun doom-eldoc-show-in-mode-line (input)
"Display string STR in the mode-line next to minibuffer."
(with-current-buffer (eldoc-current-buffer)
(let* ((max (window-width (selected-window)))
(str (and (stringp input) (concat " " input)))
(len (length str))
(tmp-str str)
(mode-line-format (or (and str (doom-eldoc-modeline))
mode-line-format))
roll mode-line-in-non-selected-windows)
(catch 'break
(if (and (> len max) eldoc-mode-line-rolling-flag)
(progn
(while (setq roll (sit-for 0.3))
(setq tmp-str (substring tmp-str 2)
mode-line-format (concat tmp-str " [<]" str))
(force-mode-line-update)
(when (< (length tmp-str) 2) (setq tmp-str str)))
(unless roll
(when eldoc-mode-line-stop-rolling-on-input
(setq eldoc-mode-line-rolling-flag nil))
(throw 'break nil)))
(force-mode-line-update)
(sit-for eldoc-show-in-mode-line-delay))))
(force-mode-line-update)))
;;
;; Mode-line segments
;; Segments
;;
(defun *buffer-project ()
@ -179,7 +215,7 @@ project root). Excludes the file basename. See `doom-buffer-name' for that."
:face face
:v-adjust -0.05
:height 1.25)
(propertize (concat " " (abbreviate-file-name (doom/project-root)))
(propertize (concat " " (abbreviate-file-name (doom-project-root)))
'face face))))
(defun *buffer-info ()
@ -230,7 +266,7 @@ directory, the file name, and its state (modified, read-only or non-existent)."
(propertize
(concat (format-mode-line mode-name)
(if (stringp mode-line-process) mode-line-process)
(if doom-ml--env-version (concat " " doom-ml--env-version))
(if doom-modeline-env-version (concat " " doom-modeline-env-version))
(and (featurep 'face-remap)
(/= text-scale-mode-amount 0)
(format " (%+d)" text-scale-mode-amount)))
@ -411,11 +447,13 @@ lines are selected, or the NxM dimensions of a block selection."
(let ((size (image-size (image-get-display-property) :pixels)))
(format " %dx%d " (car size) (cdr size))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun doom-modeline (&optional id)
`(:eval
(let* ((meta (concat (*macro-recording)
;;
;; Mode lines
;;
(doom-modeline-define 'main
`(let* ((meta (concat (*macro-recording)
(*anzu)
(*evil-substitute)
(*iedit)))
@ -424,83 +462,44 @@ lines are selected, or the NxM dimensions of a block selection."
'doom-modeline-inactive-bar))
doom-modeline-height
doom-modeline-bar-width)
,(unless (eq id 'scratch)
'(if (and (= (length meta) 0)
(not doom-ediff-enabled))
" %I "
meta))
(if (= (length meta) 0) " %I " meta)
" "
,(cond ((eq id 'scratch)
'(*buffer-project))
((eq id 'media)
'(*media-info))
(t
'(list (*buffer-info)
(*buffer-info)
" %l:%c %p "
(*selection-info)
)))))
(rhs ,(if id
'(list (*major-mode))
'(list (*buffer-encoding)
(*selection-info)))
(rhs (list (*buffer-encoding)
(*vc)
(*major-mode)
(*flycheck)
)))
(*flycheck)))
(mid (propertize
" " 'display `((space :align-to (- (+ right right-fringe right-margin)
,(+ 1 (string-width (format-mode-line rhs)))))))))
(list lhs mid rhs))))
(list lhs mid rhs)))
(setq-default mode-line-format (doom-modeline))
(add-hook! image-mode
(setq mode-line-format (doom-modeline 'media)))
;;
;; Eldoc-in-mode-line support (for `eval-expression')
;;
(defun doom-eldoc-modeline ()
`(:eval
(list (list ,(when window-system
(doom-modeline-define 'eldoc
`(list (list ,(when window-system
`(doom-make-xpm (face-background 'doom-modeline-eldoc-bar)
doom-modeline-height
doom-modeline-bar-width))
(and (bound-and-true-p str) str))
(propertize " " 'display `((space :align-to (1- (+ right right-fringe right-margin))))))))
(propertize " " 'display `((space :align-to (1- (+ right right-fringe right-margin)))))))
(defun doom-eldoc-show-in-mode-line (input)
"Display string STR in the mode-line next to minibuffer."
(with-current-buffer (eldoc-current-buffer)
(let* ((max (window-width (selected-window)))
(str (and (stringp input) (concat " " input)))
(len (length str))
(tmp-str str)
(mode-line-format (or (and str (doom-eldoc-modeline))
mode-line-format))
roll mode-line-in-non-selected-windows)
(catch 'break
(if (and (> len max) eldoc-mode-line-rolling-flag)
(progn
(while (setq roll (sit-for 0.3))
(setq tmp-str (substring tmp-str 2)
mode-line-format (concat tmp-str " [<]" str))
(force-mode-line-update)
(when (< (length tmp-str) 2) (setq tmp-str str)))
(unless roll
(when eldoc-mode-line-stop-rolling-on-input
(setq eldoc-mode-line-rolling-flag nil))
(throw 'break nil)))
(force-mode-line-update)
(sit-for eldoc-show-in-mode-line-delay))))
(force-mode-line-update)))
(doom-modeline-define 'minimal
`(let* ((lhs (list (doom-make-xpm (face-background (if (active)
'doom-modeline-bar
'doom-modeline-inactive-bar))
doom-modeline-height
doom-modeline-bar-width)
" "
(*buffer-project)))
(rhs (list (*major-mode)))
(mid (propertize
" " 'display `((space :align-to (- (+ right right-fringe right-margin)
,(+ 1 (string-width (format-mode-line rhs)))))))))
(list lhs mid rhs)))
;; Show eldoc in the mode-line when using `eval-expression'.
(use-package eldoc-eval
:config
(setq eldoc-in-minibuffer-show-fn 'doom-eldoc-show-in-mode-line)
(eldoc-in-minibuffer-mode +1))
;;
(setq-default mode-line-format (assq 'main doom-modeline-formats))
(provide 'core-modeline)
;;; core-modeline.el ends here

View file

@ -1,48 +0,0 @@
;;; core-os-linux.el --- Debian-specific settings
(setq x-super-keysym 'alt
x-meta-keysym 'meta)
(defun doom-open-with (command &rest args)
"Open PATH in APP-NAME, using xdg-open."
(interactive)
(unless args
(setq args (f-full (s-replace "'" "\\'"
(or path (if (eq major-mode 'dired-mode)
(dired-get-file-for-visit)
(buffer-file-name)))))))
(let ((command (apply 'format command
(mapcar (lambda (a) (shell-quote-argument a))
args))))
(message "Running: %s" command)
(shell-command command)))
;;
;; OS-specific functions
;;
(defun os-open-in-browser ()
"Open the current file in the browser."
(interactive)
(browse-url buffer-file-name))
(defun os-open-in-default-program ()
"Open the current file (or selected file in dired) with xdg-open."
(interactive)
(doom-open-with "xdg-open '%s'"))
;;
;; Plugins
;;
(use-package openwith
:config
(openwith-mode t)
(setq openwith-associations
'(("\\.\\(pdf\\|jpe?g\\|gif\\|docx?\\|pptx?\\|xlsx?\\|zip\\|tar\\(\\.gz\\)?\\|rar\\)$"
"xdg-open" (file)))))
(provide 'core-os-linux)
;;; core-os-linux.el ends here

View file

@ -1,126 +0,0 @@
;;; core-os-osx.el --- Mac-specific settings
(global-set-key (kbd "M-q") 'kill-emacs)
(setq ;; Prefixes: Command = M, Alt = A
mac-command-modifier 'meta
mac-option-modifier 'alt
;; sane trackpad/mouse scroll settings
mac-redisplay-dont-reset-vscroll t
mac-mouse-wheel-smooth-scroll nil
mouse-wheel-scroll-amount '(5 ((shift) . 2)) ; one line at a time
mouse-wheel-progressive-speed nil ; don't accelerate scrolling
;; Curse Lion and its sudden but inevitable fullscreen mode!
;; NOTE Meaningless to railwaycat's emacs-mac build
ns-use-native-fullscreen nil
;; Don't open files from the workspace in a new frame
ns-pop-up-frames nil)
;; On OSX, in GUI Emacs, `exec-path' isn't populated properly (it should match
;; $PATH in my shell). `exe-path-from-shell' fixes this.
(when window-system
(setenv "SHELL" "/usr/local/bin/zsh")
;; `exec-path-from-shell' is slow, so bring out the cache
(setq exec-path
(eval-when-compile
(require 'exec-path-from-shell)
(exec-path-from-shell-initialize)
exec-path)))
;; Enable mouse support in terminal
(unless window-system
(require 'mouse)
(xterm-mouse-mode t)
(global-set-key [mouse-4] (λ! (scroll-down 4)))
(global-set-key [mouse-5] (λ! (scroll-up 4)))
(defun track-mouse (e))
(setq mouse-sel-mode t))
;;
;; OSX-related plugins + hacks
;;
(use-package applescript-mode
:mode "\\.applescript$"
:init (add-hook 'applescript-mode-hook 'nlinum-mode)
:config
(def-docset! applescript-mode "applescript")
(after! quickrundb
(quickrun-add-command
"applescript" `((:command . ,as-osascript-command)
(:cmdopt . "-ss %s")
(:description . "Run applescript"))
:mode 'applescript-mode)))
(def-project-type! lb6 "lb6"
:match "\\.lb\\(action\\|ext\\)/.+$"
:build (lambda ()
(awhen (f-traverse-upwards (lambda (f) (f-ext? f "lbaction")))
(shell-command (format "open '%s'" it)))))
(after! evil
;; On OSX, stop copying each visual state move to the clipboard:
;; https://bitbucket.org/lyro/evil/issue/336/osx-visual-state-copies-the-region-on
;; Most of this code grokked from:
;; http://stackoverflow.com/questions/15873346/elisp-rename-macro
(when (or (featurep 'mac) (featurep 'ns))
(advice-add 'evil-visual-update-x-selection :override 'ignore)))
;;
;; OS-specific functions
;;
(defun doom-open-with (&optional app-name path)
"Send PATH to APP-NAME on OSX."
(interactive)
(let* ((path (f-full (s-replace "'" "\\'"
(or path (if (eq major-mode 'dired-mode)
(dired-get-file-for-visit)
(buffer-file-name))))))
(command (format "open %s"
(if app-name
(format "-a %s '%s'" (shell-quote-argument app-name) path)
(format "'%s'" path)))))
(message "Running: %s" command)
(shell-command command)))
(defmacro def-open-with! (id &optional app dir)
`(defun ,(intern (format "os-%s" id)) ()
(interactive)
(doom-open-with ,app ,dir)))
(def-open-with! open-in-default-program)
(def-open-with! open-in-browser "Google Chrome")
(def-open-with! reveal "Finder" default-directory)
(def-open-with! reveal-project "Finder" (doom/project-root))
(def-open-with! upload "Transmit")
(def-open-with! upload-folder "Transmit" default-directory)
(def-open-with! send-to-launchbar "LaunchBar")
(def-open-with! send-project-to-launchbar "LaunchBar" (doom/project-root))
(defun os-switch-to-term ()
(interactive)
(do-applescript "tell application \"iTerm\" to activate"))
(defun os-switch-to-term-and-cd ()
(interactive)
(doom:send-to-tmux (format "cd %s" (shell-quote-argument default-directory)))
(doom-switch-to-iterm))
;;
;; Plugins
;;
(use-package openwith
:config
(openwith-mode t)
(setq openwith-associations
'(("\\.\\(pdf\\|jpe?g\\|gif\\|docx?\\|pptx?\\|xlsx?\\|zip\\|tar\\(\\.gz\\)?\\|rar\\)$"
"open" (file)))))
(provide 'core-os-osx)
;;; core-os-osx.el ends here

View file

@ -1,8 +0,0 @@
;;; core-os-win32.el --- Windows-specific settings
(defun doom-open-with (&optional app-name path)
(interactive)
(error "Not yet implemented"))
(provide 'core-os-win32)
;;; core-os-win32.el ends here

View file

@ -1,28 +1,59 @@
;;; core-os.el
;;; core-os.el --- consistent behavior across OSes
(defconst IS-MAC (eq system-type 'darwin))
(defconst IS-LINUX (eq system-type 'gnu/linux))
(defconst IS-WINDOWS (eq system-type 'windows-nt))
(setq
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)
;; Use a shared clipboard
x-select-enable-clipboard t
select-enable-clipboard t
;; Treat clipboard input as UTF-8 string first; compound text next, etc.
x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))
select-enable-primary t)
;; Stubs, these should be defined in all OS modules
(noop! doom-open-with (&optional app-name path))
(noop! os-open-in-browser)
(noop! os-open-in-default-program)
(noop! os-reveal)
(noop! os-reveal-project)
(noop! os-switch-to-term)
(noop! os-switch-to-term-and-cd)
(cond (IS-MAC (require 'core-os-osx))
(IS-LINUX (require 'core-os-linux))
(IS-WINDOWS (require 'core-os-win32)))
;;;
;; OS-specific configs
(cond (IS-MAC
;; Prefixes: Command = M, Alt = A
(setq mac-command-modifier 'meta
mac-option-modifier 'alt
;; sane trackpad/mouse scroll settings
mac-redisplay-dont-reset-vscroll t
mac-mouse-wheel-smooth-scroll nil
mouse-wheel-scroll-amount '(5 ((shift) . 2)) ; one line at a time
mouse-wheel-progressive-speed nil ; don't accelerate scrolling
;; Curse Lion and its sudden but inevitable fullscreen mode!
;; NOTE Meaningless to railwaycat's emacs-mac build
ns-use-native-fullscreen nil
;; Don't open files from the workspace in a new frame
ns-pop-up-frames nil)
;; On OSX, in GUI Emacs, `exec-path' isn't populated properly (it should
;; match $PATH in my shell). `exe-path-from-shell' fixes this.
(package! exec-path-from-shell)
(when (display-graphic-p)
(setenv "SHELL" "/usr/local/bin/zsh")
;; `exec-path-from-shell' is slow, so bring out the cache
(setq exec-path
(or (persistent-soft-fetch 'exec-path "emacs")
(persistent-soft-store
'exec-path
(progn
(require 'exec-path-from-shell)
(exec-path-from-shell-initialize)
exec-path)
"emacs"))))
(after! evil
;; On OSX, stop copying each visual state move to the clipboard:
;; https://bitbucket.org/lyro/evil/issue/336/osx-visual-state-copies-the-region-on
;; Most of this code grokked from:
;; http://stackoverflow.com/questions/15873346/elisp-rename-macro
(when (or (featurep 'mac) (featurep 'ns))
(advice-add 'evil-visual-update-x-selection :override 'ignore))))
(IS-LINUX
(setq x-super-keysym 'meta
x-meta-keysym 'alt)))
(provide 'core-os)
;;; core-os.el ends here

211
core/core-packages.el Normal file
View file

@ -0,0 +1,211 @@
;;; core-packages.el
;; Emacs has always been opinionated about package management. Unfortunately, so
;; have I. I used to use Cask, but found it very unreliable, so the result is
;; this: a mini-package manager I've written by combining the functionality of
;; package.el, quelpa and use-package.
;;
;; Why all the trouble? Because I want to be able to call an
;; 'update-all-packages' function from a shell script and the like. I want to be
;; able to manage my Emacs' packages from the command line, because I have tools
;; in my dotfiles to help me auto-update everything with a one-liner.
(defvar doom-init nil
"Whether doom's package system has been initialized or not. It may not be if
you have byte-compiled your configuration (as intended).")
(defvar doom-packages '(quelpa-use-package)
"List of enabled packages.")
(defvar doom-modules nil
"List of installed modules.")
(defvar doom-packages-auto-p (not noninteractive)
"")
(defvar doom--load-path load-path
"A backup of `load-path' before it was initialized.")
(setq load-prefer-newer nil
package--init-file-ensured t
package-user-dir (expand-file-name "elpa" doom-packages-dir)
package-enable-at-startup nil
package-archives
'(("gnu" . "http://elpa.gnu.org/packages/")
("melpa" . "http://melpa.org/packages/")
("org" . "http://orgmode.org/elpa/"))
use-package-always-ensure t
use-package-always-defer t
quelpa-checkout-melpa-p nil
quelpa-update-melpa-p nil
quelpa-dir (expand-file-name "quelpa" doom-packages-dir))
;;
;; Bootstrap
;;
(autoload 'use-package "use-package")
(defun doom-package-init (&optional force-p)
"Initialize DOOM, its essential packages and package.el. This must be used on
first run. If you byte compile core/core.el, this file is avoided to speed up
startup."
(when (or (not doom-init) force-p)
(package-initialize)
(unless (file-exists-p package-user-dir)
(package-refresh-contents))
(unless (package-installed-p 'quelpa-use-package)
(package-install 'quelpa-use-package t))
(require 'quelpa)
(require 'use-package)
(when doom-packages-auto-p
(setq use-package-always-ensure t)
(require 'quelpa-use-package)
(quelpa-use-package-activate-advice))
(add-to-list 'load-path doom-modules-dir)
(add-to-list 'load-path doom-private-dir)
(add-to-list 'load-path doom-core-dir)
(setq doom-init t)))
(defmacro package! (name &rest rest)
"Declare a package. Wraps around `use-package', and takes the same arguments
that it does."
(declare (indent defun))
(add-to-list 'doom-packages name)
(unless doom-packages-auto-p
(when (and (plist-member rest :ensure)
(plist-get rest :ensure))
(setq rest (plist-put rest :ensure nil)))
(when (plist-member rest :quelpa)
(use-package-plist-delete rest :quelpa)))
(macroexpand-all `(use-package ,name ,@rest)))
(defmacro load-internal! (module package)
)
(defmacro load! (plugin)
)
;;
;; Commands
;;
(defun doom-package-outdated-p (package &optional inhibit-refresh)
"Determine whether PACKAGE (a symbol) is outdated or not. If INHIBIT-REFRESH
is non-nil, don't run `package-refresh-contents' (which is slow. Use for batch
processing, and run `package-refresh-contents' once, beforehand)."
(unless inhibit-refresh
(package-refresh-contents))
(when (and (package-installed-p package)
(cadr (assq package package-archive-contents)))
(let* ((newest-desc (cadr (assq package package-archive-contents)))
(installed-desc (cadr (or (assq package package-alist)
(assq package package--builtins))))
(newest-version (package-desc-version newest-desc))
(installed-version (package-desc-version installed-desc)))
(not (version-list-<= newest-version installed-version)))))
(defun doom/packages-reload ()
"Reload DOOM Emacs. This includes the `load-path'"
(interactive)
(setq load-path doom--load-path)
(doom-package-init t)
(when (called-interactively-p 'interactive)
(message "Reloaded %s packages" (length package-alist))))
(defun doom/packages-install ()
"Activate `doom-packages-auto-p' and evaluation your emacs configuration
again, in order to auto-install all packages that are missing."
(interactive)
(setq doom-packages-auto-p t)
(doom-package-init t)
(load (expand-file-name "init.el" doom-emacs-dir) nil nil t))
(defun doom/packages-update ()
"Update all installed packages. This includes quelpa itself, quelpa-installed
packages, and ELPA packages."
(interactive)
(doom-package-init t)
(quelpa-upgrade) ; upgrade quelpa + quelpa-installed packages
(package-refresh-contents) ; ...then packages.el
(mapc (lambda (package)
(condition-case ex
(let ((desc (cadr (assq package package-alist))))
(delete-directory (package-desc-dir desc) t)
(package-install-from-archive (cadr (assoc package package-archive-contents))))
('error (message "ERROR: %s" ex)))) ;; TODO
(-uniq (--filter (or (assq it quelpa-cache)
(doom-package-outdated-p it t))
(package--find-non-dependencies)))))
(defun doom/packages-clean ()
"Delete unused packages."
(interactive)
(doom-package-init t)
(let* ((package-selected-packages (-intersection (package--find-non-dependencies) doom-packages))
(packages-to-delete (package--removable-packages))
quelpa-modified-p)
(cond ((not package-selected-packages)
(message "No packages installed!"))
((not packages-to-delete)
(message "No unused packages to remove."))
((not (y-or-n-p
(format "%s packages will be deleted:\n%s\n\nProceed?"
(length packages-to-delete)
(mapconcat 'symbol-name (reverse packages-to-delete) ", "))))
(message "Aborted."))
(t
(dolist (package packages-to-delete)
(package-delete package t)
(when (assq package quelpa-cache)
(setq quelpa-cache (assq-delete-all package quelpa-cache)
quelpa-modified-p t)))
(when quelpa-modified-p
(quelpa-save-cache))))))
(defun doom/byte-compile ()
"Byte (re)compile the important files in your emacs configuration. No more no
less."
(interactive)
(doom-package-init)
(mapc 'byte-compile-file
(append (list (expand-file-name "init.el" doom-emacs-dir)
(expand-file-name "core.el" doom-core-dir))
(reverse
(file-expand-wildcards
(expand-file-name "core*.el" doom-core-dir)))
(file-expand-wildcards
(expand-file-name "*/*/packages.el" doom-modules-dir)))))
(defun doom/refresh-autoloads (&optional inhibit-require)
"Refreshes your emacs config's autoloads file. Use this if you modify an
autoload.el file in any module."
(interactive)
(let ((generated-autoload-file (concat doom-modules-dir "autoloads.el"))
(interactive-p (called-interactively-p 'interactive))
(autoload-files
(file-expand-wildcards
(expand-file-name "*/*/autoload.el" doom-modules-dir))))
(when (file-exists-p generated-autoload-file)
(delete-file generated-autoload-file)
(when interactive-p (message "Deleted old autoloads.el")))
(dolist (file autoload-files)
(update-file-autoloads file t)
(when interactive-p
(message "Detected: %s"
(file-relative-name (directory-file-name parent)
doom-emacs-dir))))
(when interactive-p (message "Done!"))
(with-demoted-errors "WARNING: %s"
(load "autoloads"))))
(provide 'core-packages)
;;; core-packages.el ends here

View file

@ -1,159 +0,0 @@
;;; core-popup.el --- taming stray windows
;; I use a slew of hackery to get Emacs to treat 'pop-ups' consistently. It goes
;; through great lengths to tame helm, flycheck, help buffers--*even* the beast
;; that is org-mode, with the help of `display-buffer-alist' and shackle.
;;
;; Be warned, an update could break this.
(use-package shackle
:config
(shackle-mode 1)
(setq shackle-rules
`(;; Util
("^\\*.+-Profiler-Report .+\\*$" :align below :size 0.3 :regexp t)
("*esup*" :align below :size 0.4 :noselect t)
("*minor-modes*" :align below :size 0.5 :noselect t)
("*eval*" :align below :size 16 :noselect t)
;; Doom
(" *doom*" :align below :size 35 :select t)
("^\\*doom:.+\\*$" :align below :size 35 :select t :regexp t)
("^\\*doom.+\\*$" :align below :size 12 :noselect t :regexp t)
;; Emacs
("*Pp Eval Output*" :align below :size 0.3)
("*Apropos*" :align below :size 0.3)
("*Backtrace*" :align below :size 25 :noselect t)
("*Help*" :align below :size 16 :select t)
("*Messages*" :align below :size 15 :select t)
("*Warnings*" :align below :size 10 :noselect t)
(compilation-mode :align below :size 15 :noselect t)
(eww-mode :align below :size 30 :select t)
("*command-log*" :align right :size 28 :noselect t)
;; vcs
("*vc-diff*" :align below :size 15 :noselect t)
("*vc-change-log*" :align below :size 15 :select t)
(vc-annotate-mode :same t)))
;; Emacs 25.1+ properly shows the completion window at the bottom of the
;; current frame.
(unless (version< emacs-version "25.1")
(push '("*Completions*" :align below :size 30 :noselect t) shackle-rules))
;; :noesc = Can't be closed with a single ESC
;; :nokill = Won't be killed when closed (only buried)
(defvar doom-popup-rules
'(("^\\*doom\\(:scratch\\)?\\*$" :noesc :nokill)
("^\\*doom.*\\*$" :noesc :nokill)
(ivy-occur-grep-mode :noesc)
(compilation-mode :noesc)
(comint-mode :noesc :nokill)
(eshell-mode :noesc :nokill)
(messages-buffer-mode :nokill)
(esup-mode :noesc)
(tabulated-list-mode :noesc)))
;; There is no shackle-popup hook, so I created one:
(advice-add 'shackle-display-buffer :around 'doom*popup-init)
;; Tell these functions not to mess with popups:
(advice-add 'balance-windows :around 'doom*save-neotree)
(advice-add 'balance-windows :around 'doom*save-popup)
(advice-add 'doom/evil-window-move :around 'doom*save-popup)
(advice-add 'evil-window-move-very-bottom :around 'doom*save-popup)
(advice-add 'evil-window-move-very-top :around 'doom*save-popup)
(advice-add 'evil-window-move-far-left :around 'doom*save-popup)
(advice-add 'evil-window-move-far-right :around 'doom*save-popup)
(advice-add 'evil-window-move-very-bottom :around 'doom*save-neotree)
(advice-add 'evil-window-move-very-top :around 'doom*save-neotree)
(advice-add 'evil-window-move-far-left :around 'doom*save-neotree)
(advice-add 'evil-window-move-far-right :around 'doom*save-neotree)
)
;;
;; Hacks
;;
(after! help-mode
;; Help buffers use itself (or `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 (lambda (fun file)
(require 'find-func)
(when (eq file 'C-source)
(setq file (help-C-file-name (indirect-function fun) 'fun)))
(let ((location (find-function-search-for-symbol fun nil file)))
(doom/popup-close)
(switch-to-buffer (car location) nil t)
(if (cdr location)
(goto-char (cdr location))
(message "Unable to find location in file")))))
(define-button-type 'help-variable-def
:supertype 'help-xref
'help-function (lambda (var &optional file)
(when (eq file 'C-source)
(setq file (help-C-file-name var 'var)))
(let ((location (find-variable-noselect var file)))
(doom/popup-close)
(switch-to-buffer (car location) nil t)
(if (cdr location)
(goto-char (cdr location))
(message "Unable to find location in file")))))
(define-button-type 'help-face-def
:supertype 'help-xref
'help-function (lambda (fun file)
(require 'find-func)
(let ((location
(find-function-search-for-symbol fun 'defface file)))
(doom/popup-close)
(switch-to-buffer (car location) nil t)
(if (cdr location)
(goto-char (cdr location))
(message "Unable to find location in file"))))))
(add-hook! org-load
;; Ensures org-src-edit yields control of its buffer to shackle.
(defun org-src-switch-to-buffer (buffer context)
(pop-to-buffer buffer))
;; And these for org-todo, org-link and org-agenda
(defun org-pop-to-buffer-same-window (&optional buffer-or-name norecord label)
"Pop to buffer specified by BUFFER-OR-NAME in the selected window."
(display-buffer buffer-or-name))
(defun org-switch-to-buffer-other-window (&rest args)
(car-safe
(mapc (lambda (b)
(let ((buf (if (stringp b) (get-buffer-create b) b)))
(pop-to-buffer buf t t)))
args)))
(defun doom/org-agenda-quit ()
"Necessary to finagle org-agenda into shackle popups and behave properly on quit."
(interactive)
(if org-agenda-columns-active
(org-columns-quit)
(let ((buf (current-buffer)))
(and (not (eq org-agenda-window-setup 'current-window))
(not (one-window-p))
(delete-window))
(kill-buffer buf)
(setq org-agenda-archives-mode nil
org-agenda-buffer nil))))
(after! org-agenda
(map! :map org-agenda-mode-map
:e "<escape>" 'doom/org-agenda-quit
:e "ESC" 'doom/org-agenda-quit
:e [escape] 'doom/org-agenda-quit
"q" 'doom/org-agenda-quit
"Q" 'doom/org-agenda-quit)))
(provide 'core-popup)
;;; core-popup.el ends here

351
core/core-popups.el Normal file
View file

@ -0,0 +1,351 @@
;;; core-popups.el --- taming sudden yet inevitable windows
;; I'd like certain buffers--like prompts or informational/terminal/temporary
;; buffers--to act independently from my work buffers, to minimize the context
;; switch between them. To do this, I relegate them to disposable "popup
;; windows" that can be invoked from anywhere.
;;
;; I use a slew of hackery to get Emacs to treat these popups consistently. It
;; goes through great lengths to tame helm, flycheck, help buffers--*even* the
;; beast that is org-mode, with the help of `display-buffer-alist' and
;; `shackle'.
;;
;; Be warned, this could break.
(package! shackle :demand t
:config
(shackle-mode 1)
(setq shackle-default-alignment 'below
shackle-rules
`(;; Doom
(" *doom*" :size 35 :select t)
("^ ?\\*doom:.+\\*$" :size 35 :select t :regexp t)
("^ ?\\*doom.+\\*$" :size 12 :noselect t :regexp t)
("^\\*.+-Profiler-Report .+\\*$" :size 0.3 :regexp t)
("*esup*" :size 0.4 :noselect t)
("*minor-modes*" :size 0.5 :noselect t)
("*eval*" :size 16 :noselect t)
;; Emacs
("*Pp Eval Output*" :size 0.3)
("*Apropos*" :size 0.3)
("*Backtrace*" :size 25 :noselect t)
("*Help*" :size 16 :select t)
("*Messages*" :size 15 :select t)
("*Warnings*" :size 10 :noselect t)
(compilation-mode :size 15 :noselect t)
(eww-mode :size 30 :select t)
("*command-log*" :size 28 :noselect t :align right)
;; evil
("*evil-registers*" :size 0.3)
("*Command Line*" :size 8 :select t)
;; git-gutter
("^\\*git-gutter.+\\*$" :regexp t :size 15 :noselect t)
;; vcs
("*vc-diff*" :size 15 :noselect t)
("*vc-change-log*" :size 15 :select t)
(vc-annotate-mode :same t)
))
;; :noesc = Can't be closed with a single ESC
;; :nokill = Won't be killed when closed (only buried)
(defvar doom-popup-rules
'(("^\\*doom\\(:scratch\\)?\\*$" :noesc :nokill)
("^\\*doom.*\\*$" :noesc :nokill)
(ivy-occur-grep-mode :noesc)
(compilation-mode :noesc)
(comint-mode :noesc :nokill)
(eshell-mode :noesc :nokill)
(messages-buffer-mode :nokill)
(esup-mode :noesc)
(tabulated-list-mode :noesc)))
(defvar-local doom-popup-rule nil
"A list of rules applied to this popup.")
(put 'doom-popup-rule 'permanent-local t)
(defvar doom-popup-mode-map
(let ((map (make-sparse-keymap)))
(define-key map [remap doom/kill-real-buffer] 'doom/popup-close)
(define-key map [remap evil-window-delete] 'doom/popup-close)
(define-key map [remap evil-window-move-very-bottom] 'ignore)
(define-key map [remap evil-window-move-very-top] 'ignore)
(define-key map [remap evil-window-move-far-left] 'ignore)
(define-key map [remap evil-window-move-far-right] 'ignore)
(define-key map [remap evil-window-split] 'ignore)
(define-key map [remap evil-window-vsplit] 'ignore)
(define-key map [remap evil-force-normal-state] 'doom/popup-close-maybe)
(define-key map [escape] 'doom/popup-close-maybe)
(define-key map (kbd "ESC") 'doom/popup-close-maybe)
map)
"Active keymap in popup windows.")
(define-minor-mode doom-popup-mode
"Minor mode for pop-up windows. Enables local keymaps and sets state
variables."
:global nil
:init-value nil
:keymap doom-popup-mode-map
(let ((rules (--any (let ((key (car it)))
(when (cond ((symbolp key)
(or (eq major-mode key)
(derived-mode-p key)))
((stringp key)
(string-match-p key (buffer-name))))
(cdr it)))
doom-popup-rules)))
(set-window-dedicated-p nil doom-popup-mode)
(setq doom-last-popup (current-buffer))
(setq-local doom-popup-rule rules)))
(put 'doom-popup-mode 'permanent-local t)
(defun doom*popup-init (orig-fn &rest args)
"Enables `doom-popup-mode' in every popup window and returns the window."
(let ((window (apply orig-fn args)))
(with-selected-window window
(doom-popup-mode +1))
;; NOTE orig-fn returns a window, so `doom*popup-init' must too
window))
(defun doom*popup-save (orig-fun &rest args)
"Prevents messing up a popup buffer on window changes."
(let ((in-popup-p (doom-popup-p))
(popups-p (and doom-last-popup
(window-live-p (get-buffer-window doom-last-popup)))))
(when popups-p
(mapc (lambda (w) (doom/popup-close w t))
(-filter 'doom-popup-p (window-list))))
(unwind-protect (apply orig-fun args)
(when popups-p
(let ((origin-win (selected-window)))
(doom/popup-last-buffer)
(when in-popup-p
(select-window origin-win)))))))
;; There is no shackle-popup hook, so I created one:
(advice-add 'shackle-display-buffer :around 'doom*popup-init)
;; Order matters for these two
(advice-add 'balance-windows :around 'doom*popup-save))
;;
;; Hacks
;;
(after! evil
;; Tell these functions not to mess with popups:
(advice-add 'doom-evil-window-move :around 'doom*popup-save)
(advice-add 'evil-window-move-very-bottom :around 'doom*popup-save)
(advice-add 'evil-window-move-very-top :around 'doom*popup-save)
(advice-add 'evil-window-move-far-left :around 'doom*popup-save)
(advice-add 'evil-window-move-far-right :around 'doom*popup-save)
(defun doom*evil-command-window (hist cmd-key execute-fn)
"The evil command window has a mind of its own (uses `switch-to-buffer'). We
monkey patch it to use pop-to-buffer."
(when (eq major-mode 'evil-command-window-mode)
(user-error "Cannot recursively open command line window"))
(dolist (win (window-list))
(when (equal (buffer-name (window-buffer win))
"*Command Line*")
(kill-buffer (window-buffer win))
(delete-window win)))
(setq evil-command-window-current-buffer (current-buffer))
(ignore-errors (kill-buffer "*Command Line*"))
(with-current-buffer (pop-to-buffer "*Command Line*")
(setq-local evil-command-window-execute-fn execute-fn)
(setq-local evil-command-window-cmd-key cmd-key)
(evil-command-window-mode)
(evil-command-window-insert-commands hist)))
(advice-add 'evil-command-window :override 'doom*evil-command-window))
(after! help-mode
;; Help buffers use itself (or `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 (lambda (fun file)
(require 'find-func)
(when (eq file 'C-source)
(setq file (help-C-file-name (indirect-function fun) 'fun)))
(let ((location (find-function-search-for-symbol fun nil file)))
(doom/popup-close)
(switch-to-buffer (car location) nil t)
(if (cdr location)
(progn
(goto-char (cdr location))
(recenter nil))
(message "Unable to find location in file")))))
(define-button-type 'help-variable-def
:supertype 'help-xref
'help-function (lambda (var &optional file)
(when (eq file 'C-source)
(setq file (help-C-file-name var 'var)))
(let ((location (find-variable-noselect var file)))
(doom/popup-close)
(switch-to-buffer (car location) nil t)
(if (cdr location)
(progn
(goto-char (cdr location))
(recenter nil))
(message "Unable to find location in file")))))
(define-button-type 'help-face-def
:supertype 'help-xref
'help-function (lambda (fun file)
(require 'find-func)
(let ((location
(find-function-search-for-symbol fun 'defface file)))
(doom/popup-close)
(switch-to-buffer (car location) nil t)
(if (cdr location)
(progn
(goto-char (cdr location))
(recenter nil))
(message "Unable to find location in file"))))))
(after! magit
;; Don't open files (from magit) in the magit popup
(advice-add 'magit-display-file-buffer-traditional :around 'doom*popup-save))
(after! neotree
(defun doom*save-neotree (orig-fun &rest args)
"Prevents messing up the neotree buffer on window changes."
(let ((neo-p (and (featurep 'neotree) (neo-global--window-exists-p))))
(when neo-p
(neotree-hide)
(balance-windows))
(unwind-protect (apply orig-fun args)
(when neo-p
(save-selected-window
(neotree-show))))))
;; Prevent neotree from interfering with popups
(advice-add 'shackle-display-buffer :around 'doom*save-neotree)
;; Prevents messing up the neotree buffer on window changes
(advice-add 'doom-evil-window-move :around 'doom*save-neotree)
;; (advice-add 'doom-popup-buffer :around 'doom*save-neotree)
;; Don't let neotree interfere with moving, splitting or rebalancing windows
(advice-add 'balance-windows :around 'doom*save-neotree)
(advice-add 'split-window :around 'doom*save-neotree)
(advice-add 'shackle-display-buffer :around 'doom*save-neotree)
(advice-add 'evil-window-move-very-bottom :around 'doom*save-neotree)
(advice-add 'evil-window-move-very-top :around 'doom*save-neotree)
(advice-add 'evil-window-move-far-left :around 'doom*save-neotree)
(advice-add 'evil-window-move-far-right :around 'doom*save-neotree))
(add-hook! org-load
;; Ensures org-src-edit yields control of its buffer to shackle.
(defun org-src-switch-to-buffer (buffer context)
(pop-to-buffer buffer))
;; And these for org-todo, org-link and org-agenda
(defun org-pop-to-buffer-same-window (&optional buffer-or-name norecord label)
"Pop to buffer specified by BUFFER-OR-NAME in the selected window."
(display-buffer buffer-or-name))
(defun org-switch-to-buffer-other-window (&rest args)
(car-safe
(mapc (lambda (b)
(let ((buf (if (stringp b) (get-buffer-create b) b)))
(pop-to-buffer buf t t)))
args)))
(defun doom/org-agenda-quit ()
"Necessary to finagle org-agenda into shackle popups and behave properly on quit."
(interactive)
(if org-agenda-columns-active
(org-columns-quit)
(let ((buf (current-buffer)))
(and (not (eq org-agenda-window-setup 'current-window))
(not (one-window-p))
(delete-window))
(kill-buffer buf)
(setq org-agenda-archives-mode nil
org-agenda-buffer nil))))
(after! org-agenda
(map! :map org-agenda-mode-map
:e "<escape>" 'doom/org-agenda-quit
:e "ESC" 'doom/org-agenda-quit
:e [escape] 'doom/org-agenda-quit
"q" 'doom/org-agenda-quit
"Q" 'doom/org-agenda-quit)))
;;
;; Functions
;;
(defun doom-popup-p (&optional window)
"Whether WINDOW is a popup window or not. If WINDOW is nil, use current
window. Returns nil or the popup window."
(setq window (or window (selected-window)))
(and (window-live-p window)
(buffer-local-value 'doom-popup-mode (window-buffer window))
window))
(defun doom-popup-buffer (buffer &optional plist)
"Display BUFFER in a shackle popup."
(let* ((buffer-name (cond ((stringp buffer) buffer)
((bufferp buffer) (buffer-name buffer))
(t (error "Not a valid buffer"))))
(buffer (get-buffer-create buffer-name)))
(when (doom/real-buffer-p (window-buffer))
(setq doom-last-window (selected-window)))
(shackle-display-buffer
buffer
nil (or plist (shackle-match buffer-name)))))
(defun doom/popup-messages ()
"Pop up the messages buffer."
(interactive)
(doom-popup-buffer (messages-buffer))
(goto-char (point-max)))
(defun doom/popup-last-buffer ()
"Restore the last popup."
(interactive)
(unless (buffer-live-p doom-last-popup)
(setq doom-last-popup nil)
(error "No popup to restore"))
(doom-popup-buffer doom-last-popup))
(defun doom/popup-close (&optional window dont-kill)
"Find and close the currently active popup (if available)."
(interactive)
(setq window (or window (selected-window)))
(when (doom-popup-p window)
(with-selected-window window
;; If REPL...
(when (bound-and-true-p repl-toggle-mode)
(setq rtog/--last-buffer nil))
(doom-popup-mode -1)
(unless (or dont-kill (memq :nokill doom-popup-rule))
(let ((kill-buffer-query-functions
(delq 'process-kill-buffer-query-function
kill-buffer-query-functions)))
(kill-buffer (window-buffer window)))))
(delete-window window)))
(defun doom/popup-close-maybe ()
"Close the current popup *if* its buffer doesn't have a :noesc rule in
`doom-popup-rules'."
(interactive)
(if (memq :noesc doom-popup-rule)
(call-interactively 'evil-force-normal-state)
(doom/popup-close)))
(defun doom/popup-close-all (&optional dont-kill)
"Closes all popups (kill them if DONT-KILL-BUFFERS is non-nil)."
(interactive)
(let ((orig-win (selected-window)))
(mapc (lambda (w) (doom/popup-close w dont-kill))
(--filter (and (doom-popup-p it) (not (eq it orig-win)))
(window-list)))))
(provide 'core-popups)
;;; core-popups.el ends here

View file

@ -1,41 +1,52 @@
;;; core-project.el --- all your (basic) project navigational needs
;;; core-project.el --- tools for getting around your project
(setq ;; Always copy/delete recursively
dired-recursive-copies 'always
dired-recursive-deletes 'top
;; Auto refresh dired, but be quiet about it
global-auto-revert-non-file-buffers t
auto-revert-verbose nil)
;; I want Emacs project-aware. i.e. To know what project I'm in, and to be able
;; to tell me about it. `projectile' helps me with this. It also provides nifty
;; tools for digging out files I want from a project of any size.
;;
;; `neotree', on the other hand, allows me to browse my project files. I
;; occasionally like having a birds-eye view of my files.
;; List directories first
(defun doom|dired-sort ()
"Dired sort hook to list directories first."
(save-excursion
(let (buffer-read-only)
(forward-line 2) ;; beyond dir. header
(sort-regexp-fields t "^.*$" "[ ]*." (point) (point-max))))
(and (featurep 'xemacs)
(fboundp 'dired-insert-set-properties)
(dired-insert-set-properties (point-min) (point-max)))
(set-buffer-modified-p nil))
(add-hook 'dired-after-readin-hook 'doom|dired-sort)
(package! projectile :demand t
:init
(setq projectile-cache-file (concat doom-temp-dir "/projectile.cache")
projectile-completion-system 'ivy
projectile-enable-caching t
projectile-file-exists-remote-cache-expire nil
projectile-globally-ignored-directories `(,doom-temp-dir ".sync")
projectile-globally-ignored-file-suffixes '(".elc" ".pyc" ".o")
projectile-globally-ignored-files '(".DS_Store" "Icon ")
projectile-indexing-method 'alien
projectile-known-projects-file (concat doom-temp-dir "/projectile.projects")
projectile-project-root-files '(".git" ".hg" ".svn" ".project")
projectile-require-project-root nil)
(use-package dired-k
:after dired
:config
(setq dired-k-style 'git)
(add-hook 'dired-initial-position-hook 'dired-k)
(add-hook 'dired-after-readin-hook #'dired-k-no-revert))
(mapc (lambda (r) (push r projectile-other-file-alist))
'(("less" "css")
("styl" "css")
("sass" "css")
("scss" "css")
("css" "scss" "sass" "less" "styl")
("jade" "html")
("pug" "html")
("html" "jade" "pug" "jsx" "tsx")))
;; Automatically create missing directories when creating new files
(defun doom|create-non-existent-directory ()
(let ((parent-directory (file-name-directory buffer-file-name)))
(when (and (not (file-exists-p parent-directory))
(y-or-n-p (format "Directory `%s' does not exist! Create it?" parent-directory)))
(make-directory parent-directory t))))
(push 'doom|create-non-existent-directory find-file-not-found-functions)
(defun doom*projectile-cache-current-file (orig-fun &rest args)
"Don't cache ignored files."
(unless (--any (f-descendant-of? buffer-file-name it)
(projectile-ignored-directories))
(apply orig-fun args)))
(advice-add 'projectile-cache-current-file :around 'doom*projectile-cache-current-file)
(use-package neotree
(projectile-global-mode +1))
;;
;; Autoloaded Packages
;;
(package! neotree
:commands (neotree-show
neotree-hide
neotree-toggle
@ -51,23 +62,30 @@
neo-window-width 25
neo-show-updir-line nil
neo-theme 'nerd ; fallback
neo-banner-message nil)
neo-banner-message nil
neo-show-hidden-files nil
neo-hidden-regexp-list
'(;; vcs folders
"^\\.\\(git\\|hg\\|svn\\)$"
;; compiled files
"\\.\\(pyc\\|o\\|elc\\|lock\\|css.map\\)$"
;; generated files, caches or local pkgs
"^\\(node_modules\\|vendor\\|.\\(project\\|cask\\|yardoc\\|sass-cache\\)\\)$"
;; org-mode folders
"^\\.\\(sync\\|export\\|attach\\)$"
"~$"
"^#.*#$"))
:config
(evil-set-initial-state 'neotree-mode 'motion)
(add-hook 'neo-after-create-hook 'doom-hide-mode-line-mode)
;; Don't ask for confirmation when creating files
(advice-add 'neotree-create-node :around 'doom*neotree-create-node)
;; Prevents messing up the neotree buffer on window changes
(advice-add 'doom/evil-window-move :around 'doom*save-neotree)
(advice-add 'doom/popup-buffer :around 'doom*save-neotree)
;; Adding keybindings to `neotree-mode-map' wouldn't work for me (they get
;; overridden when the neotree buffer is spawned). So we bind them in a hook.
(add-hook 'neo-after-create-hook 'doom|neotree-init-keymap)
(defun doom|neotree-init-keymap (&rest _)
(map! :Lm "\\\\" 'evil-window-prev
:Lm "ESC ESC" 'doom/neotree-close
:Lm "q" 'doom/neotree-close
:Lm "ESC ESC" 'neotree-hide
:Lm "q" 'neotree-hide
:Lm [return] 'neotree-enter
:Lm "RET" 'neotree-enter
:Lm "<return>" 'neotree-enter
@ -83,32 +101,5 @@
:Lm "r" 'neotree-rename-node
:Lm "R" 'neotree-change-root)))
(use-package projectile
:config
(setq projectile-require-project-root nil
projectile-enable-caching t
projectile-cache-file (concat doom-temp-dir "/projectile.cache")
projectile-known-projects-file (concat doom-temp-dir "/projectile.projects")
projectile-indexing-method 'alien
projectile-file-exists-remote-cache-expire nil
projectile-project-root-files '(".git" ".hg" ".svn" ".project"))
;; Don't cache ignored files!
(defun doom*projectile-cache-current-file (orig-fun &rest args)
(unless (--any (f-descendant-of? buffer-file-name it)
(projectile-ignored-directories))
(apply orig-fun args)))
(advice-add 'projectile-cache-current-file :around 'doom*projectile-cache-current-file)
(push doom-temp-dir projectile-globally-ignored-directories)
(push "assets" projectile-globally-ignored-directories)
(push ".cask" projectile-globally-ignored-directories)
(push ".sync" projectile-globally-ignored-directories)
(push ".elc" projectile-globally-ignored-file-suffixes)
(push ".project" projectile-globally-ignored-file-suffixes)
(push "Icon " projectile-globally-ignored-files)
(projectile-global-mode +1))
(provide 'core-project)
;;; core-project.el ends here

6
core/core-repl.el Normal file
View file

@ -0,0 +1,6 @@
;;; core-repl.el
;; TODO
(provide 'core-repl)
;;; core-repl.el ends here

View file

@ -1,196 +0,0 @@
;;; core-scratch.el
(setq initial-major-mode 'doom-mode
initial-scratch-message "\n Loading..."
inhibit-startup-screen t
;; shuts up emacs at startup
inhibit-startup-echo-area-message user-login-name)
(defvar doom-buffer nil
"The global and persistent scratch buffer for doom.")
(defvar doom-scratch-name " *doom*"
"The name of the doom scratch buffer.")
(defvar doom-scratch-edited nil
"If non-nil, the scratch buffer has been edited.")
(defvar doom-scratch-inhibit-refresh nil
"If non-nil, the doom buffer won't be refreshed.")
(defvar doom-scratch-modeline (doom-modeline 'scratch)
"Modeline format for doom scratch buffer.")
(defvar doom-scratch-widgets '(banner shortmenu loaded)
"List of widgets to display in a blank scratch buffer.")
(define-derived-mode doom-mode fundamental-mode
(concat "v" doom-version)
"Major mode for the DOOM scratch buffer.")
(defvar doom-scratch--width 0)
(defvar doom-scratch--height 0)
;;
(add-hook 'emacs-startup-hook 'doom-scratch)
(add-hook! 'kill-buffer-query-functions (not (doom-scratch-buffer-p)))
(add-hook! window-setup
(add-hook 'window-configuration-change-hook 'doom-scratch-reload)
(doom-scratch-reload))
;;
(defun doom-scratch-buffer-p (&optional buffer)
(let ((buffer (or buffer (current-buffer))))
(and (buffer-live-p buffer)
(eq buffer doom-buffer))))
(defun doom-scratch-buffer ()
"Ensure the scratch buffer exists and is alive (otherwise create it)."
;; Rename the old scratch buffer, if it exists.
(let ((old-scratch (get-buffer "*scratch*")))
(when old-scratch (kill-buffer old-scratch)))
;; Ensure the doom buffer is alive!
(unless (buffer-live-p doom-buffer)
(setq doom-buffer nil))
(unless doom-buffer
(setq doom-buffer (get-buffer-create doom-scratch-name)))
doom-buffer)
(defun doom-scratch ()
(interactive)
(doom-scratch-reload)
(switch-to-buffer doom-buffer)
nil)
(defun doom-scratch-force-reload ()
(setq doom-scratch-edited nil)
(doom-scratch-reload))
(defun doom|scratch-clear-on-insert ()
"Erase the buffer and prepare it to be used like a normal buffer."
(erase-buffer)
;; (set-window-margins (get-buffer-window doom-buffer) 0 0)
(setq doom-scratch-edited t
mode-line-format (doom-modeline))
(remove-hook 'evil-insert-state-entry-hook 'doom|mode-erase-on-insert t))
(defun doom-scratch-reload (&optional dir)
"Update the DOOM scratch buffer (or create it, if it doesn't exist)."
(when (and (not doom-scratch-inhibit-refresh)
(not (minibuffer-window-active-p (minibuffer-window)))
(get-buffer-window-list doom-buffer nil t)
(or (not doom-scratch-edited) dir))
(let ((old-pwd (or dir default-directory)))
(with-current-buffer (doom-scratch-buffer)
(doom-mode)
(add-hook 'evil-insert-state-entry-hook 'doom|scratch-clear-on-insert nil t)
(add-hook 'after-change-major-mode-hook 'doom|scratch-clear-on-insert nil t)
(setq doom-scratch-edited nil)
(erase-buffer)
(let ((doom-scratch--width (1- (window-width (get-buffer-window doom-buffer))))
(doom-scratch--height (window-height (get-buffer-window doom-buffer))))
(insert (make-string (max 0 (- (truncate (/ doom-scratch--height 2)) 12)) ?\n))
(mapc (lambda (widget-name)
(funcall (intern (format "doom-scratch-widget-%s" widget-name)))
(insert "\n\n"))
doom-scratch-widgets))
(setq default-directory old-pwd)
(setq mode-line-format (doom-modeline 'scratch)))))
t)
(defun doom-scratch-widget-banner ()
(mapc (lambda (line)
(insert "\n")
(insert (propertize (s-center doom-scratch--width line)
'face 'font-lock-comment-face) " "))
'("================= =============== =============== ======== ========"
"\\\\ . . . . . . .\\\\ //. . . . . . .\\\\ //. . . . . . .\\\\ \\\\. . .\\\\// . . //"
"||. . ._____. . .|| ||. . ._____. . .|| ||. . ._____. . .|| || . . .\\/ . . .||"
"|| . .|| ||. . || || . .|| ||. . || || . .|| ||. . || ||. . . . . . . ||"
"||. . || || . .|| ||. . || || . .|| ||. . || || . .|| || . | . . . . .||"
"|| . .|| ||. _-|| ||-_ .|| ||. . || || . .|| ||. _-|| ||-_.|\\ . . . . ||"
"||. . || ||-' || || `-|| || . .|| ||. . || ||-' || || `|\\_ . .|. .||"
"|| . _|| || || || || ||_ . || || . _|| || || || |\\ `-_/| . ||"
"||_-' || .|/ || || \\|. || `-_|| ||_-' || .|/ || || | \\ / |-_.||"
"|| ||_-' || || `-_|| || || ||_-' || || | \\ / | `||"
"|| `' || || `' || || `' || || | \\ / | ||"
"|| .===' `===. .==='.`===. .===' /==. | \\/ | ||"
"|| .==' \\_|-_ `===. .===' _|_ `===. .===' _-|/ `== \\/ | ||"
"|| .==' _-' `-_ `=' _-' `-_ `=' _-' `-_ /| \\/ | ||"
"|| .==' _-' '-__\\._-' '-_./__-' `' |. /| | ||"
"||.==' _-' `' | /==.||"
"==' _-' E M A C S \\/ `=="
"\\ _-' `-_ /"
" `'' ``'")))
(defun doom-scratch-widget-loaded ()
(insert
(s-center (1- doom-scratch--width)
(propertize
(format "Loaded %d packages in %s"
(length doom-packages)
(emacs-init-time))
'face '(:inherit font-lock-comment-face
:height 0.9)))))
(defun doom-scratch-widget-shortmenu ()
(let ((all-the-icons-scale-factor 1.3)
(all-the-icons-default-adjust -0.05)
(start (point))
(sep " ")
(last-session-p (and (featurep 'workgroups2)
(f-exists-p wg-session-file)))
end)
(unless last-session-p
(setq sep " "))
(insert
(s-center (- doom-scratch--width 5)
(with-temp-buffer
(insert-text-button
(concat (all-the-icons-octicon
"mark-github"
:face 'font-lock-keyword-face)
(propertize " Homepage" 'face 'font-lock-keyword-face))
'action '(lambda (_) (browse-url "https://github.com/hlissner/.emacs.d"))
'follow-link t)
(insert sep " ")
(insert-text-button
(concat (all-the-icons-octicon
"file-text"
:face 'font-lock-keyword-face)
(propertize " Recent files" 'face 'font-lock-keyword-face))
'action '(lambda (_) (call-interactively 'counsel-recentf))
'follow-link t)
(insert sep)
(insert-text-button
(concat (all-the-icons-octicon
"tools"
:face 'font-lock-keyword-face)
(propertize " Edit emacs.d" 'face 'font-lock-keyword-face))
'action '(lambda (_) (find-file (f-expand "init.el" doom-emacs-dir)))
'follow-link t)
(when last-session-p
(insert sep)
(insert-text-button
(concat (all-the-icons-octicon
"history"
:face 'font-lock-keyword-face)
(propertize " Reload last session" 'face 'font-lock-keyword-face))
'action '(lambda (_) (doom:workgroup-load))
'follow-link t))
(setq end (point))
(buffer-string))))))
(provide 'core-scratch)
;;; core-scratch.el ends here

6
core/core-sessions.el Normal file
View file

@ -0,0 +1,6 @@
;;; core-sessions.el
;; TODO
(provide 'core-sessions)
;;; core-sessions.el ends here

22
core/core-settings.el Normal file
View file

@ -0,0 +1,22 @@
;;; core-settings.el --- centralized inter-package configuration
(defvar doom-settings '()
"docstring")
(defun doom-define-setting (name &optional docs &rest args))
(defmacro config! (package-name &rest args)
(declare (indent defun))
`(let ((doom-current-package ',package-name))
,(macroexpand-progn args))
;; 1. Check for `set!' calls
;; 2. Append mode
)
(defmacro set! (&rest args))
(defun doom-set (mode key value)
(declare (indent defun)))
(provide 'core-settings)
;;; core-settings.el ends here

6
core/core-snippets.el Normal file
View file

@ -0,0 +1,6 @@
;;; core-snippets.el
;; TODO
(provide 'core-snippets)
;;; core-snippets.el ends here

6
core/core-states.el Normal file
View file

@ -0,0 +1,6 @@
;;; core-states.el
(provide 'core-states)
;;; core-states.el ends here

View file

@ -1,6 +1,6 @@
;;; core-flycheck.el --- check yourself before you shrek yourself
;;; core-syntax-checking.el --- tasing you for every forgotten semicolon
(use-package flycheck
(package! flycheck
:commands (flycheck-mode flycheck-list-errors flycheck-buffer)
:init
(setq flycheck-indication-mode 'right-fringe
@ -13,7 +13,7 @@
flycheck-display-errors-delay 0.5)
:config
(def-popup! " ?\\*Flycheck.+\\*" :align below :size 14 :noselect t :regexp t)
;; (def-popup! " ?\\*Flycheck.+\\*" :align below :size 14 :noselect t :regexp t)
(map! :map flycheck-error-list-mode-map
:n "C-n" 'flycheck-error-list-next-error
@ -23,16 +23,20 @@
:n "RET" 'flycheck-error-list-goto-error)
;; Flycheck buffer on ESC in normal mode.
(defun doom*flycheck-buffer ()
(when (bound-and-true-p flycheck-mode) (flycheck-buffer)))
(advice-add 'evil-force-normal-state :after 'doom*flycheck-buffer)
(define-fringe-bitmap 'flycheck-fringe-bitmap-double-arrow
[0 0 0 0 0 4 12 28 60 124 252 124 60 28 12 4 0 0 0 0])
[0 0 0 0 0 4 12 28 60 124 252 124 60 28 12 4 0 0 0 0]))
(when (eq window-system 'mac)
(require 'flycheck-pos-tip)
(flycheck-pos-tip-mode +1)))
;; NOTE Looks bad on emacs-mac build on MacOS
(package! flycheck-pos-tip
:unless (eq window-system 'ns)
:after flycheck
:config (flycheck-pos-tip-mode +1))
(use-package flyspell :commands flyspell-mode)
(package! flyspell :commands flyspell-mode)
(provide 'core-flycheck)
;;; core-flycheck.el ends here
(provide 'core-syntax-checking)
;;; core-syntax-checking.el ends here

View file

@ -1,4 +1,4 @@
;;; core-ui.el
;; core-ui.el --- draw me like one of your French editors
(defvar doom-ui-fringe-size '3
"Default fringe width")
@ -14,204 +14,40 @@
(font-spec :family "Fira Sans" :size 12)
"The font currently in use.")
(defvar doom-ui-unicode-font
(font-spec :family "DejaVu Sans Mono" :size 12)
"Fallback font for unicode glyphs.")
;;
;; Configuration
;;
(setq-default
mode-line-default-help-echo nil ; don't say anything on mode-line mouseover
indicate-buffer-boundaries nil ; don't show where buffer starts/ends
indicate-empty-lines nil ; don't show empty lines
fringes-outside-margins t ; switches order of fringe and margin
;; Keep cursors and highlights in current window only
(setq bidi-display-reordering nil ; disable bidirectional text for tiny performance boost
blink-matching-paren nil ; don't blink--too distracting
cursor-in-non-selected-windows nil
highlight-nonselected-windows nil
;; Disable bidirectional text support for slight performance bonus
bidi-display-reordering nil
;; Remove continuation arrow on right fringe
echo-keystrokes 0.02
frame-inhibit-implied-resize t
;; remove continuation arrow on right fringe
fringe-indicator-alist (delq (assq 'continuation fringe-indicator-alist)
fringe-indicator-alist)
blink-matching-paren nil ; don't blink--too distracting
show-paren-delay 0.075
show-paren-highlight-openparen t
show-paren-when-point-inside-paren t
uniquify-buffer-name-style nil
visible-bell nil
visible-cursor nil
x-stretch-cursor t
use-dialog-box nil ; always avoid GUI
redisplay-dont-pause t ; don't pause display on input
split-width-threshold nil ; favor horizontal splits
show-help-function nil ; hide :help-echo text
highlight-nonselected-window nil
image-animate-loop t
indicate-buffer-boundaries nil
indicate-empty-lines nil
jit-lock-defer-time nil
jit-lock-stealth-nice 0.1
jit-lock-stealth-time 0.2
jit-lock-stealth-verbose nil
;; Minibuffer resizing
resize-mini-windows 'grow-only
max-mini-window-height 0.3
image-animate-loop t
;; Ask for confirmation on exit only if there are real buffers left
confirm-kill-emacs
(lambda (_)
(if (ignore-errors (doom/get-real-buffers))
(y-or-n-p " Quit?")
t)))
;; A subtle bell: flash the mode-line
;; TODO More flexible colors (only suits dark themes)
(defvar doom--modeline-bg nil)
(setq ring-bell-function
(lambda ()
(unless doom--modeline-bg
(setq doom--modeline-bg (face-attribute 'mode-line :background)))
(set-face-attribute 'mode-line nil :background "#54252C")
(run-with-timer
0.1 nil
(lambda () (set-face-attribute 'mode-line nil :background doom--modeline-bg)))))
;; y/n instead of yes/no
(fset 'yes-or-no-p 'y-or-n-p)
;; mode-line is unimportant in help/compile/completion candidate windows
(with-current-buffer "*Messages*" (doom-hide-mode-line-mode +1))
(add-hook! (help-mode
compilation-mode
messages-buffer-mode
completion-list-mode)
'doom-hide-mode-line-mode)
;; Eldoc is enabled globally on Emacs 25. No thank you, I'll do it myself.
(when (bound-and-true-p global-eldoc-mode)
(global-eldoc-mode -1))
;; TODO/FIXME/NOTE highlighting in comments
(add-hook! (prog-mode emacs-lisp-mode css-mode)
(font-lock-add-keywords
nil '(("\\<\\(TODO\\(?:(.*)\\)?:?\\)\\>" 1 'warning prepend)
("\\<\\(FIXME\\(?:(.*)\\)?:?\\)\\>" 1 'error prepend)
("\\<\\(NOTE\\(?:(.*)\\)?:?\\)\\>" 1 'success prepend))))
;; `window-divider-mode' gives us finer control over the border between windows.
;; The native border "consumes" a pixel of the fringe on righter-most splits (in
;; Yamamoto's emacs-mac at least), window-divider does not.
;; NOTE Only available on Emacs 25.1+
(when (boundp 'window-divider-mode)
(setq window-divider-default-places t
window-divider-default-bottom-width 1
window-divider-default-right-width 1)
(window-divider-mode +1))
;;
;; Plugins
;;
(use-package doom-themes
:config
(setq doom-neotree-enable-variable-pitch t
doom-neotree-file-icons 'simple
doom-neotree-line-spacing 3)
(load-theme doom-ui-theme t)
;; brighter source buffers
(add-hook 'find-file-hook 'doom-buffer-mode)
;; Custom neotree theme
(when window-system
(require 'doom-neotree)))
(use-package beacon
:config
(beacon-mode +1)
(setq beacon-color (face-attribute 'highlight :background nil t)
beacon-blink-when-buffer-changes t
beacon-blink-when-point-moves-vertically 10))
(use-package hl-line
:init (add-hook 'prog-mode-hook 'hl-line-mode)
:config
;; stickiness doesn't play nice with emacs 25+
(setq hl-line-sticky-flag nil
global-hl-line-sticky-flag nil)
;; Remember whether hl-line was initially on or off in the current buffer
(defvar-local doom--hl-line-mode nil)
(defun doom|hl-line-on () (if doom--hl-line-mode (hl-line-mode +1)))
(defun doom|hl-line-off () (if doom--hl-line-mode (hl-line-mode -1)))
(add-hook! hl-line-mode (if hl-line-mode (setq doom--hl-line-mode t))))
(use-package highlight-indentation
:commands (highlight-indentation-mode
highlight-indentation-current-column-mode)
:init
(after! editorconfig
(advice-add 'highlight-indentation-guess-offset
:override 'doom*hl-indent-guess-offset))
;; Since empty lines are stripped on save, the indentation highlights will
;; have unseemly breaks in them. These hooks will indent empty lines so that
;; the highlights are consistent, without affecting the saved output.
(add-hook! highlight-indentation-mode
(if highlight-indentation-mode
(progn
(doom/add-whitespace)
(add-hook 'after-save-hook 'doom/add-whitespace nil t))
(remove-hook 'after-save-hook 'doom/add-whitespace t)
(delete-trailing-whitespace))))
(use-package highlight-numbers :commands (highlight-numbers-mode))
(use-package nlinum
:commands nlinum-mode
:preface
(setq linum-format "%3d ")
(defvar nlinum-format "%4d ")
(defvar doom--hl-nlinum-overlay nil)
(defvar doom--hl-nlinum-line nil)
:init
(add-hook!
(markdown-mode prog-mode scss-mode web-mode conf-mode groovy-mode
nxml-mode snippet-mode php-mode)
'nlinum-mode)
;; FIXME This only works if hl-line is active! Why?
(add-hook! nlinum-mode
(if nlinum-mode-hook
(add-hook 'post-command-hook 'doom|nlinum-hl-line nil t)
(remove-hook 'post-command-hook 'doom|nlinum-hl-line t)))
:config
;; Calculate line number column width beforehand
(add-hook! nlinum-mode
(setq nlinum--width (length (save-excursion (goto-char (point-max))
(format-mode-line "%l")))))
;; Disable nlinum when making frames, otherwise we get linum face error
;; messages that prevent frame creation.
(add-hook 'before-make-frame-hook 'doom|nlinum-disable)
(add-hook 'after-make-frame-functions 'doom|nlinum-enable))
(use-package rainbow-delimiters
:commands rainbow-delimiters-mode
:config (setq rainbow-delimiters-max-face-count 3)
:init
(add-hook! (emacs-lisp-mode lisp-mode js-mode css-mode c-mode-common)
'rainbow-delimiters-mode))
;; NOTE hl-line-mode and rainbow-mode don't play well together
(use-package rainbow-mode
:commands rainbow-mode
:init (after! hl-line (add-hook 'rainbow-mode-hook 'doom|hl-line-off)))
(use-package stripe-buffer
:commands stripe-buffer-mode
:init (add-hook 'dired-mode-hook 'stripe-buffer-mode))
(use-package visual-fill-column :defer t
:config
(setq-default visual-fill-column-center-text nil
visual-fill-column-width fill-column
split-window-preferred-function 'visual-line-mode-split-window-sensibly))
mode-line-default-help-echo nil ; disable mode-line mouseovers
redisplay-dont-pause t ; don't pause display on input
resize-mini-windows 'grow-only ; Minibuffer resizing
show-help-function nil ; hide :help-echo text
show-paren-delay 0.075
show-paren-highlight-openparen t
show-paren-when-point-inside-paren t
split-width-threshold nil ; favor horizontal splits
uniquify-buffer-name-style nil
use-dialog-box nil ; always avoid GUI
visible-bell nil
visible-cursor nil
x-stretch-cursor t)
;;
@ -229,9 +65,11 @@
(with-demoted-errors "FONT ERROR: %s"
(set-frame-font doom-ui-font t t)
;; Fallback to `doom-unicode-font' for Unicode characters
(set-fontset-font t 'unicode doom-unicode-font)
(when doom-ui-unicode-font
(set-fontset-font t 'unicode doom-ui-unicode-font))
;; Set font for variable-pitch mode
(set-face-attribute 'variable-pitch nil :font doom-ui-variable-pitch-font))
(when doom-ui-variable-pitch-font
(set-face-attribute 'variable-pitch nil :font doom-ui-variable-pitch-font)))
;; standardize fringe width
(fringe-mode doom-ui-fringe-size)
(push `(left-fringe . ,doom-ui-fringe-size) default-frame-alist)
@ -244,5 +82,237 @@
(set-fringe-bitmap-face 'tilde 'fringe)
(setcdr (assq 'empty-line fringe-indicator-alist) 'tilde))
(fset 'yes-or-no-p 'y-or-n-p) ; y/n instead of yes/no
(global-eldoc-mode -1) ; auto-enabled in Emacs 25+; I'd rather do this myself
;;; TODO Smart quit-confirmation prompt
;; Only prompt if there are real buffers left (see ;; `doom-real-buffer-p')
;;(setq confirm-kill-emacs
;; (lambda (_)
;; (if (ignore-errors (doom-get-real-buffers))
;; (y-or-n-p " Quit?")
;; t)))
;;; Flash the mode-line on error
;; TODO More flexible colors (only suits dark themes)
;; FIXME With a rapid key-repeat setting the mode-line bg can get stuck
(defvar doom--visual-bell-bg nil)
(setq ring-bell-function 'doom-visual-bell)
(defun doom-visual-bell ()
(unless doom--visual-bell-bg
(setq doom--visual-bell-bg (face-attribute 'mode-line :background)))
(set-face-attribute 'mode-line nil :background "#54252C")
(run-with-timer
0.1 nil
(lambda () (set-face-attribute 'mode-line nil :background doom--visual-bell-bg))))
;;; TODO/FIXME/NOTE highlighting in comments
(add-hook! (prog-mode emacs-lisp-mode css-mode)
(font-lock-add-keywords
nil '(("\\<\\(TODO\\(?:(.*)\\)?:?\\)\\>" 1 'warning prepend)
("\\<\\(FIXME\\(?:(.*)\\)?:?\\)\\>" 1 'error prepend)
("\\<\\(NOTE\\(?:(.*)\\)?:?\\)\\>" 1 'success prepend))))
;;; More reliable inter-window border
;; The native border "consumes" a pixel of the fringe on righter-most splits (in
;; Yamamoto's emacs-mac at least), `window-divider' does not.
;; NOTE available since Emacs 25.1
(setq window-divider-default-places t
window-divider-default-bottom-width 1
window-divider-default-right-width 1)
(window-divider-mode +1)
;;; Mode-line hiding minor mode
(defvar doom-hide-mode-line-format nil
"Format to use when `doom-hide-mode-line-mode' replaces the modeline")
(defvar-local doom--old-mode-line nil)
(define-minor-mode doom-hide-mode-line-mode
"Minor mode to hide the mode-line in the current buffer."
:init-value nil
:global nil
(if doom-hide-mode-line-mode
(setq doom--old-mode-line mode-line-format
mode-line-format doom-hide-mode-line-format)
(setq mode-line-format doom--old-mode-line
doom--mode-line doom-hide-mode-line-format))
(force-mode-line-update))
;; Ensure major-mode or theme changes don't overwrite these variables
(put 'doom--old-mode-line 'permanent-local t)
(put 'doom-hide-mode-line-mode 'permanent-local t)
;; mode-line is unimportant in some windows
(with-current-buffer "*Messages*" (doom-hide-mode-line-mode +1))
(add-hook! (help-mode compilation-mode messages-buffer-mode completion-list-mode)
'doom-hide-mode-line-mode)
;;
;; Plugins
;;
;; Causes a flash around the cursor when it moves across a "large" distance.
;; Usually between windows, or across files. This makes it easier to keep track
;; where your cursor is, which I find helpful on my 30" 2560x1600 display.
(package! beacon
:config (beacon-mode +1)
(setq beacon-color (let ((bg (face-attribute 'highlight :background nil t)))
(if (eq bg 'unspecified) (face-attribute 'highlight :foreground nil t) bg))
beacon-blink-when-buffer-changes t
beacon-blink-when-point-moves-vertically 10))
;; I modified the built-in `hideshow' package to be prettier, autoload when
;; needed, and to behave as much like folding in vim does as possible. A better
;; option might be `origami', but certain bugs in it are preventing the switch
;; for now.
(package! hideshow :ensure nil
:commands (hs-minor-mode hs-toggle-hiding hs-already-hidden-p)
:init
(defun doom*load-hs-minor-mode ()
(hs-minor-mode 1)
(advice-remove 'evil-toggle-fold 'doom-load-hs-minor-mode))
(advice-add 'evil-toggle-fold :before 'doom*load-hs-minor-mode)
:config
;; Prettify code folding in emacs
(defface doom-folded-face '((t (:background "#ff8")))
"Face to hightlight `hideshow' overlays."
:group 'hideshow)
(setq hs-set-up-overlay
(lambda (ov)
(when (eq 'code (overlay-get ov 'hs))
(overlay-put
ov 'display (propertize " [...] " 'face 'doom-folded-face))))))
;; Show unintrusive indentation markers, and do some whitespace voodoo to
;; prevent the lack-of-indent-guides-on-blank-lines problem.
(package! highlight-indent-guides
:commands highlight-indent-guides-mode
:config
(setq highlight-indent-guides-method 'character)
(defun doom|highlight-indent-guides-adjust-whitespace (&optional start end)
"Consider this the opposite of `delete-trailing-whitespace'. Injects
whitespace into buffer so that `highlight-indent-guides-mode' will display
consistent, unbroken indent markers. This whitespace is stripped out on save, as
not to affect the resulting file."
(interactive (progn (barf-if-buffer-read-only)
(if (use-region-p)
(list (region-beginning) (region-end))
(list nil nil))))
(unless indent-tabs-mode
(save-match-data
(save-excursion
(let ((end-marker (copy-marker (or end (point-max))))
(start (or start (point-min))))
(goto-char start)
(while (and (re-search-forward "^$" end-marker t) (not (>= (point) end-marker)))
(let (line-start line-end next-start next-end)
(save-excursion
;; Check previous line indent
(forward-line -1)
(setq line-start (point)
line-end (save-excursion (back-to-indentation) (point)))
;; Check next line indent
(forward-line 2)
(setq next-start (point)
next-end (save-excursion (back-to-indentation) (point)))
;; Back to origin
(forward-line -1)
;; Adjust indent
(let* ((line-indent (- line-end line-start))
(next-indent (- next-end next-start))
(indent (min line-indent next-indent)))
(insert (make-string (if (zerop indent) 0 (1+ indent)) ? )))))
(forward-line 1)))))
(set-buffer-modified-p nil))
nil)
(add-hook! highlight-indent-guides-mode
(if highlight-indent-guides-mode
(progn
(doom|highlight-indent-guides-adjust-whitespace)
(add-hook 'after-save-hook 'doom|highlight-indent-guides-adjust-whitespace nil t))
(remove-hook 'after-save-hook 'doom|highlight-indent-guides-adjust-whitespace t)
(delete-trailing-whitespace)))
;; If all else fails, this package tries to guess the indentation, but does it
;; naively, so get default indentation from editorconfig instead.
(defun doom*highlight-indentation-guess-offset (&rest _)
(when (featurep 'editorconfig)
(setq-local highlight-indentation-offset
(string-to-int (gethash 'indent_size (editorconfig-get-properties))))))
(advice-add 'highlight-indentation-guess-offset :before 'doom*highlight-indentation-guess-offset))
;; Some modes don't adequately highlight numbers, therefore...
(package! highlight-numbers :commands highlight-numbers-mode)
;; Line highlighting (built-in)
(package! hl-line :ensure nil
:config
;; stickiness doesn't play nice with emacs 25+
(setq hl-line-sticky-flag nil
global-hl-line-sticky-flag nil)
;; Remember whether hl-line was initially on or off in the current buffer
(defvar-local doom--hl-line-mode nil)
(defun doom|hl-line-on () (if doom--hl-line-mode (hl-line-mode +1)))
(defun doom|hl-line-off () (if doom--hl-line-mode (hl-line-mode -1)))
(add-hook! hl-line-mode (if hl-line-mode (setq doom--hl-line-mode t))))
;; A faster (or equal, in the worst case) line number plugin than `linum'. I've
;; modified it to highlight the current line, and fixed some glaring problems
;; with nlinum and frames.
(package! nlinum
:commands nlinum-mode
:preface (defvar nlinum-format "%4d ")
:init
(add-hook!
(markdown-mode prog-mode scss-mode web-mode conf-mode groovy-mode
nxml-mode snippet-mode php-mode)
'nlinum-mode)
:config
(defun doom/nlinum-toggle ()
"Toggle `nlinum-mode'."
(interactive)
(nlinum-mode (if (bound-and-true-p nlinum-mode) -1 +1)))
;; Optimization: calculate line number column width beforehand
(add-hook! nlinum-mode
(setq nlinum--width (length (save-excursion (goto-char (point-max))
(format-mode-line "%l")))))
;; Disable nlinum when making frames, otherwise we get linum face error
;; messages that prevent frame creation.
(defun doom|nlinum-off () (nlinum-mode -1))
(add-hook 'before-make-frame-hook 'doom|nlinum-off)
(add-hook 'after-make-frame-functions 'doom|nlinum-off))
;; Makes distinguishing stacked delimiters apart much, much easier. Especially
;; in parentheses-drunk languages like Lisp.
(package! rainbow-delimiters
:commands rainbow-delimiters-mode
:config (setq rainbow-delimiters-max-face-count 3)
:init
(add-hook! (emacs-lisp-mode lisp-mode js-mode css-mode c-mode-common)
'rainbow-delimiters-mode))
;; Give color codes or names a background in that color. Nifty for css. Note
;; that hl-line and rainbow-mode don't play nicely together.
(package! rainbow-mode
:commands rainbow-mode
:init (after! hl-line (add-hook 'rainbow-mode-hook 'doom|hl-line-off)))
;; This makes distractions-free mode possible, but modifying window margins on
;; the fly and centering the buffer.
(package! visual-fill-column
:config
(add-hook! visual-fill-column-mode
(setq-local split-window-preferred-function 'visual-line-mode-split-window-sensibly)))
(provide 'core-ui)
;;; core-ui.el ends here

View file

@ -1,27 +1,23 @@
;;; core-vcs.el --- version control awareness
;;; core-vcs.el
(use-package gitconfig-mode
:mode ("/\\.?git/?config$" "/\\.gitmodules$")
(package! gitconfig-mode
:mode "/\\.?git/?config$"
:mode "/\\.gitmodules$"
:init (add-hook 'gitconfig-mode-hook 'flyspell-mode))
(use-package gitignore-mode
:mode ("/\\.gitignore$"
"/\\.git/info/exclude$"
"/git/ignore$"))
(package! gitignore-mode
:mode "/\\.gitignore$"
:mode "/\\.git/info/exclude$"
:mode "/git/ignore$")
(use-package git-gutter
:commands (git-gutter-mode doom/vcs-next-hunk doom/vcs-prev-hunk
doom/vcs-show-hunk doom/vcs-stage-hunk doom/vcs-revert-hunk)
:init
(add-hook! (text-mode prog-mode conf-mode) 'git-gutter-mode)
(package! git-gutter-fringe
:commands git-gutter-mode
:init (add-hook! (text-mode prog-mode conf-mode) 'git-gutter-mode)
:config
(require 'git-gutter-fringe)
(def-popup! "^\\*git-gutter.+\\*$" :align below :size 15 :noselect t :regexp t)
;; places the git gutter outside the margins.
(setq-default fringes-outside-margins t)
;; NOTE If you want the git gutter to be on the outside of the margins (rather
;; than inside), `fringes-outside-margins' should be non-nil.
;; colored fringe "bars"
;; thin fringe bitmaps
(define-fringe-bitmap 'git-gutter-fr:added
[224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224]
nil nil 'center)
@ -32,35 +28,15 @@
[0 0 0 0 0 0 0 0 0 0 0 0 0 128 192 224 240 248]
nil nil 'center)
;; Refreshing git-gutter
;; Refreshing git-gutter on ESC and focus
(advice-add 'evil-force-normal-state :after 'git-gutter)
(add-hook 'focus-in-hook 'git-gutter:update-all-windows)
(add-hook 'focus-in-hook 'git-gutter:update-all-windows))
(defalias 'doom/vcs-next-hunk 'git-gutter:next-hunk)
(defalias 'doom/vcs-prev-hunk 'git-gutter:previous-hunk)
(defalias 'doom/vcs-show-hunk 'git-gutter:popup-hunk)
(defalias 'doom/vcs-stage-hunk 'git-gutter:stage-hunk)
(defalias 'doom/vcs-revert-hunk 'git-gutter:revert-hunk))
(use-package git-messenger
:commands git-messenger:popup-message
:init (defvar git-messenger-map (make-sparse-keymap))
(package! magit
:commands magit-status
:config
(def-popup! "*git-messenger*" :align left :size 55 :select t)
(setq git-messenger:show-detail t)
(map! :map git-messenger-map
"<escape>" 'git-messenger:popup-close
"q" 'git-messenger:popup-close))
(use-package magit
:commands (magit-status)
:config
(def-popup! "^\\*magit.+" :align below :regexp t)
;; Prevent magit + evil-snipe conflicts
(add-hook 'magit-mode-hook 'turn-off-evil-snipe-override-mode)
(require 'evil-magit)
(setq magit-display-file-buffer-function 'doom/magit-pop-to-buffer)
(map! :map magit-mode-map
;; Don't let Tab binding in my-bindings conflict with Tab in magit
@ -69,6 +45,11 @@
:nv "C-j" nil
:nv "C-k" nil))
(package! evil-magit :after magit)
(package! browse-at-remote
:commands (browse-at-remote/browse browse-at-remote/get-url))
(after! vc-annotate
(evil-set-initial-state 'vc-annotate-mode 'normal)
(evil-set-initial-state 'vc-git-log-view-mode 'normal)
@ -82,24 +63,41 @@
:n [tab] 'vc-annotate-toggle-annotation-visibility
:n "RET" 'vc-annotate-find-revision-at-line))
(use-package browse-at-remote
:commands (browse-at-remote/browse browse-at-remote/get-url))
;; Ediff
(defvar doom-ediff-enabled nil)
(add-hook! ediff-load
(setq ediff-diff-options "-w"
ediff-split-window-function 'split-window-horizontally
ediff-window-setup-function 'ediff-setup-windows-plain) ; no extra frames
;;
;; Defuns
;;
;; Brighten other buffers
(add-hook 'ediff-prepare-buffer-hook 'doom-buffer-mode)
(defun doom-git-root ()
"Get git url root."
(when-let (url (car-safe (browse-at-remote--remote-ref buffer-file-name)))
(cdr (browse-at-remote--get-url-from-remote url))))
;; TODO Custom modeline for ediff buffers
(defun doom/git-browse-issues ()
"Open the github issues page for current repo."
(interactive)
(if-let (root (doom-git-root))
(browse-url (concat root "/issues"))
(user-error "No git root found!")))
;; For modeline awareness
(add-hook! ediff-startup (setq doom-ediff-enabled t))
(add-hook! ediff-quit (setq doom-ediff-enabled nil)))
(evil-define-command doom:git-browse (&optional bang)
"Open the website for the current (or specified) version controlled FILE. If
BANG, then copy it to clipboard. Fallback to repository root."
(interactive "<!>")
(let (url)
(condition-case err
(setq url (browse-at-remote-get-url))
(error
(setq url (shell-command-to-string "hub browse -u --"))
(setq url (if url
(concat (s-trim url) "/" (f-relative (buffer-file-name) (doom-project-root))
(when (use-region-p) (format "#L%s-L%s"
(line-number-at-pos (region-beginning))
(line-number-at-pos (region-end)))))))))
(when url
(if bang
(message "Url copied to clipboard: %s" (kill-new url))
(browse-url url)))))
(provide 'core-vcs)
;;; core-vcs.el ends here

View file

@ -1,88 +0,0 @@
;;; core-workgroups.el
;; I use workgroups to accomplish two things:
;; 1. Vim-like tab emulation (type :tabs to see a list of tabs -- maybe I'll
;; add some code to make a permanent frame header to display these some
;; day)
;; 2. Session persistence (with :ss and :sl)
;; 3. Tab names reflect the project open in them, unless they've been
;; explicitly named with :tabrename <name>
(defvar doom-wg-frames '()
"A list of all the frames opened as separate workgroups. See
defuns/defuns-workgroups.el.")
(defvar doom-wg-names '()
"Keeps track of the fixed names for workgroups (set with :tabrename), so that
these workgroups won't be auto-renamed.")
(use-package workgroups2
:when window-system
:init
(setq-default
wg-session-file (concat doom-temp-dir "/workgroups/last")
wg-workgroup-directory (concat doom-temp-dir "/workgroups/")
wg-first-wg-name "*untitled*"
wg-session-load-on-start nil
wg-mode-line-display-on nil
wg-mess-with-buffer-list nil
wg-emacs-exit-save-behavior 'save ; Options: 'save 'ask nil
wg-workgroups-mode-exit-save-behavior 'save
wg-log-level 0
;; NOTE: Some of these make workgroup-restoration unstable
wg-restore-mark t
wg-restore-frame-position t
wg-restore-remote-buffers nil
wg-restore-scroll-bars nil
wg-restore-fringes nil
wg-restore-margins nil
wg-restore-point-max t ; Throws silent errors if non-nil
wg-list-display-decor-divider " "
wg-list-display-decor-left-brace ""
wg-list-display-decor-right-brace "| "
wg-list-display-decor-current-left ""
wg-list-display-decor-current-right ""
wg-list-display-decor-previous-left ""
wg-list-display-decor-previous-right "")
:config
;; Remember fixed workgroup names between sessions
(push 'doom-wg-names savehist-additional-variables)
;; `wg-mode-line-display-on' wasn't enough
(advice-add 'wg-change-modeline :override 'ignore)
;; Don't remember popup and neotree windows
(add-hook 'kill-emacs-hook 'doom|wg-cleanup)
(after! projectile
;; Create a new workgroup on switch-project
(setq projectile-switch-project-action 'doom/wg-projectile-switch-project))
;; This helps abstract some of the underlying functions away, just in case I want to
;; switch to a different package in the future, like persp-mode, eyebrowse or wconf.
(defalias 'doom/tab-display 'doom/workgroup-display)
(defalias 'doom/helm-tabs 'doom:helm-wg)
(defalias 'doom/close-window-or-tab 'doom/close-window-or-workgroup)
(defalias 'doom:tab-create 'doom:workgroup-new)
(defalias 'doom:tab-rename 'doom:workgroup-rename)
(defalias 'doom:kill-tab 'doom:workgroup-delete)
(defalias 'doom:kill-other-tabs 'doom:kill-other-workgroups)
(defalias 'doom:switch-to-tab 'doom:switch-to-workgroup-at-index)
(defalias 'doom:switch-to-tab-left 'wg-switch-to-workgroup-left)
(defalias 'doom:switch-to-tab-right 'wg-switch-to-workgroup-right)
(defalias 'doom:switch-to-tab-last 'wg-switch-to-previous-workgroup)
(add-hook! emacs-startup
(workgroups-mode +1)
(wg-create-workgroup wg-first-wg-name)))
(unless window-system
(defalias 'wg-workgroup-associated-buffers 'ignore)
(defalias 'wg-current-workgroup 'ignore)
(defalias 'wg-save-session 'ignore))
(provide 'core-workgroups)
;;; core-workgroups.el ends here

6
core/core-workspaces.el Normal file
View file

@ -0,0 +1,6 @@
;;; core-workspaces.el
(provide 'core-workspaces)
;;; core-workspaces.el ends here

View file

@ -1,53 +0,0 @@
;;; core-yasnippet.el
(use-package yasnippet
:mode ("emacs\\.d/private/\\(snippets\\|templates\\)/.+$" . snippet-mode)
:commands (yas-minor-mode
yas-minor-mode-on
yas-expand
yas-insert-snippet
yas-new-snippet
yas-visit-snippet-file)
:init
(defvar yas-minor-mode-map (make-sparse-keymap))
(setq yas-verbosity 0
yas-indent-line 'auto
yas-also-auto-indent-first-line t
yas-prompt-functions '(yas-ido-prompt yas-no-prompt)
;; Only load personal snippets
yas-snippet-dirs (list (concat doom-private-dir "/snippets")
(concat doom-private-dir "/templates")))
(add-hook! (text-mode prog-mode snippet-mode markdown-mode org-mode)
'yas-minor-mode-on)
:config
(yas-reload-all)
(map! :map yas-keymap
"C-e" 'doom/yas-goto-end-of-field
"C-a" 'doom/yas-goto-start-of-field
"<M-right>" 'doom/yas-goto-end-of-field
"<M-left>" 'doom/yas-goto-start-of-field
"<S-tab>" 'yas-prev-field
"<M-backspace>" 'doom/yas-clear-to-sof
"<escape>" 'evil-normal-state
[backspace] 'doom/yas-backspace
"<delete>" 'doom/yas-delete)
;; Fix an error caused by smartparens interfering with yasnippet bindings
(advice-add 'yas-expand :before 'sp-remove-active-pair-overlay)
;; Exit snippets on ESC in normal mode
(advice-add 'evil-force-normal-state :before 'yas-exit-all-snippets)
;; Once you're in normal mode, you're out
(add-hook 'evil-normal-state-entry-hook 'yas-abort-snippet)
;; Strip out whitespace before a line selection
(add-hook 'yas-before-expand-snippet-hook 'doom|yas-before-expand)
;; Fix previous hook persisting yas-selected-text between expansions
(add-hook 'yas-after-exit-snippet-hook 'doom|yas-after-expand))
(use-package auto-yasnippet
:commands (aya-create aya-expand aya-open-line aya-persist-snippet)
:config (setq aya-persist-snippets-dir (concat doom-private-dir "auto-snippets/")))
(provide 'core-yasnippet)
;;; core-yasnippet.el ends here

View file

@ -1,99 +1,56 @@
;;; core.el --- The heart of the beast
;;
;;; Naming conventions:
;;
;; doom-... A public variable/constant or function
;; doom--... An internal variable or function (non-interactive)
;; doom/... An autoloaded function
;; doom:... An ex command
;; doom-... A public variable or function (non-interactive use)
;; doom--... A private variable, function (non-interactive use) or macro
;; doom/... An interactive function
;; doom:... An evil operator, motion or command
;; doom|... A hook
;; doom*... An advising function
;; ...! Macro, shortcut alias or subst defun
;; @... Autoloaded interactive lambda macro for keybinds
;; ...! Macro, shortcut alias or defsubst
;; @... lambda macro for keybinds
;; +... Any of the above, but part of a module, e.g. +emacs-lisp|init-hook
;;
;;; Autoloaded functions are in {core,modules}/defuns/defuns-*.el
;; Premature optimization for faster startup
(setq-default gc-cons-threshold 339430400
gc-cons-percentage 0.6)
(when (version< emacs-version "25.1")
(error "DOOM Emacs no longer supports Emacs <25.1! Time to upgrade!"))
;;
;; Global Constants
;;
(defconst doom-version "1.3.1"
;;;
(defvar doom-version "2.0.0"
"Current version of DOOM emacs")
(defconst doom-emacs-dir
(expand-file-name user-emacs-directory)
(defvar doom-emacs-dir user-emacs-directory
"The path to this emacs.d directory")
(defconst doom-core-dir
(expand-file-name "core" doom-emacs-dir)
(defvar doom-core-dir (concat doom-emacs-dir "core/")
"Where essential files are stored")
(defconst doom-modules-dir
(expand-file-name "modules" doom-emacs-dir)
(defvar doom-modules-dir (concat doom-emacs-dir "modules/")
"Where configuration modules are stored")
(defconst doom-private-dir
(expand-file-name "private" doom-emacs-dir)
(defvar doom-private-dir (concat doom-emacs-dir "private/")
"Where private configuration filse and assets are stored (like snippets)")
(defconst doom-packages-dir
(expand-file-name
(format ".cask/%s.%s/elpa" emacs-major-version emacs-minor-version)
doom-emacs-dir)
"Where plugins are installed (by cask)")
(defconst doom-ext-dir
(expand-file-name "ext" doom-emacs-dir)
(defvar doom-scripts-dir (concat doom-emacs-dir "scripts/")
"Where external dependencies are stored (like libraries or binaries)")
(defconst doom-themes-dir
(expand-file-name "themes" doom-private-dir)
(defvar doom-packages-dir (concat doom-private-dir "packages/")
"Where package.el and quelpa plugins (and their caches) are kept.")
(defvar doom-themes-dir (concat doom-private-dir "themes/")
"Where theme files and subfolders go")
(defconst doom-temp-dir
(format "%s/cache/%s" doom-private-dir (system-name))
(defvar doom-temp-dir
(concat doom-private-dir "cache/" (system-name) "/")
"Hostname-based elisp temp directories")
(defconst doom-org-dir
(expand-file-name "~/org")
(defvar doom-org-dir "~/org/"
"Where to find org notes")
;; window-system is deprecated. Not on my watch!
(unless (boundp 'window-system)
(defvar window-system (framep-on-display)))
;;
(defconst doom-leader "," "Prefix for <leader> bindings")
(defconst doom-localleader "\\" "Prefix for <localleader> bindings")
(defvar doom-unreal-buffers
'("^ ?\\*.+" image-mode dired-mode reb-mode messages-buffer-mode
tabulated-list-mode comint-mode magit-mode)
"A list of regexps or modes whose buffers are considered unreal, and will be
ignored when using `doom:next-real-buffer' and `doom:previous-real-buffer' (or
killed by `doom/kill-unreal-buffers', or after `doom/kill-real-buffer').")
(defvar doom-cleanup-processes-alist
'(("pry" . ruby-mode)
("irb" . ruby-mode)
("ipython" . python-mode))
"An alist of (process-name . major-mode) that `doom/kill-process-buffers'
checks before killing processes. If there are no buffers with matching
major-modes, the process gets killed.")
(defvar doom-unicode-font
(font-spec :family "DejaVu Sans Mono" :size 12)
"Fallback font for unicode glyphs.")
;;
;; Core configuration
;;
;;;
;; UTF-8 as the default coding system, please
(set-charset-priority 'unicode) ; pretty
(prefer-coding-system 'utf-8) ; pretty
@ -101,93 +58,35 @@ major-modes, the process gets killed.")
(set-keyboard-coding-system 'utf-8) ; perdy
(set-selection-coding-system 'utf-8) ; please
(setq locale-coding-system 'utf-8) ; with sugar on top
(setq-default buffer-file-coding-system 'utf-8)
;; default-buffer-file-coding-system is deprecated on 23.2
(if (boundp 'buffer-file-coding-system)
(setq-default buffer-file-coding-system 'utf-8)
(setq default-buffer-file-coding-system 'utf-8))
;; Don't pester me package.el. Cask is my one and only.
(setq-default
package--init-file-ensured t
package-user-dir doom-packages-dir
package-enable-at-startup nil
package-archives
'(("gnu" . "http://elpa.gnu.org/packages/")
("melpa" . "http://melpa.org/packages/")
("org" . "http://orgmode.org/elpa/")))
;; Core settings
(setq ad-redefinition-action 'accept ; silence the advised function warnings
;; Configuration
(setq ad-redefinition-accept 'accept ; silence advised function warnings
apropos-do-all t ; make `apropos' more useful
byte-compile-warnings nil
compilation-always-kill t ; kill compl. process before spawning another
compilation-ask-about-save nil ; save all buffers before compiling
compilation-scroll-output t ; scroll with output while compiling
compilation-always-kill t
compilation-ask-about-save nil
compilation-scroll-output t
confirm-nonexistent-file-or-buffer t
delete-by-moving-to-trash t
echo-keystrokes 0.02 ; show me what I type
enable-recursive-minibuffers nil ; no minibufferception
idle-update-delay 5 ; update a little less often
major-mode 'text-mode
save-interprogram-paste-before-kill nil
sentence-end-double-space nil
;; http://ergoemacs.org/emacs/emacs_stop_cursor_enter_prompt.html
minibuffer-prompt-properties
'(read-only t point-entered minibuffer-avoid-prompt face minibuffer-prompt)
;; persistent bookmarks
bookmark-save-flag t
bookmark-default-file (concat doom-temp-dir "/bookmarks")
;; Disable backups (that's what git/dropbox are for)
history-length 1000
vc-make-backup-files nil
auto-save-default nil
enable-recursive-minibuffers nil
idle-update-delay 5
minibuffer-prompt-properties '(read-only t point-entered minibuffer-avoid-prompt face minibuffer-prompt)
save-interprogram-paste-before-kill nil)
;; History & backup settings
(setq auto-save-default nil
auto-save-list-file-name (concat doom-temp-dir "/autosave")
make-backup-files nil
backup-directory-alist (list (cons ".*" (concat doom-temp-dir "/backup/")))
create-lockfiles nil
backup-directory-alist `((".*" . ,(concat doom-temp-dir "/backup/")))
;; Remember undo history
undo-tree-auto-save-history nil
undo-tree-history-directory-alist `(("." . ,(concat doom-temp-dir "/undo/"))))
history-length 1000
make-backup-files nil
vc-make-backup-files nil)
;;
;; Bootstrap
;;
(defvar doom--load-path load-path
"Initial `load-path', used as a base so we don't clobber it on consecutive
reloads.")
(defvar doom-packages '()
"A list of all installed packages. Filled internally; do not edit it!")
;; Just the bear necessities... ♫
(setq load-path (append (list doom-core-dir) doom--load-path))
;; Populate load-path manually. This way, cask (and `cask-initialize') won't be
;; an internal dependency -- they slow down startup a lot!
(require 'core-defuns)
(let ((paths (eval-when-compile (doom-reload))))
(setq load-path (car paths)
custom-theme-load-path (nth 1 paths)
doom-packages (nth 2 paths)))
;; Many functions are lazy-loaded. The autoloads.el file contains info on where
;; to find them if they're called. Tries to generate autoloads.el if one isn't
;; found.
(unless (require 'autoloads nil t)
(doom-reload-autoloads)
(unless (require 'autoloads nil t)
(error "Autoloads weren't generated! Run `make autoloads`")))
;;
;;;
;; Automatic minor modes
;;
(defvar doom-auto-minor-mode-alist '()
"Alist of filename patterns vs corresponding minor mode functions, see
"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.")
@ -211,37 +110,105 @@ enable multiple minor modes for the same regexp.")
(add-hook 'find-file-hook 'doom|enable-minor-mode-maybe)
;;
;; Essential plugins
;;
;;;
;; Bootstrap
(setq gc-cons-threshold 339430400
gc-cons-percentage 0.6)
(require 'dash)
(require 's)
(require 'f)
(let (file-name-handler-list)
(eval-and-compile
(load (concat doom-core-dir "core-packages") nil t))
(eval-when-compile
;; Ensure cache folder exists
(unless (file-exists-p doom-temp-dir)
(make-directory doom-temp-dir t))
(doom-package-init))
(autoload 'use-package "use-package" "" nil 'macro)
(setq load-path (eval-when-compile load-path)
custom-theme-load-path (append (list doom-themes-dir) custom-theme-load-path))
(use-package anaphora
:commands (awhen aif acond awhile))
;;; Essential packages
(require 'core-lib)
(package! dash :demand t)
(package! s :demand t)
(package! f :demand t)
(use-package persistent-soft
:commands (persistent-soft-store
persistent-soft-fetch
persistent-soft-exists-p
persistent-soft-flush
persistent-soft-location-readable
persistent-soft-location-destroy)
:init (defvar pcache-directory (concat doom-temp-dir "/pcache/")))
(use-package async
;;; Helper packages (autoloaded)
(package! async
:commands (async-start
async-start-process
async-get
async-wait
async-inject-variables))
async-byte-recompile-directory))
(use-package json
:commands (json-read-from-string json-encode json-read-file))
(package! persistent-soft
:commands (persistent-soft-exists-p
persistent-soft-fetch
persistent-soft-flush
persistent-soft-store)
:init (defvar pcache-directory (concat doom-temp-dir "/pcache/")))
(package! smex :commands smex)
;;; Let 'er rip! (order matters!)
;; (require 'core-settings) ; configuration management system
;; (require 'core-popups) ; taming sudden yet inevitable windows
(require 'core-evil) ; come to the dark side, we have cookies
;; (require 'core-project)
;; (require 'core-os)
;; (require 'core-ui)
;; (require 'core-modeline)
;; (require 'core-editor)
;; (require 'core-completion)
;; (require 'core-syntax-checking)
;; (require 'core-snippets)
;; (require 'core-repl)
;; (require 'core-sessions)
;; (require 'core-workspaces)
;; (require 'core-vcs)
;; (require 'core-dashboard)
(unless (require 'autoloads nil t)
(doom/refresh-autoloads t)))
;;;
;;
(defmacro doom! (&rest packages)
(let (paths)
(dolist (p packages)
(if (memq p '(:apps :emacs :lang :lib :private :ui))
(setq mode p)
(unless mode
(error "No namespace specified on `doom!' for %s" p))
(pushnew (format "%s%s/%s/" doom-modules-dir (substring (symbol-name mode) 1) (symbol-name p))
paths)))
`(let (file-name-handler-alist)
(unless noninteractive
(load "~/.emacs.local.el" t t))
(with-demoted-errors "ERROR: %s"
,@(mapcar
(lambda (path)
(macroexp-progn
(mapcar (lambda (file)
(when noninteractive (setq file (file-name-sans-extension file)))
`(load ,(expand-file-name file path) t t (not noninteractive)))
(append (list "packages.el")
(unless noninteractive (list "config.el"))))))
paths))
(unless noninteractive
(require 'my-bindings)
(require 'my-commands)
(when (display-graphic-p)
(require 'server)
(unless (server-running-p)
(server-start)))
;; Prevent any auto-displayed text + benchmarking
(advice-add 'display-startup-echo-area-message :override 'ignore)
(message "")))))
(provide 'core)
;;; core.el ends here

View file

@ -1,23 +0,0 @@
;;; defuns-auto-insert.el
;; for ../core-auto-insert.el
;;;###autoload
(defun doom/auto-insert-snippet (key &optional mode project-only)
"Auto insert a snippet of yasnippet into new file."
(interactive)
(when (if project-only (doom/project-p) t)
(let ((is-yasnippet-on (not (cond ((functionp yas-dont-activate)
(funcall yas-dont-activate))
((consp yas-dont-activate)
(some #'funcall yas-dont-activate))
(yas-dont-activate))))
(snippet (let ((template (cdar (mapcan #'(lambda (table) (yas--fetch table key))
(yas--get-snippet-tables mode)))))
(if template (yas--template-content template) nil))))
(when (and is-yasnippet-on snippet)
(yas-expand-snippet snippet)
(when (and (featurep 'evil) evil-mode)
(evil-initialize-state 'insert))))))
(provide 'defuns-auto-insert)
;;; defuns-auto-insert.el ends here

View file

@ -1,330 +0,0 @@
;;; defuns-buffers.el
(defvar doom-buffer)
(defvar-local doom--narrowed-origin nil)
;;;###autoload (autoload 'doom:narrow "defuns-buffers" nil t)
(evil-define-operator doom:narrow (&optional beg end bang)
"Restrict editing in this buffer to the current region, indirectly. With BANG,
clone the buffer and hard-narrow the selection. If mark isn't active, then widen
the buffer (if narrowed).
Inspired from http://demonastery.org/2013/04/emacs-evil-narrow-region/"
(interactive "<r><!>")
(if (region-active-p)
(progn
(deactivate-mark)
(when bang
(let ((old-buf (current-buffer)))
(switch-to-buffer (clone-indirect-buffer nil nil))
(setq doom--narrowed-origin old-buf)))
(narrow-to-region beg end))
(if doom--narrowed-origin
(progn
(kill-this-buffer)
(switch-to-buffer doom--narrowed-origin)
(setq doom--narrowed-origin nil))
(widen))))
;;;###autoload
(defun doom/set-read-only-region (begin end)
"Mark a region as read-only (http://stackoverflow.com/questions/7410125)"
(let ((modified (buffer-modified-p)))
(add-text-properties begin end '(read-only t))
(set-buffer-modified-p modified)))
;;;###autoload
(defun doom/set-region-writeable (begin end)
"Undoes `doom/set-read-only-region' (http://stackoverflow.com/questions/7410125)"
(let ((modified (buffer-modified-p))
(inhibit-read-only t))
(remove-text-properties begin end '(read-only t))
(set-buffer-modified-p modified)))
;; Buffer Life and Death ;;;;;;;;;;;;;;;
;;;###autoload
(defun doom/get-buffers (&optional all-p)
"Get all buffers in the current project, in the current workgroup.
If ALL-P is non-nil, get all buffers across all projects in current
workgroup."
(let ((buffers (if (wg-current-workgroup t)
(doom/get-buffers-in-workgroup)
(buffer-list)))
(project-root (and (not all-p) (doom/project-root t))))
(append (if project-root
(funcall (if (eq all-p 'not) '-remove '-filter)
(lambda (b) (projectile-project-buffer-p b project-root))
buffers)
buffers)
(list doom-buffer))))
;;;###autoload
(defun doom/get-buffers-in-workgroup ()
"Get a list of buffers in current workgroup. Returns nil if workgroups2 isn't
loaded."
(when (featurep 'workgroups2)
(let ((assoc-bufs (wg-workgroup-associated-buffers nil)))
(--filter (memq it assoc-bufs) (buffer-list)))))
;;;###autoload
(defun doom/get-buffer-names (&optional buffer-list)
"Get a list of names of buffers in the current workgroup, OR return the names
of the buffers in BUFFER-LIST."
(mapcar #'buffer-name (or buffer-list (doom/get-buffers))))
;;;###autoload
(defun doom/get-visible-windows (&optional window-list)
"Get a list of the visible windows in the current frame (that aren't popups),
OR return only the visible windows in WINDOW-LIST."
(-remove #'doom/popup-p (or window-list (window-list))))
;;;###autoload
(defun doom/get-visible-buffers (&optional buffer-list)
"Get a list of unburied buffers in the current project and workgroup, OR
return only the unburied buffers in BUFFER-LIST (a list of BUFFER-OR-NAMEs)."
(-filter #'get-buffer-window (or buffer-list (doom/get-buffers))))
;;;###autoload
(defun doom/get-buried-buffers (&optional buffer-list)
"Get a list of buried buffers in the current project and workgroup, OR return
only the buried buffers in BUFFER-LIST (a list of BUFFER-OR-NAMEs)."
(-remove 'get-buffer-window (or buffer-list (doom/get-buffers))))
;;;###autoload
(defun doom/get-matching-buffers (pattern &optional buffer-list)
"Get a list of all buffers (in the current workgroup OR in BUFFER-LIST) that
match the regex PATTERN."
(--filter (string-match-p pattern (buffer-name it))
(or buffer-list (doom/get-buffers))))
;;;###autoload
(defun doom/get-buffers-in-modes (modes &optional buffer-list)
"Get a list of all buffers (in the current workgroup OR in BUFFER-LIST) whose
`major-mode' is one of MODES."
(--filter (memq (buffer-local-value 'major-mode it) modes)
(or buffer-list (doom/get-buffers))))
;;;###autoload
(defun doom/get-real-buffers (&optional buffer-list)
"Get a list of all buffers (in the current workgroup OR in BUFFER-LIST) that
`doom/real-buffer-p' returns non-nil for."
(-filter #'doom/real-buffer-p (or buffer-list (doom/get-buffers))))
;;;###autoload
(defun doom/kill-real-buffer (&optional arg)
"Kill buffer then switch to a real buffer. Only buries the buffer if it is
being displayed in another window.
NOTE: only buries scratch buffer.
See `doom/real-buffer-p' for what 'real' means."
(interactive (list t))
(let* ((scratch-p (doom-scratch-buffer-p))
(old-project (doom/project-root))
(buffer (current-buffer))
(only-buffer-window-p (= (length (get-buffer-window-list buffer nil t)) 1)))
(unless scratch-p
(when (and buffer-file-name only-buffer-window-p (buffer-modified-p))
(if (yes-or-no-p "Buffer is unsaved, save it?")
(save-buffer)
(set-buffer-modified-p nil)))
(when arg
(doom/previous-real-buffer)
(unless (eq (current-buffer) buffer)
(when only-buffer-window-p
(kill-buffer buffer)
(unless (doom/real-buffer-p)
(doom/previous-real-buffer)))))))
(when (doom-scratch-buffer-p)
(doom-scratch-force-reload))
t)
;;;###autoload
(defun doom/kill-unreal-buffers ()
"Kill all buried buffers in current frame that match any of the rules in
`doom-unreal-buffers'."
(interactive)
(let ((kill-list (-remove 'doom/real-buffer-p
(doom/get-buried-buffers (buffer-list)))))
(mapc 'kill-buffer kill-list)
(doom/kill-process-buffers)
(message "Cleaned up %s buffers" (length kill-list))))
;;;###autoload
(defun doom/kill-process-buffers ()
"Kill all buried buffers that represent running processes."
(interactive)
(let ((buffer-list (buffer-list))
(killed-processes 0))
(dolist (p (process-list))
(let* ((process-name (process-name p))
(assoc (assoc process-name doom-cleanup-processes-alist)))
(when (and assoc
(not (string= process-name "server"))
(process-live-p p)
(not (--any? (let ((mode (buffer-local-value 'major-mode it)))
(eq mode (cdr assoc)))
buffer-list)))
(delete-process p)
(incf killed-processes))))
(message "Cleaned up %s processes" killed-processes)))
;;;###autoload
(defun doom/kill-matching-buffers (pattern &optional buffer-list)
"Kill all buffers (in current workgroup OR in BUFFER-LIST) that match the
regex PATTERN."
(interactive)
(let ((i 0))
(mapc (lambda (b)
(when (string-match-p pattern (buffer-name b))
(kill-buffer b)
(setq i (1+ i))))
(if buffer-list buffer-list (doom/get-buffers)))
(message "Killed %s matches" i)))
;;;###autoload
(defun doom/cycle-real-buffers (&optional n)
"Switch to the previous buffer, skipping over special buffers. If there's
nothing left, create a scratch buffer."
(let* ((start-buffer (current-buffer))
(move-func (if (> n 0) 'switch-to-next-buffer 'switch-to-prev-buffer))
(max 25)
(i 0)
(continue t)
(buffers (doom/get-real-buffers (doom/get-buffers t)))
(fail-buffer (if (> (length (get-buffer-window-list doom-buffer nil t)) 1)
start-buffer
doom-buffer))
destbuf)
(setq destbuf
(catch 'goto
(if (or (not buffers)
(= (length buffers) 1))
(progn (message "No other buffers in workgroup")
(throw 'goto fail-buffer))
(funcall move-func)
(while (not (memq (current-buffer) buffers))
(if (or (eq (current-buffer) start-buffer)
(>= i max))
(throw 'goto fail-buffer)
(funcall move-func))
(cl-incf i))
(current-buffer))))
(when (eq destbuf doom-buffer)
(doom-scratch-reload)
(message "Nowhere to go"))
(switch-to-buffer destbuf)))
;;;###autoload
(defun doom/real-buffer-p (&optional buffer)
"Returns whether BUFFER a 'real' buffer or not. Real means: a) it isn't a
popup (or temporary) window and b) it isn't a special buffer (e.g. scratch or
*messages* buffer)."
(setq buffer (or (and (bufferp buffer) buffer)
(and (stringp buffer) (get-buffer buffer))
(current-buffer)))
(when (buffer-live-p buffer)
(with-current-buffer buffer
(not (or (apply #'derived-mode-p (-filter 'symbolp doom-unreal-buffers))
(--any? (string-match-p it (buffer-name buffer))
(-filter 'stringp doom-unreal-buffers)))))))
;;;###autoload
(defun doom/next-real-buffer ()
"Switch to the next real buffer, skipping special buffers. See
`doom/real-buffer-p'."
(interactive)
(doom/cycle-real-buffers +1))
;;;###autoload
(defun doom/previous-real-buffer ()
"Switch to the previous real buffer, skipping special buffers. See
`doom/real-buffer-p'."
(interactive)
(doom/cycle-real-buffers -1))
(defun doom--kill-buffers (buffers &optional filter-func)
(let ((buffers (if filter-func (-filter filter-func buffers) buffers))
(affected 0))
(mapc (lambda (b) (when (kill-buffer b) (incf affected))) buffers)
(unless (doom/real-buffer-p)
(doom/previous-real-buffer))
(message "Killed %s buffers" affected)))
;;;###autoload (autoload 'doom:kill-all-buffers "defuns-buffers" nil t)
(evil-define-command doom:kill-all-buffers (&optional bang)
"Kill all project buffers. If BANG, kill *all* buffers (in workgroup)."
(interactive "<!>")
(doom--kill-buffers (--filter (not (eq it doom-buffer))
(doom/get-buffers (not bang))))
(delete-other-windows)
(switch-to-buffer doom-buffer))
;;;###autoload (autoload 'doom:kill-other-buffers "defuns-buffers" nil t)
(evil-define-command doom:kill-other-buffers (&optional bang)
"Kill all other project buffers. If BANG, kill *all* other buffers (in workgroup)."
(interactive "<!>")
(doom--kill-buffers (doom/get-buffers (not bang))
(lambda (b) (not (eq b (current-buffer)))))
(when bang
(delete-other-windows)))
;;;###autoload (autoload 'doom:kill-buried-buffers "defuns-buffers" nil t)
(evil-define-command doom:kill-buried-buffers (&optional bang)
"Kill buried project buffers in current workgroup and report how many it
found. If BANG, then include buffers that aren't part of the current project."
(interactive "<!>")
(doom--kill-buffers (doom/get-buried-buffers (doom/get-buffers (not bang)))))
;;;###autoload (autoload 'doom:kill-buried-buffers "defuns-buffers" nil t)
(evil-define-command doom:kill-matching-buffers (&optional bang pattern)
"Kill project buffers in current workgroup that match regex PATTERN. If BANG,
then include buffers that aren't part of the current project."
:repeat nil
(interactive "<!><a>")
(doom--kill-buffers (doom/get-matching-buffers pattern (doom/get-buffers (not bang)))))
;;;###autoload (autoload 'doom:scratch-buffer "defuns-buffers" nil t)
(evil-define-operator doom:scratch-buffer (&optional beg end bang)
"Send a region to and pop up the scratch buffer. If BANG, don't use a popup
(use the current window)."
:move-point nil
:type inclusive
(interactive "<r><!>")
(let ((text (when (and (evil-visual-state-p) beg end)
(buffer-substring beg end)))
(mode major-mode)
(old-project (doom/project-root))
(new-buf (get-buffer-create "*doom:scratch*")))
(with-current-buffer new-buf
(setq default-directory old-project)
(setq mode-line-format (doom-modeline))
(when (and (not (eq major-mode mode))
(functionp mode))
(funcall mode))
(if text (insert text)))
(if bang (switch-to-buffer new-buf) (doom/popup-buffer new-buf))))
;;;###autoload (autoload 'doom:cd "defuns-buffers" nil t)
(evil-define-command doom:cd (dir)
"Change the `default-directory' to DIR (alias for `cd')"
:repeat nil
(interactive "<f>")
(cd (if (zerop (length dir)) "~" dir)))
;;;###autoload
(defun doom/kill-workgroup-and-quit ()
"Wipe the current workgroup session and save the blank slate."
(interactive)
(let (confirm-kill-emacs)
(mapc 'kill-buffer (doom/get-buffers t))
(kill-this-buffer)
(delete-other-windows)
(wg-save-session t)
(save-buffers-kill-terminal)))
(provide 'defuns-buffers)
;;; defuns-buffers.el ends here

View file

@ -1,70 +0,0 @@
;;; defuns-company.el
;;;###autoload
(defun doom/company-evil-complete-next (&optional arg)
"dabbrev wrapper for `evil-complete-next'"
(call-interactively 'company-dabbrev)
(if (eq company-candidates-length 1)
(company-complete)))
;;;###autoload
(defun doom/company-evil-complete-previous (&optional arg)
"dabbrev wrapper for `evil-complete-previous'"
(let ((company-selection-wrap-around t))
(call-interactively 'company-dabbrev)
(if (eq company-candidates-length 1)
(company-complete)
(call-interactively 'company-select-previous))))
;;;###autoload
(defun doom/company-complete-common-or-complete-full ()
(interactive)
(when (company-manual-begin)
(if (eq last-command #'company-complete-common-or-cycle)
(let ((company-selection-wrap-around t))
(call-interactively #'company-complete-selection))
(let ((buffer-mod-tick (buffer-chars-modified-tick)))
(call-interactively #'company-complete-common)
(when (= buffer-mod-tick (buffer-chars-modified-tick))
(call-interactively #'company-complete-selection)
(call-interactively #'company-complete))))))
(defun doom--company-whole-lines ()
(split-string
(replace-regexp-in-string
"^[\t\s]+" ""
(concat (buffer-substring-no-properties (point-min) (line-beginning-position))
(buffer-substring-no-properties (line-end-position) (point-max))))
"\\(\r\n\\|[\n\r]\\)" t))
;;;###autoload
(defun doom/company-whole-lines (command &optional arg &rest ignored)
"`company-mode' completion backend that completes whole-lines, akin to vim's
C-x C-l."
(interactive (list 'interactive))
(require 'company)
(unless (bound-and-true-p company-mode) (company-mode))
(let ((lines (doom--company-whole-lines)))
(cl-case command
(interactive (company-begin-backend 'doom/company-whole-lines))
(prefix (company-grab-line "^[\t\s]*\\(.+\\)" 1))
(candidates (all-completions arg lines)))))
;;;###autoload
(defun doom/company-dict-or-keywords ()
(interactive)
(let ((company-backends '((company-keywords company-dict))))
(call-interactively 'company-complete)))
;;;###autoload
(defun doom/company-complete ()
"Bring up the completion popup. If only one result, complete it."
(interactive)
(require 'company)
(unless (bound-and-true-p company-mode) (company-mode))
(when (and (company-manual-begin)
(= company-candidates-length 1))
(company-complete-common)))
(provide 'defuns-company)
;;; defuns-company.el ends here

View file

@ -1,31 +0,0 @@
;;; defuns-docs.el
;;;###autoload (autoload 'doom:docs-lookup "defuns-docs" nil t)
(evil-define-command doom:docs-lookup (&optional bang input)
"Look up INPUT (otherwise the current selection) in Dash or Zeal."
(interactive "<!><a>")
(let ((query input))
(when (evil-visual-state-p)
(setq query (concat (buffer-substring-no-properties (region-beginning) (region-end))
" " query)))
(when (or (not query) (zerop (length query)))
(setq query (thing-at-point 'symbol)))
(doom-docs-lookup query bang)))
;;;###autoload (autoload 'doom:google-search "defuns-docs" nil t)
(evil-define-command doom:google-search (&optional bang search)
"Opens a browser and performs the entered google search. If BANG, use 'I'm
feeling lucky'."
(interactive "<!><a>")
(if search
(google-this-parse-and-search-string
search nil
(if bang (google-this-lucky-search-url)))
(cond ((eq major-mode 'c++-mode)
(google-this-cpp-reference))
((evil-visual-state-p)
(google-this-region nil))
(t (google-this-symbol nil)))))
(provide 'defuns-docs)
;;; defuns-docs.el ends here

View file

@ -1,58 +0,0 @@
;;; defuns-editor.el
;; for ../core-editor.el
(defvar *linum-mdown-line* nil)
(defun doom--line-at-click ()
(save-excursion
(let ((click-y (cdr (cdr (mouse-position))))
(line-move-visual-store line-move-visual))
(setq line-move-visual t)
(goto-char (window-start))
(next-line (1- click-y))
(setq line-move-visual line-move-visual-store)
;; If you are using tabbar substitute the next line with
;; (line-number-at-pos))))
(1+ (line-number-at-pos)))))
;;;###autoload
(defun doom/mouse-drag-line ()
(interactive)
(goto-line (doom--line-at-click))
(set-mark (point))
(setq *linum-mdown-line* (line-number-at-pos)))
;;;###autoload
(defun doom/mouse-select-line ()
(interactive)
(when *linum-mdown-line*
(let (mu-line)
(setq mu-line (doom--line-at-click))
(goto-line *linum-mdown-line*)
(if (> mu-line *linum-mdown-line*)
(progn
(set-mark (point))
(goto-line mu-line)
(end-of-line))
(set-mark (line-end-position))
(goto-line mu-line)
(beginning-of-line))
(setq *linum-mdown-line* nil))))
;;;###autoload
(defun doom/reselect-paste ()
"Go back into visual mode and reselect the last pasted region."
(interactive)
(evil-goto-mark ?\[)
(evil-visual-state)
(evil-goto-mark ?\]))
;;;###autoload
(defun doom/delete-forward-word ()
"Delete the word in front of the cursor."
(interactive)
(evil-forward-word)
(evil-delete-backward-word))
(provide 'defuns-editor)
;;; defuns-editor.el ends here

View file

@ -1,35 +0,0 @@
;;; defuns-embrace.el
(defun doom--embrace-get-pair (char)
(acond ((cdr-safe (assoc (string-to-char char) evil-surround-pairs-alist))
`(,(car it) . ,(cdr it)))
((assoc-default char embrace--pairs-list)
(if (functionp (embrace-pair-struct-read-function it))
(let ((pair (funcall (embrace-pair-struct-read-function it))))
`(,(car pair) . ,(cdr pair)))
`(,(embrace-pair-struct-left it) . ,(embrace-pair-struct-right it))))
(t `(,char . ,char))))
;;;###autoload
(defun doom/embrace-escaped ()
"Backslash-escaped surround character support for embrace."
(let ((char (read-char "\\")))
(if (eq char 27)
(cons "" "")
(let ((pair (doom--embrace-get-pair (string char)))
(text (if (sp-point-in-string) "\\\\%s" "\\%s")))
(cons (format text (car pair))
(format text (cdr pair)))))))
;;;###autoload
(defun doom/embrace-latex ()
"LaTeX command support for embrace."
(cons (format "\\%s{" (read-string "\\")) "}"))
;;;###autoload
(defun doom/embrace-elisp-fn ()
"Elisp function support for embrace."
(cons (format "(%s " (or (read-string "(") "")) ")"))
(provide 'defuns-embrace)
;;; defuns-embrace.el ends here

View file

@ -1,253 +0,0 @@
;;; defuns-evil.el
;;;###autoload (autoload 'doom/evil-open-folds "defuns-evil" nil t)
(evil-define-command doom/evil-open-folds (count)
"Instead of `evil-open-folds'; accepts COUNT for dictating fold level."
(interactive "P")
(unless (bound-and-true-p hs-minor-mode)
(hs-minor-mode 1))
(if count (hs-hide-level count) (evil-open-folds)))
;;;###autoload (autoload 'doom/evil-close-folds "defuns-evil" nil t)
(evil-define-command doom/evil-close-folds (count)
"Instead of `evil-close-folds'; accepts COUNT for dictating fold level."
(interactive "P")
(unless (bound-and-true-p hs-minor-mode)
(hs-minor-mode 1))
(if count (hs-hide-level count) (evil-close-folds)))
;;;###autoload (autoload 'doom/multi-next-line "defuns-evil" nil t)
(evil-define-motion doom/multi-next-line (count)
"Move down 6 lines."
:type line
(let ((line-move-visual visual-line-mode))
(evil-line-move (* 6 (or count 1)))))
;;;###autoload (autoload 'doom/multi-previous-line "defuns-evil" nil t)
(evil-define-motion doom/multi-previous-line (count)
"Move up 6 lines."
:type line
(let ((line-move-visual visual-line-mode))
(evil-line-move (- (* 6 (or count 1))))))
;;;###autoload
(defun doom/evil-visual-line-state-p ()
"Returns non-nil if in visual-line mode, nil otherwise."
(and (evil-visual-state-p)
(eq (evil-visual-type) 'line)))
;;;###autoload
(defun doom*evil-exchange-off ()
(when evil-exchange--overlays
(evil-exchange-cancel)))
;;;###autoload (autoload 'doom/evil-macro-on-all-lines "defuns-evil" nil t)
(evil-define-operator doom/evil-macro-on-all-lines (beg end &optional macro)
"Apply macro to each line."
:motion nil
:move-point nil
(interactive "<r><a>")
(unless (and beg end)
(setq beg (region-beginning)
end (region-end)))
(evil-ex-normal beg end
(concat "@"
(single-key-description
(or macro (read-char "@-"))))))
;;; Custom argument handlers
(defvar doom-buffer-match-global evil-ex-substitute-global "")
(defun doom--evil-ex-match-init (name &optional face update-hook)
(with-current-buffer evil-ex-current-buffer
(cond
((eq flag 'start)
(evil-ex-make-hl name
:face (or face 'evil-ex-substitute-matches)
:update-hook (or update-hook #'evil-ex-pattern-update-ex-info))
(setq flag 'update))
((eq flag 'stop)
(evil-ex-delete-hl name)))))
(defun doom--evil-ex-buffer-match (arg &optional hl-name flags beg end)
(when (and (eq flag 'update)
evil-ex-substitute-highlight-all
(not (zerop (length arg))))
(condition-case lossage
(let ((pattern (evil-ex-make-substitute-pattern
(if evil-ex-bang (regexp-quote arg) arg)
(or flags (list))))
(range (or (evil-copy-range evil-ex-range)
(evil-range (or beg (line-beginning-position))
(or end (line-end-position))
'line
:expanded t))))
(evil-expand-range range)
(evil-ex-hl-set-region hl-name
(max (evil-range-beginning range) (window-start))
(min (evil-range-end range) (window-end)))
(evil-ex-hl-change hl-name pattern))
(end-of-file
(evil-ex-pattern-update-ex-info nil "incomplete replacement"))
(user-error
(evil-ex-pattern-update-ex-info nil (format "?%s" lossage))))))
;;;###autoload
(defun doom/evil-ex-buffer-match (flag &optional arg)
(let ((hl-name 'evil-ex-buffer-match))
(with-selected-window (minibuffer-selected-window)
(doom--evil-ex-match-init hl-name)
(doom--evil-ex-buffer-match arg hl-name (list (if doom-buffer-match-global ?g))))))
;;;###autoload
(defun doom/evil-ex-global-match (flag &optional arg)
(let ((hl-name 'evil-ex-global-match))
(with-selected-window (minibuffer-selected-window)
(doom--evil-ex-match-init hl-name)
(let ((result (car-safe (evil-ex-parse-global arg))))
(doom--evil-ex-buffer-match result hl-name nil (point-min) (point-max))))))
;;;###autoload
(defun doom/evil-ex-undefine-cmd (cmd)
(if (string-match "^[^][]*\\(\\[\\(.*\\)\\]\\)[^][]*$" cmd)
(let ((abbrev (replace-match "" nil t cmd 1))
(full (replace-match "\\2" nil nil cmd 1)))
(setq evil-ex-commands (delq (assoc full evil-ex-commands) evil-ex-commands))
(setq evil-ex-commands (delq (assoc abbrev evil-ex-commands) evil-ex-commands)))
(setq evil-ex-commands (delq (assoc cmd evil-ex-commands) evil-ex-commands))))
(defvar doom:map-maps '())
;;;###autoload (autoload 'doom:map "defuns-evil" nil t)
(evil-define-command doom:map (bang input &optional mode)
"Map ex commands to keybindings. INPUT should be in the format [KEY] [EX COMMAND]."
(interactive "<!><a>")
(let* ((parts (s-split-up-to " " input 2 t))
(mode (or mode 'normal))
(key (kbd (car parts)))
(command (s-join " " (cdr parts)))
(map (cl-case mode
('normal evil-normal-state-local-map)
('insert evil-insert-state-local-map)
('visual evil-visual-state-local-map)
('motion evil-motion-state-local-map)
('operator evil-operator-state-local-map)))
(fn `(lambda () (interactive) (evil-ex-eval ,command))))
(if bang
(evil-define-key mode nil key fn)
(define-key map key fn))))
;;;###autoload (autoload 'doom:nmap "defuns-evil" nil t)
(evil-define-command doom:nmap (bang input &optional mode)
(interactive "<!><a>") (doom:map bang input 'normal))
;;;###autoload (autoload 'doom:imap "defuns-evil" nil t)
(evil-define-command doom:imap (bang input &optional mode)
(interactive "<!><a>") (doom:map bang input 'insert))
;;;###autoload (autoload 'doom:vmap "defuns-evil" nil t)
(evil-define-command doom:vmap (bang input &optional mode)
(interactive "<!><a>") (doom:map bang input 'visual))
;;;###autoload (autoload 'doom:mmap "defuns-evil" nil t)
(evil-define-command doom:mmap (bang input &optional mode)
(interactive "<!><a>") (doom:map bang input 'motion))
;;;###autoload (autoload 'doom:omap "defuns-evil" nil t)
(evil-define-command doom:omap (bang input &optional mode)
(interactive "<!><a>") (doom:map bang input 'operator))
;;;###autoload
(defun doom/evil-snipe-easymotion ()
(interactive)
(require 'evil-easymotion)
(call-interactively doom--evil-snipe-repeat-fn))
;;;###autoload
(defun doom/evil-matchit ()
(interactive)
(if (ignore-errors (hs-already-hidden-p))
(hs-toggle-hiding)
(call-interactively 'evilmi-jump-items)))
;;;###autoload
(defun doom*evil-command-window (hist cmd-key execute-fn)
"The evil command window has a mind of its own (uses `switch-to-buffer'). We
monkey patch it to use pop-to-buffer."
(when (eq major-mode 'evil-command-window-mode)
(user-error "Cannot recursively open command line window"))
(dolist (win (window-list))
(when (equal (buffer-name (window-buffer win))
"*Command Line*")
(kill-buffer (window-buffer win))
(delete-window win)))
(setq evil-command-window-current-buffer (current-buffer))
(ignore-errors (kill-buffer "*Command Line*"))
(with-current-buffer (pop-to-buffer "*Command Line*")
(setq-local evil-command-window-execute-fn execute-fn)
(setq-local evil-command-window-cmd-key cmd-key)
(evil-command-window-mode)
(evil-command-window-insert-commands hist)))
;;;###autoload
(defun doom*evil-esc-quit ()
"Close popups, disable search highlights and quit the minibuffer if open."
(let ((minib-p (minibuffer-window-active-p (minibuffer-window)))
(evil-hl-p (evil-ex-hl-active-p 'evil-ex-search)))
(when minib-p (abort-recursive-edit))
(when evil-hl-p (evil-ex-nohighlight))
;; Close non-repl popups and clean up `doom-popup-windows'
(unless (or minib-p evil-hl-p)
(doom/popup-close-all))))
;;;###autoload
(defun doom*evil-ex-replace-special-filenames (file-name)
"Replace special symbols in FILE-NAME."
(let ((regexp (concat "\\(?:^\\|[^\\\\]\\)"
"\\([#%@]\\)"
"\\(\\(?::\\(?:[phtreS~.]\\|g?s[^: $]+\\)\\)*\\)"))
case-fold-search)
(dolist (match (s-match-strings-all regexp file-name))
(let ((flags (split-string (caddr match) ":" t))
(path (file-relative-name
(pcase (cadr match)
("@" (doom/project-root))
("%" (buffer-file-name))
("#" (and (other-buffer) (buffer-file-name (other-buffer)))))
default-directory))
flag global)
(when path
(while flags
(setq flag (pop flags))
(when (string-suffix-p "\\" flag)
(setq flag (concat flag (pop flags))))
(when (string-prefix-p "gs" flag)
(setq global t
flag (string-remove-prefix "g" flag)))
(setq path
(or (pcase (substring flag 0 1)
("p" (expand-file-name path))
("~" (file-relative-name path "~"))
("." (file-relative-name path default-directory))
("h" (directory-file-name path))
("t" (file-name-nondirectory (directory-file-name path)))
("r" (file-name-sans-extension path))
("e" (file-name-extension path))
("s" (let* ((args (evil-delimited-arguments (substring flag 1) 2))
(pattern (evil-transform-vim-style-regexp (car args)))
(replace (cadr args)))
(replace-regexp-in-string
(if global pattern (concat "\\(" pattern "\\).*\\'"))
(evil-transform-vim-style-regexp replace) path t t
(unless global 1))))
("S" (shell-quote-argument path))
(_ path))
"")))
(setq file-name
(replace-regexp-in-string (format "\\(?:^\\|[^\\\\]\\)\\(%s\\)"
(string-trim-left (car match)))
path file-name t t 1)))))
(setq file-name (replace-regexp-in-string regexp "\\1" file-name t))))
(provide 'defuns-evil)
;;; defuns-evil.el ends here

View file

@ -1,72 +0,0 @@
;;; defuns-file.el
;;;###autoload (autoload 'doom:file-delete "defuns-file" nil t)
(evil-define-command doom:file-delete (&optional bang filename)
"Delete current buffer's file. If BANG, kill buffer afterwards."
:repeat nil
(interactive "<!><f>")
(let ((filename (file-truename (or filename (buffer-file-name)))))
(if (not (file-exists-p filename))
(error "File doesn't exist: %s" filename)
(when (or bang (and (not bang) (y-or-n-p (format "Delete %s?" (f-base filename)))))
(set-buffer-modified-p nil)
(delete-file filename)
(kill-this-buffer)
(unless (doom/real-buffer-p)
(doom/previous-real-buffer))
(save-place-forget-unreadable-files)
(message "File successfully deleted: %s" filename)))))
(defun doom--save-exit() (save-buffer) (kill-buffer) (remove-hook 'yas-after-exit-snippet-hook '--save-exit))
;;;###autoload (autoload 'doom:file-create "defuns-file" nil t)
(evil-define-command doom:file-create (path &optional bang)
"Deploy files (and their associated templates) quickly. Will prompt
you to fill in each snippet field before buffer closes unless BANG is
provided."
:repeat nil
(interactive "<f><!>")
(let ((dir (f-dirname path))
(fullpath (f-full path))
(is-auto t))
(when (and bang (not (f-exists? dir)))
(mkdir dir))
(if (f-exists? dir)
(if (f-exists? fullpath)
(error "File already exists: %s" path)
(find-file fullpath)
(add-hook 'yas-after-exit-snippet-hook 'doom--save-exit)
(if bang (doom--save-exit)))
(error "Directory doesn't exist: %s" dir))))
;;;###autoload (autoload 'doom:file-move "defuns-file" nil t)
(evil-define-command doom:file-move (path)
"Move current buffer's file to PATH. Replaces %, # and other variables (see
`evil-ex-replace-special-filenames')"
:repeat nil
(interactive "<f>")
(let* ((old-path (buffer-file-name))
(new-path (cond ((f-dir? path)
(f-expand (f-filename old-path) path))
((f-dir? (f-dirname path))
(f-full path))
(t (user-error "Not a valid destination: %s" path))))
(project-root (doom/project-root)))
;; Move all attachments if in org-mode
(when (eq major-mode 'org-mode)
(mapc (lambda (file)
(when (and (file-exists-p file) (not (f-same? old-path new-path)))
(rename-file file (f-expand (f-filename old-path) (f-dirname new-path)) t)))
(doom/org-attachments)))
(when (buffer-modified-p)
(save-buffer))
(rename-file old-path new-path 1)
(rename-buffer (f-filename new-path))
(set-visited-file-name new-path)
(set-buffer-modified-p nil)
(save-place-forget-unreadable-files)
(setq doom--spaceline-file-path nil)
(message "File '%s' successfully renamed to '%s'"
(f-relative old-path project-root) (f-relative new-path project-root))))
(provide 'defuns-file)
;;; defuns-file.el ends here

View file

@ -1,33 +0,0 @@
;;; defuns-flycheck.el
;; for ../core-flycheck.el
;;;###autoload
(defun doom*flycheck-buffer ()
(when (bound-and-true-p flycheck-mode)
(flycheck-buffer)))
;;;###autoload
(defun doom/flycheck-next-error ()
(interactive)
(call-interactively
(if (bound-and-true-p flycheck-mode)
'flycheck-next-error
'next-error)))
;;;###autoload
(defun doom/flycheck-previous-error ()
(interactive)
(call-interactively
(if (bound-and-true-p flycheck-mode)
'flycheck-previous-error
'previous-error)))
;;;###autoload
(defun doom/flycheck-errors ()
(interactive)
(when (bound-and-true-p flycheck-mode)
(flycheck-buffer)
(flycheck-list-errors)))
(provide 'defuns-flycheck)
;;; defuns-flycheck.el ends here

View file

@ -1,41 +0,0 @@
;;; defuns-git.el
;;;###autoload
(defun doom/git-root ()
(awhen (car-safe (browse-at-remote/remote-ref buffer-file-name))
(cdr (browse-at-remote/get-url-from-remote it))))
;;;###autoload
(defun doom/git-issues ()
"Open the github issues page for current repo."
(interactive)
(awhen (doom/git-root)
(browse-url (concat it "/issues"))))
;;;###autoload
(defun doom/git-magit ()
(interactive)
(call-interactively 'magit-status))
;;;###autoload (autoload 'doom:git-browse "defuns-git" nil t)
(evil-define-command doom:git-browse (&optional bang)
"Open the website for the current (or specified) version controlled FILE. If
BANG, then use hub to do it."
(interactive "<!>")
(let (url)
(condition-case err
(setq url (browse-at-remote/get-url))
(error
(setq url (shell-command-to-string "hub browse -u --"))
(setq url (if url
(concat (s-trim url) "/" (f-relative (buffer-file-name) (doom/project-root))
(when (use-region-p) (format "#L%s-L%s"
(line-number-at-pos (region-beginning))
(line-number-at-pos (region-end)))))))))
(when url
(if bang
(message "Url copied to clipboard: %s" (kill-new url))
(browse-url url)))))
(provide 'defuns-git)
;;; defuns-git.el ends here

View file

@ -1,90 +0,0 @@
;;; defuns-helm.el
;;;###autoload (autoload 'doom:helm-recentf "defuns-helm" nil t)
(evil-define-command doom:helm-recentf (&optional bang)
"Ex-mode interface for `helm-recentf' and `helm-projectile-recentf'."
:repeat nil
(interactive "<!>")
(if bang (helm-recentf) (helm-projectile-recentf)))
;; Ex-mode interface for `helm-ag'. If `bang', then `search' is interpreted as
;; regexp.
;;;###autoload (autoload 'doom:helm-ag-search "defuns-helm" nil t)
(evil-define-operator doom:helm-ag-search (beg end search regex-p &optional dir)
"Preform an helm-ag search with SEARCH. If SEARCH is nil and in visual mode, use the
selection, otherwise activate live ag searching in helm.
If REGEX-P is non-nil, SEARCH will be treated as a regular expression.
DIR specifies the default-directory from which ag is run."
:type inclusive
:repeat nil
(interactive "<r><a><!>")
(require 'helm-ag)
(let* ((helm-ag--default-directory (or dir (f-slash (doom/project-root))))
(helm-ag-command-option (unless regex-p "-Q "))
(input "")
(header-name (format "Search in %s" helm-ag--default-directory)))
(if search
(progn
(helm-attrset 'search-this-file nil helm-ag-source)
(setq helm-ag--last-query search))
(if (and beg end (/= beg (1- end)))
(setq input (buffer-substring-no-properties beg end))))
(helm-attrset 'name header-name helm-ag-source)
(helm :sources (if search helm-ag-source '(helm-source-do-ag))
:buffer "*helm-ag*"
:keymap helm-ag-map
:input input)))
;; Ex-mode interface for `helm-do-ag'. If `bang', then `search' is interpreted
;; as regexp
;;;###autoload (autoload 'doom:helm-ag-search-cwd "defuns-helm" nil t)
(evil-define-operator doom:helm-ag-search-cwd (beg end &optional search bang)
:type inclusive :repeat nil
(interactive "<r><a><!>")
(doom:helm-ag-search beg end search bang default-directory))
;; Ex-mode interface for `helm-swoop', `helm-multi-swoop-all' (if `bang'), or
;; `helm-css-scss' and `helm-css-scss-multi' (if `bang') if major-mode is
;; `scss-mode'
;;;###autoload (autoload 'doom:helm-swoop "defuns-helm" nil t)
(evil-define-command doom:helm-swoop (&optional search bang)
:repeat nil
(interactive "<a><!>")
(if bang (helm-multi-swoop-all search) (helm-swoop :$query search)))
;;;###autoload
(defun doom/helm-buffers-dwim (&optional all-p)
"Displays open buffers in current project. If ALL-P, then show all open
buffers."
(interactive)
(let ((doom-helm-force-project-buffers (and (not all-p) (doom/project-p))))
(helm-buffers-list)))
;;;###autoload
(defun doom*helm-replace-prompt (plist)
(if (keywordp (car plist))
(setq plist (plist-put plist :prompt helm-global-prompt))
(setcar (nthcdr 2 plist) helm-global-prompt))
plist)
;;;###autoload
(defun doom*helm-hide-header (source &optional force)
(doom-hide-mode-line-mode +1))
;;;###autoload
(defun doom*helm-hide-source-header-maybe ()
(if (<= (length helm-sources) 1)
(set-face-attribute 'helm-source-header nil :height 0.1 :foreground "#111111")
(set-face-attribute 'helm-source-header nil :height 1.0 :foreground doom-helm-header-fg)))
(defvar doom-helm-force-project-buffers nil
"If non-nil, helm-buffers-list will only show project buffers.")
;;;###autoload
(defun helm*buffer-list (&rest _)
(append (doom/get-buffer-names doom-helm-force-project-buffers)
(list doom-buffer-name)))
(provide 'defuns-helm)
;;; defuns-helm.el ends here

View file

@ -1,45 +0,0 @@
;;; defuns-highlight-indentation.el
;;;###autoload
(defun doom/add-whitespace (&optional start end)
"Maintain indentation whitespace in buffer. Used so that highlight-indentation will
display consistent guides. Whitespace is stripped out on save, so this doesn't affect the
end file."
(interactive (progn (barf-if-buffer-read-only)
(if (use-region-p)
(list (region-beginning) (region-end))
(list nil nil))))
(unless indent-tabs-mode
(save-match-data
(save-excursion
(let ((end-marker (copy-marker (or end (point-max))))
(start (or start (point-min))))
(goto-char start)
(while (and (re-search-forward "^$" end-marker t) (not (>= (point) end-marker)))
(let (line-start line-end next-start next-end)
(save-excursion
;; Check previous line indent
(forward-line -1)
(setq line-start (point)
line-end (save-excursion (back-to-indentation) (point)))
;; Check next line indent
(forward-line 2)
(setq next-start (point)
next-end (save-excursion (back-to-indentation) (point)))
;; Back to origin
(forward-line -1)
;; Adjust indent
(let* ((line-indent (- line-end line-start))
(next-indent (- next-end next-start))
(indent (min line-indent next-indent)))
(insert (make-string (if (zerop indent) 0 (1+ indent)) ? )))))
(forward-line 1)))))
(set-buffer-modified-p nil))
nil)
;;;###autoload
(defun doom*hl-indent-guess-offset ()
(string-to-int (gethash 'indent_size (editorconfig-get-properties))))
(provide 'defuns-highlight-indentation)
;;; defuns-highlight-indentation.el ends here

View file

@ -1,60 +0,0 @@
;;; defuns-ido.el
;;;###autoload
(defun doom*ido-sort-mtime ()
"Sort ido filelist by mtime instead of alphabetically."
(setq ido-temp-list
(sort ido-temp-list
(lambda (a b)
(ignore-errors
(time-less-p
(sixth (file-attributes (concat ido-current-directory b)))
(sixth (file-attributes (concat ido-current-directory a))))))))
(ido-to-end ;; move . files to end (again)
(delq nil (mapcar
(lambda (x) (and (char-equal (string-to-char x) ?.) x))
ido-temp-list))))
;;;###autoload
(defun doom|ido-setup-home-keybind ()
"Go to $HOME with ~"
(define-key ido-file-completion-map (kbd "~")
(λ! (if (looking-back "/")
(insert "~/")
(call-interactively 'self-insert-command)))))
;;;###autoload
(defun doom/ido-find-file (&optional dir)
(interactive)
(let ((default-directory (or dir default-directory)))
(ido-find-file)))
;;;###autoload
(defun doom/ido-find-file-other-window (&optional dir)
(interactive)
(let ((default-directory (or dir default-directory)))
(ido-find-file-other-window)))
;;;###autoload
(defun doom/ido-find-project-file ()
(interactive)
(let ((default-directory (doom/project-root)))
(ido-find-file)))
;;;###autoload
(defun doom/ido-recentf ()
"Use `ido-completing-read' to \\[find-file] a recent file"
(interactive)
(if (find-file (ido-completing-read "Find recent file: " recentf-list))
(message "Opening file...")
(message "Aborting")))
;;;###autoload (autoload 'doom:ido-find-file-in-emacsd "defuns-ido" nil t)
(evil-define-command doom:ido-find-file-in-emacsd (&optional bang) :repeat nil
(interactive "<!>")
(if bang
(ido-find-file-in-dir doom-modules-dir)
(ido-find-file-in-dir doom-emacs-dir)))
(provide 'defuns-ido)
;;; defuns-ido.el ends here

View file

@ -1,140 +0,0 @@
;;; defuns-ivy.el
;; Show more information in ivy-switch-buffer; and only display
;; project/workgroup-relevant buffers.
(defun doom-ivy-get-buffers (&optional buffer-list)
(let ((min-name 5)
(min-mode 5)
(proot (doom/project-root)))
(mapcar
(lambda (b) (format (format "%%-%ds %%-%ds %%s" min-name min-mode)
(nth 0 b)
(nth 1 b)
(or (nth 2 b) "")))
(mapcar (lambda (b)
(with-current-buffer b
(let ((buffer-name (buffer-name b))
(mode-name (symbol-name major-mode)))
(when (> (length buffer-name) min-name)
(setq min-name (+ (length buffer-name) 10)))
(when (> (length mode-name) min-mode)
(setq min-mode (+ (length mode-name) 3)))
(list
(concat
(propertize buffer-name
'face (cond ((string-match-p "^ ?\\*" buffer-name)
'font-lock-comment-face)
((not (string= proot (doom/project-root)))
'font-lock-keyword-face)
(buffer-read-only
'error)))
(when (and buffer-file-name (buffer-modified-p))
(propertize "[+]" 'face 'doom-modeline-buffer-modified)))
(propertize mode-name 'face 'font-lock-constant-face)
(when buffer-file-name
(f-slash (abbreviate-file-name (f-dirname buffer-file-name))))))))
(or buffer-list (doom/get-buffers))))))
(defun doom--ivy-select-buffer-action (buffer)
(ivy--switch-buffer-action
(s-chop-suffix
"[+]"
(substring buffer 0 (s-index-of " " buffer)))))
;;;###autoload
(defun doom/ivy-switch-project-buffer (&optional all-p)
"Displays open buffers in current project and workspace. If ALL-P, then show
all open buffers."
(interactive)
(ivy-read (format "%s buffers: " (if all-p "All" "Project"))
(doom-ivy-get-buffers (if all-p (buffer-list)))
:matcher #'ivy--switch-buffer-matcher
:action #'doom--ivy-select-buffer-action
:keymap ivy-switch-buffer-map
:caller 'doom/ivy-switch-project-buffer))
;;;###autoload
(defun doom/ivy-switch-buffer ()
"Displays all open buffers, across projects and workspaces."
(interactive)
(doom/ivy-switch-project-buffer t))
;;;###autoload
(defun doom/ivy-kill-ring ()
(interactive)
(ivy-read "Kill ring:" (--filter (not (or (< (length it) 3)
(string-match-p "\\`[\n[:blank:]]+\\'" it)))
(remove-duplicates kill-ring :test 'equal))))
;;;###autoload (autoload 'doom:ivy-recentf "defuns-ivy" nil t)
(evil-define-command doom:ivy-recentf (&optional bang)
"Ex-mode interface for `ivy-recentf' and `projectile-recentf'."
:repeat nil
(interactive "<!>")
(if bang (ivy-recentf) (projectile-recentf)))
;;;###autoload (autoload 'doom:ivy-swiper "defuns-ivy" nil t)
(evil-define-command doom:ivy-swiper (&optional search)
(interactive "<a>")
(swiper (or search (thing-at-point 'symbol))))
(defvar doom-ivy-ag-last-search nil)
;;;###autoload (autoload 'doom:ivy-ag-search "defuns-ivy" nil t)
(evil-define-operator doom:ivy-ag-search (beg end search regex-p &optional dir)
"Preform a counsel search with SEARCH. If SEARCH is nil and in visual mode,
use the selection, otherwise activate live ag searching in helm.
If REGEX-P is non-nil, SEARCH will be treated as a regular expression.
DIR specifies the default-directory from which ag is run."
:type inclusive :repeat nil
(interactive "<r><a><!>")
(let ((search (or search
(and (evil-visual-state-p)
(and beg end (rxt-quote-pcre (buffer-substring-no-properties beg end))))
doom-ivy-ag-last-search)))
(setq doom-ivy-ag-last-search search)
(counsel-ag search (or dir (f-slash (doom/project-root)))
(concat "--nocolor --nogroup" (if regex-p " -Q")))))
;;;###autoload (autoload 'doom:ivy-ag-search-cwd "defuns-ivy" nil t)
(evil-define-operator doom:ivy-ag-search-cwd (beg end search regex-p)
:type inclusive :repeat nil
(interactive "<r><a><!>")
(doom:ivy-ag-search beg end search regex-p default-directory))
;;;###autoload
(defun doom/ivy-tasks ()
(interactive)
;; TODO Something a little nicer
(counsel-ag " (TODO|FIXME|NOTE) " (doom/project-root)))
;;;###autoload
(defun doom*counsel-ag-function (string base-cmd extra-ag-args)
"Advice to get rid of the character limit from `counsel-ag-function', which
interferes with my custom :ag ex command `doom:ivy-ag-search'."
(when (null extra-ag-args)
(setq extra-ag-args ""))
(if (< (length string) 1)
(counsel-more-chars 1)
(let ((default-directory counsel--git-grep-dir)
(regex (counsel-unquote-regex-parens
(setq ivy--old-re
(ivy--regex string)))))
(let ((ag-cmd (format base-cmd
(concat extra-ag-args
" -- "
(shell-quote-argument regex)))))
(if (file-remote-p default-directory)
(split-string (shell-command-to-string ag-cmd) "\n" t)
(counsel--async-command ag-cmd)
nil)))))
;;;###autoload
(defun doom/counsel-ag-occur ()
"Invoke the search+replace wgrep buffer on the current ag search results."
(interactive)
(require 'wgrep)
(call-interactively 'ivy-occur))
(provide 'defuns-ivy)
;;; defuns-ivy.el ends here

View file

@ -1,13 +0,0 @@
;;; defuns-magit.el
;;;###autoload
(defun doom/magit-pop-to-buffer (buffer)
"Pop to buffer in non-magit buffer."
(let (pt)
(doom/popup-save
(pop-to-buffer buffer)
(setq pt (point)))
(goto-char pt)))
(provide 'defuns-magit)
;;; defuns-magit.el ends here

View file

@ -1,55 +0,0 @@
;;; defuns-neotree.el
;; for ../core-project.el
;;;###autoload
(defun doom/neotree ()
"Toggle the neotree window"
(interactive)
(let ((in-neotree (and (neo-global--window-exists-p)
(window-live-p neo-global--buffer)
(eq (current-buffer) neo-global--buffer)))
(path buffer-file-name))
(if in-neotree
(neotree-hide)
(let ((project-root (doom/project-root)))
(unless (and (neo-global--window-exists-p)
(f-same? (neo-global--with-buffer neo-buffer--start-node) project-root))
(neotree-dir project-root))
(neotree-find path project-root)))))
;;;###autoload
(defun doom/neotree-close ()
(interactive)
(when (neo-global--window-exists-p)
(with-selected-window neo-global--window
(evil-window-delete))))
;;;###autoload
(defmacro doom/neotree-save (&rest body)
`(let ((neo-p (neo-global--window-exists-p)))
(when neo-p (doom/neotree-close))
,@body
(when neo-p
(save-selected-window
(neotree-show)))))
;;;###autoload
(defun doom|neotree-close-on-window-change (&rest _)
"Close neotree to prevent ensuing mindow buggery."
(unless (and (neo-global--window-exists-p)
(eq (current-buffer) (neo-global--get-buffer)))
(neotree-hide)))
;;;###autoload
(defun doom*save-neotree (orig-fun &rest args)
"Prevents messing up the neotree buffer on window changes"
(doom/neotree-save (apply orig-fun args)))
;;;###autoload
(defun doom*neotree-create-node (orig-fun &rest args)
"Don't ask for confirmation when creating files"
(cl-letf (((symbol-function 'yes-or-no-p) (lambda (&rest _) t)))
(apply orig-fun args)))
(provide 'defuns-neotree)
;;; defuns-neotree.el ends here

View file

@ -1,50 +0,0 @@
;;; defuns-nlinum.el
;;;###autoload
(defun doom/nlinum-toggle ()
(interactive)
(if (bound-and-true-p nlinum-mode)
(doom|nlinum-disable)
(doom|nlinum-enable)))
;;;###autoload
(defun doom|nlinum-enable (&rest _)
(nlinum-mode +1)
(add-hook 'post-command-hook 'doom|nlinum-hl-line nil t)
(doom--nlinum-unhl-line))
;;;###autoload
(defun doom|nlinum-disable (&rest _)
(nlinum-mode -1)
(remove-hook 'post-command-hook 'doom|nlinum-hl-line t)
(doom--nlinum-unhl-line))
(defun doom--nlinum-unhl-line ()
"Unhighlight line number"
(when doom--hl-nlinum-overlay
(let* ((disp (get-text-property
0 'display (overlay-get doom--hl-nlinum-overlay 'before-string)))
(str (nth 1 disp)))
(put-text-property 0 (length str) 'face 'linum str)
(setq doom--hl-nlinum-overlay nil)
disp)))
;;;###autoload
(defun doom|nlinum-hl-line (&rest _)
"Highlight line number"
(let* ((pbol (line-beginning-position))
(peol (1+ pbol))
(max (point-max)))
;; Handle EOF case
(when (>= peol max)
(setq peol max))
(jit-lock-fontify-now pbol peol)
(let ((ov (--first (overlay-get it 'nlinum) (overlays-in pbol peol))))
(doom--nlinum-unhl-line)
(when ov
(let ((str (nth 1 (get-text-property 0 'display (overlay-get ov 'before-string)))))
(put-text-property 0 (length str) 'face 'doom-nlinum-highlight str)
(setq doom--hl-nlinum-overlay ov))))))
(provide 'defuns-nlinum)
;;; defuns-nlinum.el ends here

View file

@ -1,158 +0,0 @@
;;; defuns-popups.el
(defvar doom-last-popup nil
"The last popup buffer open (or group thereof).")
(defvar-local doom-popup-rule nil
"A list of rules applied to this popup.")
(defvar doom-popup-mode-map
(let ((map (make-sparse-keymap)))
(define-key map [remap doom/kill-real-buffer] 'doom/popup-close)
(define-key map [remap evil-window-delete] 'doom/popup-close)
(define-key map [remap evil-window-move-very-bottom] 'ignore)
(define-key map [remap evil-window-move-very-top] 'ignore)
(define-key map [remap evil-window-move-far-left] 'ignore)
(define-key map [remap evil-window-move-far-right] 'ignore)
(define-key map [remap evil-window-split] 'ignore)
(define-key map [remap evil-window-vsplit] 'ignore)
(define-key map [remap evil-force-normal-state] 'doom/popup-close-maybe)
(define-key map [escape] 'doom/popup-close-maybe)
(define-key map (kbd "ESC") 'doom/popup-close-maybe)
map)
"Active keymap in popup windows.")
;;;###autoload
(define-minor-mode doom-popup-mode
"Minor mode for pop-up windows. Enables local keymaps and sets state
variables."
:global nil
:init-value nil
:keymap doom-popup-mode-map
(let ((rules (--any (let ((key (car it)))
(when (cond ((symbolp key)
(or (eq major-mode key)
(derived-mode-p key)))
((stringp key)
(string-match-p key (buffer-name))))
(cdr it)))
doom-popup-rules)))
(set-window-dedicated-p nil doom-popup-mode)
(setq doom-last-popup (current-buffer))
(setq-local doom-popup-rule rules)))
(put 'doom-popup-mode 'permanent-local t)
;;;###autoload
(defun doom*popup-window-move (orig-fn &rest args)
(unless (doom/popup-p)
(apply orig-fn args)))
;;;###autoload
(defun doom/popup-p (&optional window)
"Whether WINDOW is a popup window or not. If WINDOW is nil, use current
window. Returns nil or the popup window."
(setq window (or window (selected-window)))
(and (window-live-p window)
(buffer-local-value 'doom-popup-mode (window-buffer window))
window))
;;;###autoload
(defun doom/popups-p ()
"Whether there is a popup window open and alive somewhere."
(and doom-last-popup (window-live-p (get-buffer-window doom-last-popup))))
;;;###autoload
(defmacro doom/popup-save (&rest body)
"Close popups before BODY and restore them afterwards."
`(let ((popup-p (doom/popups-p))
(in-popup-p (doom/popup-p)))
(when popup-p
(doom/popup-close-all t)
(doom/popup-close nil t))
(prog1
,@body
(when popup-p
(let ((origin-win (selected-window)))
(doom/popup-last-buffer)
(when in-popup-p
(select-window origin-win)))))))
;;;###autoload
(defun doom/popup-buffer (buffer &optional plist)
"Display BUFFER in a shackle popup."
(let* ((buffer-name (cond ((stringp buffer) buffer)
((bufferp buffer) (buffer-name buffer))
(t (error "Not a valid buffer"))))
(buffer (get-buffer-create buffer-name)))
(shackle-display-buffer
buffer
nil (or plist (shackle-match buffer-name)))))
;;;###autoload
(defun doom/popup-close (&optional window dont-kill)
"Find and close the currently active popup (if available)."
(interactive)
(setq window (or window (selected-window)))
(when (doom/popup-p window)
(with-selected-window window
;; If REPL...
(when (bound-and-true-p repl-toggle-mode)
(setq rtog/--last-buffer nil))
(doom-popup-mode -1)
(unless (or dont-kill (memq :nokill doom-popup-rule))
(let ((kill-buffer-query-functions
(delq 'process-kill-buffer-query-function
kill-buffer-query-functions)))
(kill-buffer (window-buffer window)))))
(delete-window window)))
;;;###autoload
(defun doom/popup-close-maybe ()
"Close the current popup *if* its buffer doesn't have a :noesc rule in
`doom-popup-rules'."
(interactive)
(if (memq :noesc doom-popup-rule)
(call-interactively 'evil-force-normal-state)
(doom/popup-close)))
;;;###autoload
(defun doom/popup-close-all (&optional dont-kill)
"Closes all popups (kill them if DONT-KILL-BUFFERS is non-nil)."
(interactive)
(let ((orig-win (selected-window)))
(mapc (lambda (w) (doom/popup-close w dont-kill))
(--filter (and (doom/popup-p it) (not (eq it orig-win)))
(window-list)))))
;;;###autoload
(defun doom/popup-last-buffer ()
"Restore the last popup."
(interactive)
(unless (buffer-live-p doom-last-popup)
(setq doom-last-popup nil)
(error "No popup to restore"))
(doom/popup-buffer doom-last-popup))
;;;###autoload
(defun doom/popup-messages ()
"Pop up the messages buffer."
(interactive)
(doom/popup-buffer (messages-buffer))
(goto-char (point-max)))
;;;###autoload
(defun doom*popup-init (orig-fn &rest args)
"Enables `doom-popup-mode' in every popup window and returns the window."
(let ((window (apply orig-fn args)))
(with-selected-window window
(doom-popup-mode +1))
;; NOTE orig-fn returns a window, so `doom*popup-init' must too
window))
;;;###autoload
(defun doom*save-popup (orig-fun &rest args)
"Prevents messing up a popup buffer on window changes"
(doom/popup-save (apply orig-fun args)))
(provide 'defuns-popups)
;;; defuns-popups.el ends here

View file

@ -1,32 +0,0 @@
;;; defuns-projectile.el
;;;###autoload
(defun doom/project-root (&optional strict-p)
"Get the path to the root of your project."
(let (projectile-require-project-root strict-p)
(projectile-project-root)))
;;;###autoload
(defun doom/project-has-files (files &optional root)
"Return non-nil if FILES exist in the project root."
(let ((root (or root (doom/project-root)))
(files (if (listp files) files (list files)))
(found-p (if files t)))
(while (and found-p files)
(let ((file (expand-file-name (pop files) root)))
(setq found-p (if (string-suffix-p "/" file)
(file-directory-p file)
(file-exists-p file)))))
found-p))
;;;###autoload
(defun doom/project-p (&optional strict-p)
"Whether or not this buffer is currently in a project or not."
(let ((projectile-require-project-root strict-p))
(projectile-project-p)))
;;;###autoload
(defalias 'doom/project-name 'projectile-project-name)
(provide 'defuns-projectile)
;;; defuns-projectile.el ends here

View file

@ -1,35 +0,0 @@
;;; defuns-repl.el
;;;###autoload (autoload 'doom:repl "defuns-repl" nil t)
(evil-define-command doom:repl (&optional bang command)
:repeat nil
(interactive "<!><a>")
(if (and doom-repl-buffer (buffer-live-p doom-repl-buffer))
(doom/popup-buffer doom-repl-buffer)
(rtog/toggle-repl (if (use-region-p) 4))
(setq doom-repl-buffer (current-buffer))
(when command
(with-current-buffer doom-repl-buffer
(insert command)
(unless bang (comint-send-input))))))
;;;###autoload (autoload 'doom:repl-eval "defuns-repl" nil t)
(evil-define-operator doom:repl-eval (&optional beg end bang)
:type inclusive
:repeat nil
(interactive "<r><!>")
(let ((region-p (use-region-p))
(selection (s-trim (buffer-substring-no-properties beg end))))
(doom:repl bang)
(when (and region-p beg end)
(let* ((buf doom-repl-buffer)
(win (get-buffer-window buf)))
(unless (eq buf (doom/popup-p (get-buffer-window buf)))
(doom/popup-buffer buf))
(when (and doom-repl-buffer (buffer-live-p doom-repl-buffer))
(with-current-buffer doom-repl-buffer
(goto-char (point-max))
(insert selection)))))))
(provide 'defuns-repl)
;;; defuns-repl.el ends here

View file

@ -1,79 +0,0 @@
;;; defuns-ui.el
;;;###autoload (autoload 'doom:set-columns "defuns-ui" nil t)
(after! evil
(evil-define-command doom:set-columns (&optional bang columns)
"Adjusts visual-fill-column-width on the fly."
(interactive "<!><a>")
(if (or (= (length columns) 0) bang)
(progn
(setq visual-fill-column-width 80)
(when visual-fill-column-mode
(visual-fill-column-mode -1)))
(setq columns (string-to-number columns))
(when (> columns 30)
(setq visual-fill-column-width columns)))
(if visual-fill-column-mode
(visual-fill-column--adjust-window)
(visual-fill-column-mode 1))))
;;;###autoload
(defun doom/toggle-fullscreen ()
(interactive)
(set-frame-parameter nil 'fullscreen (if (not (frame-parameter nil 'fullscreen)) 'fullboth)))
;;;###autoload
(defun doom/reset-theme ()
(interactive)
(doom/load-theme doom-ui-theme))
;;;###autoload
(defun doom/load-font (font)
(interactive)
(set-frame-font font t))
;;;###autoload
(defun doom/load-theme (theme)
(interactive)
(when doom-ui-theme
(disable-theme doom-ui-theme))
(load-theme theme t))
;;;###autoload
(defun doom/show-as (how &optional pred)
(let* ((beg (match-beginning 1))
(end (match-end 1))
(ok (or (not pred) (funcall pred beg end))))
(when ok
(compose-region beg end how 'decompose-region))
nil))
;;;###autoload
(defun doom/imenu-list-quit ()
(interactive)
(quit-window)
(mapc (lambda (b) (with-current-buffer b
(when imenu-list-minor-mode
(imenu-list-minor-mode -1))))
(doom/get-visible-buffers (doom/get-real-buffers))))
(put 'doom-hide-mode-line-mode 'permanent-local t)
(put 'doom--mode-line 'permanent-local t)
(defvar doom-hide-mode-line-format nil
"Format to use when `doom-hide-mode-line-mode' replaces the modeline")
(defvar-local doom--mode-line nil)
;;;###autoload
(define-minor-mode doom-hide-mode-line-mode
"Minor mode to hide the mode-line in the current buffer."
:init-value nil
:global nil
(if doom-hide-mode-line-mode
(setq doom--mode-line mode-line-format
mode-line-format doom-hide-mode-line-format)
(setq mode-line-format doom--mode-line
doom--mode-line doom-hide-mode-line-format)))
(provide 'defuns-ui)
;;; defuns-ui.el ends here

View file

@ -1,39 +0,0 @@
;;; defuns-util.el
;;;###autoload
(defun what-face (pos)
"Tells you the name of the face (point) is on."
(interactive "d")
(let ((hl-line-p (bound-and-true-p hl-line-mode)))
(if hl-line-p (hl-line-mode -1))
(let ((face (or (get-char-property (point) 'read-face-name)
(get-char-property (point) 'face))))
(if face (message "Face: %s" face) (message "No face at %d" pos)))
(if hl-line-p (hl-line-mode 1))))
;;;###autoload
(defun what-col ()
(interactive)
(message "Column %d" (current-column)))
;;;###autoload
(defun what-bindings (key)
(list
(minor-mode-key-binding key)
(local-key-binding key)
(global-key-binding key)))
;;;###autoload
(defun what-major-mode ()
(interactive)
(message "Mode: %s" major-mode))
;;;###autoload (autoload 'doom:echo "defuns-util" nil t)
(evil-define-command doom:echo (bang message)
"Display MSG in echo-area without logging it in *Messages* buffer."
(interactive "<!><a>")
(let (message-log-max)
(message "%s%s" (if bang ">> " "") message)))
(provide 'defuns-util)
;;; defuns-util.el ends here

View file

@ -1,198 +0,0 @@
;;; defuns-whitespace.el
;;;###autoload
(defun doom--point-at-bol-non-blank()
(save-excursion (evil-first-non-blank) (point)))
;;;###autoload
(defun doom/surrounded-p ()
(and (looking-back "[[{(]\\(\s+\\|\n\\)?\\(\s\\|\t\\)*")
(let* ((whitespace (match-string 1))
(match-str (concat whitespace (match-string 2) "[])}]")))
(looking-at-p match-str))))
;;;###autoload
(defun doom/backward-kill-to-bol-and-indent ()
"Kill line to the first non-blank character. If invoked again
afterwards, kill line to column 1."
(interactive)
(let ((empty-line (sp-point-in-blank-line)))
(evil-delete (point-at-bol) (point))
(if (not empty-line)
(indent-according-to-mode))))
;;;###autoload
(defun doom/move-to-bol ()
"Moves cursor to the first non-blank character on the line. If
already there, move it to the true bol."
(interactive)
(evil-save-goal-column
(let ((point-at-bol (doom--point-at-bol-non-blank))
(point (point)))
(if (= point-at-bol point)
(evil-move-beginning-of-line)
(unless (= (point-at-bol) point)
(evil-first-non-blank))))))
;;;###autoload
(defun doom/move-to-eol ()
(interactive)
(evil-save-goal-column
(let ((old-point (point)))
(when (comment-search-forward (point-at-eol) t)
(goto-char (match-beginning 0))
(skip-syntax-backward " ^<*" (doom--point-at-bol-non-blank))
(if (eq old-point (point)) ;
(evil-move-end-of-line))))))
;; Mimic expandtab in vim
;;;###autoload
;;;###autoload
(defun doom/backward-delete-whitespace-to-column ()
"Delete back to the previous column of whitespace, or as much whitespace as
possible, or just one char if that's not possible."
(interactive)
(let* ((context (sp--get-pair-list-context 'navigate))
(open-pair-re (sp--get-opening-regexp context))
(close-pair-re (sp--get-closing-regexp context))
open-len close-len)
(cond ;; When in strings (sp acts weird with quotes; this is the fix)
;; Also, skip closing delimiters
((and (and (sp--looking-back open-pair-re)
(setq open-len (- (match-beginning 0) (match-end 0))))
(and (looking-at close-pair-re)
(setq close-len (- (match-beginning 0) (match-end 0))))
(string= (plist-get (sp-get-thing t) :op)
(plist-get (sp-get-thing) :cl)))
(delete-backward-char open-len)
(delete-char close-len))
;; Delete up to the nearest tab column IF only whitespace between
;; point and bol.
((save-match-data (looking-back "^[\\t ]*" (line-beginning-position)))
(let ((movement (% (current-column) tab-width))
(p (point)))
(when (= movement 0)
(setq movement tab-width))
(save-match-data
(if (string-match "\\w*\\(\\s-+\\)$"
(buffer-substring-no-properties (- p movement) p))
(delete-backward-char (- (match-end 1) (match-beginning 1)))
(call-interactively 'delete-backward-char)))))
;; Otherwise do a regular delete
(t (call-interactively 'delete-backward-char)))))
;;;###autoload
(defun doom/dumb-indent (&optional smart)
"Inserts a tab character (or spaces x tab-width). Checks if the
auto-complete window is open."
(interactive)
(if indent-tabs-mode
(insert "\t")
(let* ((movement (% (current-column) tab-width))
(spaces (if (zerop movement) tab-width (- tab-width movement))))
(insert (s-repeat spaces " ")))))
;;;###autoload
(defun doom/smart-indent ()
(interactive)
(save-excursion
(back-to-indentation)
(doom/dumb-indent)))
;;;###autoload
(defun doom/dumb-dedent ()
(interactive)
(if indent-tabs-mode
(call-interactively 'backward-delete-char)
(save-excursion
(unless (looking-back "^[\s\t]*")
(evil-first-non-blank))
(let* ((movement (% (current-column) tab-width))
(spaces (if (zerop movement) tab-width (- tab-width movement))))
(delete-char (- spaces))))))
;;;###autoload
(defun doom/inflate-space-maybe ()
"Checks if point is surrounded by {} [] () delimiters and adds a
space on either side of the point if so."
(interactive)
(if (doom/surrounded-p)
(progn (call-interactively 'self-insert-command)
(save-excursion (call-interactively 'self-insert-command)))
(call-interactively 'self-insert-command)))
;;;###autoload
(defun doom/deflate-space-maybe ()
"Checks if point is surrounded by {} [] () delimiters, and deletes
spaces on either side of the point if so. Resorts to
`doom/backward-delete-whitespace-to-column' otherwise."
(interactive)
(save-match-data
(if (doom/surrounded-p)
(let ((whitespace-match (match-string 1)))
(cond ((not whitespace-match)
(call-interactively 'delete-backward-char))
((string-match "\n" whitespace-match)
(evil-delete (point-at-bol) (point))
(call-interactively 'delete-backward-char)
(save-excursion (call-interactively 'delete-char)))
(t (just-one-space 0))))
(doom/backward-delete-whitespace-to-column))))
;;;###autoload
(defun doom/newline-and-indent ()
(interactive)
(cond ((sp-point-in-string)
(newline))
((sp-point-in-comment)
(cond ((eq major-mode 'js2-mode)
(js2-line-break))
((-contains? '(java-mode php-mode) major-mode)
(c-indent-new-comment-line))
((-contains? '(c-mode c++-mode objc-mode css-mode scss-mode js2-mode) major-mode)
(newline-and-indent)
(insert "* ")
(indent-according-to-mode))
(t
;; Fix an off-by-one cursor-positioning issue
;; with `indent-new-comment-line'
(let ((col (save-excursion (comment-beginning) (current-column))))
(indent-new-comment-line)
(unless (= col (current-column))
(insert " "))))))
(t
(newline nil t)
(indent-according-to-mode))))
;;;###autoload (autoload 'doom:whitespace-retab "defuns-whitespace" nil t)
(evil-define-operator doom:whitespace-retab (beg end)
"Akin to vim's retab, this changes all tabs-to-spaces or spaces-to-tabs,
depending on `indent-tab-mode'. Untested."
:motion nil
:move-point nil
:type line
(interactive "<r>")
(unless (and beg end)
(setq beg (point-min))
(setq end (point-max)))
(if indent-tabs-mode
(tabify beg end)
(untabify beg end)))
;;;###autoload (autoload 'doom:whitespace-align "defuns-whitespace" nil t)
(evil-define-command doom:whitespace-align (beg end &optional regexp bang)
:repeat nil
(interactive "<r><a><!>")
(when regexp
(align-regexp beg end
(concat "\\(\\s-*\\)" (rxt-pcre-to-elisp regexp)) 1 1)))
;;;###autoload
(defun doom/static-reindent ()
"Reindent without moving cursor."
(interactive)
(save-excursion (call-interactively 'evil-indent)))
(provide 'defuns-whitespace)
;;; defuns-whitespace.el ends here

View file

@ -1,128 +0,0 @@
;;; defuns-window.el --- library for acting on windows
;;;###autoload
(defun doom*evil-window-split (orig-fn &rest args)
(interactive)
(doom/neotree-save
(apply orig-fn args)
(evil-window-down 1)))
;;;###autoload
(defun doom*evil-window-vsplit (orig-fn &rest args)
(interactive)
(doom/neotree-save
(apply orig-fn args)
(evil-window-right 1)))
;;;###autoload
(defun doom/evil-window-move (direction)
"Move current window to the next window in DIRECTION. If there are no windows
there and there is only one window, split in that direction and place this
window there. If there are no windows and this isn't the only window, use
evil-window-move-* (e.g. `evil-window-move-far-left')"
(let* ((this-window (get-buffer-window))
(this-buffer (current-buffer))
(that-window (windmove-find-other-window direction nil this-window))
(that-buffer (window-buffer that-window)))
(when (or (minibufferp that-buffer)
(doom/popup-p that-window))
(setq that-buffer nil that-window nil))
(if (not (or that-window (one-window-p t)))
(funcall (case direction
('left 'evil-window-move-far-left)
('right 'evil-window-move-far-right)
('up 'evil-window-move-very-top)
('down 'evil-window-move-very-bottom)))
(unless that-window
(setq that-window
(split-window this-window nil (cond ((eq direction 'up) 'above)
((eq direction 'down) 'below)
(t direction))))
(with-selected-window that-window
(switch-to-buffer doom-buffer))
(setq that-buffer (window-buffer that-window)))
(with-selected-window this-window
(switch-to-buffer that-buffer))
(with-selected-window that-window
(switch-to-buffer this-buffer))
(select-window that-window))))
;;;###autoload
(defun doom/evil-window-move-l () (interactive) (doom/evil-window-move 'left))
;;;###autoload
(defun doom/evil-window-move-d () (interactive) (doom/evil-window-move 'down))
;;;###autoload
(defun doom/evil-window-move-u () (interactive) (doom/evil-window-move 'up))
;;;###autoload
(defun doom/evil-window-move-r () (interactive) (doom/evil-window-move 'right))
;;;###autoload
(defun doom/new-buffer ()
(interactive)
(switch-to-buffer (generate-new-buffer "*new*")))
;;;###autoload
(defun doom/new-frame ()
(interactive)
(let ((nlinum-p (and (featurep 'nlinum)
(memq 'nlinum--setup-window window-configuration-change-hook))))
;; Disable nlinum to fix elusive "invalid face linum" bug
(remove-hook 'window-configuration-change-hook 'nlinum--setup-window t)
(let ((frame (new-frame))
(frame-name (format "*new-%s*" (length doom-wg-frames))))
(with-selected-frame frame
(wg-create-workgroup frame-name t)
(add-to-list 'doom-wg-frames (cons frame frame-name))))
(when nlinum-p
(add-hook 'window-configuration-change-hook 'nlinum--setup-window nil t))))
;;;###autoload
(defun doom/close-frame ()
(interactive)
(let ((frame (assq (selected-frame) doom-wg-frames)))
(if frame
(progn (wg-delete-workgroup (wg-get-workgroup (cdr frame)))
(delete-frame (car frame)))
(delete-frame))))
;;;###autoload
(defun doom/evil-window-resize (direction &optional count)
(interactive)
(let ((count (or count 1))
(next-window (window-in-direction direction)))
(when (or (not next-window) (not (doom/real-buffer-p (window-buffer next-window))))
(setq count (- count)))
(cond ((memq direction '(left right))
(evil-window-increase-width count))
((memq direction '(above below))
(evil-window-increase-height count)))))
;;;###autoload (autoload 'doom/evil-window-resize-r "defuns-window" nil t)
(evil-define-command doom/evil-window-resize-r (&optional count)
(interactive "<c>") (doom/evil-window-resize 'right count))
;;;###autoload (autoload 'doom/evil-window-resize-l "defuns-window" nil t)
(evil-define-command doom/evil-window-resize-l (&optional count)
(interactive "<c>") (doom/evil-window-resize 'left count))
;;;###autoload (autoload 'doom/evil-window-resize-u "defuns-window" nil t)
(evil-define-command doom/evil-window-resize-u (&optional count)
:repeat nil
(interactive "<c>") (doom/evil-window-resize 'above count))
;;;###autoload (autoload 'doom/evil-window-resize-d "defuns-window" nil t)
(evil-define-command doom/evil-window-resize-d (&optional count)
(interactive "<c>") (doom/evil-window-resize 'below count))
;;;###autoload
(defun doom/window-reorient ()
"Reorient all windows that are scrolled to the right."
(interactive)
(let ((i 0))
(mapc (lambda (w)
(with-selected-window w
(when (> (window-hscroll) 0)
(cl-incf i)
(evil-beginning-of-line))))
(doom/get-visible-windows))
(message "Reoriented %s windows" i)))
(provide 'defuns-window)
;;; defuns-window.el ends here

View file

@ -1,204 +0,0 @@
;;; defuns-workgroup.el
;;;###autoload
(defun doom|wg-cleanup ()
"Remove unsavable windows and buffers before we save the window
configuration."
(let (doom-buffer-inhibit-refresh)
(doom/popup-close-all)
(when (and (featurep 'neotree) (neo-global--window-exists-p))
(neotree-hide))))
;;;###autoload
(defun doom/wg-projectile-switch-project ()
(let ((project-root (doom/project-root)))
(doom:workgroup-new nil (file-name-nondirectory (directory-file-name project-root)) t)
(doom-reload-scratch-buffer project-root)
(when (featurep 'neotree)
(neotree-projectile-action))))
;;;###autoload (autoload 'doom:workgroup-save "defuns-workgroup" nil t)
(evil-define-command doom:workgroup-save (&optional bang session-name)
(interactive "<!><a>")
(doom|wg-cleanup)
(unless (wg-workgroup-list)
(wg-create-workgroup wg-first-wg-name))
(wg-save-session-as (if session-name
(concat wg-workgroup-directory session-name)
(if bang
(concat wg-workgroup-directory (f-filename (doom/project-root)))
wg-session-file))))
;;;###autoload (autoload 'doom:workgroup-load "defuns-workgroup" nil t)
(evil-define-command doom:workgroup-load (&optional bang session-name)
(interactive "<!><a>")
(doom|wg-cleanup)
(let ((session-file (if session-name
(concat wg-workgroup-directory session-name)
(let ((sess (concat wg-workgroup-directory (f-filename (doom/project-root)))))
(if bang
(when (file-exists-p sess)
sess)
wg-session-file)))))
(unless session-file
(user-error "No session found"))
(wg-open-session session-file))
(doom/workgroup-display t))
;;;###autoload
(defun doom/clear-sessions ()
"Delete all session files."
(interactive)
(mapc 'delete-file (f-glob (expand-file-name "*" wg-workgroup-directory))))
;;;###autoload (autoload 'doom:workgroup-new "defuns-workgroup" nil t)
(evil-define-command doom:workgroup-new (bang name &optional silent)
"Create a new workgroup named NAME. If BANG, overwrite any workgroup named
NAME. If NAME is omitted, autogenerate a name. If SILENT, then don't show the
tabs in the minibuffer afterwards."
(interactive "<!><a>")
(unless name
(setq name (format "#%s" (1+ (length (wg-session-workgroup-list (wg-current-session t)))))))
(let ((new-wg (wg-get-workgroup name t)))
(when (and new-wg bang)
(wg-delete-workgroup new-wg)
(setq new-wg nil))
(setq new-wg (or new-wg (wg-make-and-add-workgroup name t)))
(add-to-list 'doom-wg-names (wg-workgroup-uid new-wg))
(wg-switch-to-workgroup new-wg))
(unless silent
(doom--workgroup-display (wg-previous-workgroup t)
(format "Created %s" name)
'success)))
;;;###autoload (autoload 'doom:workgroup-rename "defuns-workgroup" nil t)
(evil-define-command doom:workgroup-rename (&optional bang new-name)
"Rename the current workgroup to NEW-NAME. If BANG and this workgroup has a
fixed name, un-fix it."
(interactive "<!><a>")
(let* ((wg (wg-current-workgroup))
(wg-uid (wg-workgroup-uid wg))
(old-name (wg-workgroup-name wg)))
(if bang
(setq doom-wg-names (delete wg-uid doom-wg-names))
(unless new-name
(user-error "You didn't enter in a name"))
(wg-rename-workgroup new-name wg)
(add-to-list 'doom-wg-names wg-uid)
(doom--workgroup-display wg (format "Renamed '%s'->'%s'" old-name new-name) 'success))))
;;;###autoload (autoload 'doom:workgroup-delete "defuns-workgroup" nil t)
(evil-define-command doom:workgroup-delete (&optional bang name)
"Delete the workgroup specified by NAME. If NAME is omitted, delete the
current workgroup. If BANG, prompts the user for which workgroup to delete."
(interactive "<!><a>")
(let* ((current-wg (wg-current-workgroup))
(wg-name (or name (wg-workgroup-name current-wg))))
(when bang
(setq wg-name (wg-read-workgroup-name)))
(let ((wg (wg-get-workgroup name)))
(setq doom-wg-names (delete (wg-workgroup-uid wg) doom-wg-names))
(if (eq wg current-wg)
(wg-kill-workgroup)
(wg-delete-workgroup wg))
(doom--workgroup-display nil (format "Deleted %s" wg-name) 'success))))
;;;###autoload
(defun doom:kill-other-workgroups ()
"Kill all other workgroups."
(interactive)
(let (workgroup (wg-current-workgroup))
(dolist (w (wg-session-workgroup-list (wg-current-session t)))
(unless (wg-current-workgroup-p w)
(wg-kill-workgroup w)))))
(defun doom--workgroup-display (&optional suppress-update message message-face)
(message "%s%s" (doom/workgroup-display suppress-update t)
(propertize message 'face message-face)))
;;;###autoload
(defun doom/workgroup-display (&optional suppress-update return-p message)
(interactive)
(awhen (wg-current-session t)
(unless (eq suppress-update t)
(doom/workgroup-update-names (if (wg-workgroup-p suppress-update) suppress-update)))
(let ((output (wg-display-internal
(lambda (workgroup index)
(if (not workgroup) wg-nowg-string
(wg-element-display
workgroup
(format " [%d] %s " (1+ index) (wg-workgroup-name workgroup))
'wg-current-workgroup-p)))
(wg-session-workgroup-list it))))
(if return-p
output
(message "%s%s" output (or message ""))))))
;;;###autoload
(defun doom/workgroup-update-names (&optional wg)
(let ((wg (or wg (wg-current-workgroup))))
(unless (member (wg-workgroup-uid wg) doom-wg-names)
(ignore-errors
(let ((old-name (wg-workgroup-name wg))
(new-name (f-filename (doom/project-root))))
(unless (string= new-name old-name)
(wg-rename-workgroup new-name wg)))))))
(defun doom--switch-to-workgroup (direction &optional count)
(interactive "<c>")
(assert (memq direction '(left right)))
(condition-case err
(progn
(if count
(wg-switch-to-workgroup-at-index (1- count))
(funcall (intern (format "wg-switch-to-workgroup-%s" direction))))
(doom/workgroup-display t))
(error (doom/workgroup-display t nil (format "Nope! %s" (cadr err))))))
;;;###autoload (autoload 'doom:switch-to-workgroup-left "defuns-workgroup" nil t)
(evil-define-command doom:switch-to-workgroup-left (count)
(interactive "<c>")
(doom--switch-to-workgroup 'left))
;;;###autoload (autoload 'doom:switch-to-workgroup-right "defuns-workgroup" nil t)
(evil-define-command doom:switch-to-workgroup-right (count)
(interactive "<c>")
(doom--switch-to-workgroup 'right))
;;;###autoload
(defun doom:switch-to-workgroup-at-index (index)
(interactive)
(doom/workgroup-update-names)
(let ((wg (nth index (wg-workgroup-list-or-error)))
msg)
(if wg
(unless (eq wg (wg-current-workgroup t))
(wg-switch-to-workgroup-at-index index))
(setq msg (format "No tab #%s" (1+ index))))
(doom/workgroup-display t nil msg)))
;;;###autoload
(defun doom/undo-window-change ()
(interactive)
(call-interactively (if (wg-current-workgroup t) 'wg-undo-wconfig-change 'winner-undo)))
;;;###autoload
(defun doom/redo-window-change ()
(interactive)
(call-interactively (if (wg-current-workgroup t) 'wg-redo-wconfig-change 'winner-redo)))
;;;###autoload
(defun doom/close-window-or-workgroup ()
(interactive)
(if (doom/popup-p)
(doom/popup-close)
(when (doom/kill-real-buffer)
(if (and (one-window-p t)
(> (length (wg-workgroup-list)) 1))
(if (string= (wg-workgroup-name (wg-current-workgroup)) wg-first-wg-name)
(evil-window-delete)
(doom:workgroup-delete))
(evil-window-delete)))))
(provide 'defuns-workgroup)
;;; defuns-workgroup.el ends here

View file

@ -1,103 +0,0 @@
;;; defuns-yasnippet.el
;; for ../core-yasnippet.el
;;;###autoload
(defun doom|yas-before-expand ()
"Strip out the shitespace before a line selection."
(when (doom/evil-visual-line-state-p)
(setq-local
yas-selected-text
(replace-regexp-in-string
"\\(^ *\\|\n? $\\)" ""
(buffer-substring-no-properties (region-beginning)
(1- (region-end)))))))
;;;###autoload
(defun doom|yas-after-expand ()
"Switch to insert mode when expanding a template via backtab, or go back to
normal mode if there are no fields."
(setq yas-selected-text nil))
;;;###autoload
(defun doom/yas-insert-snippet ()
"Switch to insert mode when expanding a template via backtab, or go back to
normal mode if there are no fields."
(interactive)
(when (evil-visual-state-p)
(let ((end (region-end)))
(evil-visual-select
(region-beginning)
(if (eq evil-this-type 'line) end (1+ end))
'inclusive)))
(yas-insert-snippet)
(let* ((snippet (first (yas--snippets-at-point)))
(fields (yas--snippet-fields snippet)))
(evil-insert-state +1)
(unless fields (evil-change-state 'normal))))
;;;###autoload
(defun doom/yas-goto-start-of-field ()
"Go to the beginning of a field."
(interactive)
(let* ((snippet (car (yas--snippets-at-point)))
(position (yas--field-start (yas--snippet-active-field snippet))))
(if (= (point) position)
(move-beginning-of-line 1)
(goto-char position))))
;;;###autoload
(defun doom/yas-goto-end-of-field ()
(interactive)
(let* ((snippet (car (yas--snippets-at-point)))
(position (yas--field-end (yas--snippet-active-field snippet))))
(if (= (point) position)
(move-end-of-line 1)
(goto-char position))))
;;;###autoload
(defun doom/yas-backspace (&optional field)
"Prevents Yas from stepping on my toes when I use backspace."
(interactive)
(let ((field (or field (and yas--active-field-overlay
(overlay-buffer yas--active-field-overlay)
(overlay-get yas--active-field-overlay 'yas--field)))))
(cond ((eq (point) (marker-position (yas--field-start field))) nil)
(t (delete-char -1)))))
;;;###autoload
(defun doom/yas-delete (&optional field)
(interactive)
(let ((field (or field (and yas--active-field-overlay
(overlay-buffer yas--active-field-overlay)
(overlay-get yas--active-field-overlay 'yas--field)))))
(cond ((and field
(not (yas--field-modified-p field))
(eq (point) (marker-position (yas--field-start field))))
(yas--skip-and-clear field)
(yas-next-field 1))
((eq (point) (marker-position (yas--field-end field))) nil)
(t (delete-char 1)))))
;;;###autoload
(defun doom/yas-clear-to-sof (&optional field)
(interactive)
(let* ((field (or field (and yas--active-field-overlay
(overlay-buffer yas--active-field-overlay)
(overlay-get yas--active-field-overlay 'yas--field))))
(sof (marker-position (yas--field-start field))))
(when (and field (> (point) sof))
(delete-region sof (point)))))
;; Snippet helpers ;;;;;;;;;;;;;;;;;;;;;
;;;###autoload
(defun doom/yas-find-file ()
"Browse through snippets folder"
(interactive)
(projectile-find-file-in-directory (car yas-snippet-dirs)))
;;;###autoload
(defun doom/yas-ivy-prompt (prompt choices &optional display-fn)
(yas-completing-prompt prompt choices display-fn #'ivy-completing-read))
(provide 'defuns-yasnippet)
;;; nlinum-defuns.el ends here

View file

@ -1,24 +0,0 @@
;;; macros-company.el --- macros for company-mode
;; for ../core-company.el
;;;###autoload
(defmacro def-company-backend! (hooks backends)
"Register a company backend for a mode."
(let* ((hooks (if (listp hooks) hooks (list hooks)))
(def-name (intern (format "doom--init-company-%s"
(mapconcat 'identity (mapcar 'symbol-name hooks) "-"))))
(quoted (eq (car-safe backends) 'quote)))
`(progn
(defun ,def-name ()
(require 'company)
(set (make-local-variable 'company-backends)
(append '((,@(mapcar (lambda (backend)
(if quoted
backend
(intern (format "company-%s" backend))))
(if quoted (cadr backends) backends))))
company-backends)))
(add-hook! ,hooks ',def-name))))
(provide 'macros-company)
;;; macros-company.el ends here

View file

@ -1,38 +0,0 @@
;;; macros-editor.el
;;;###autoload
(defmacro def-electric! (modes &rest rest)
"Declare :words (list of strings) or :chars (lists of chars) in MODES that
trigger electric indentation."
(declare (indent 1))
(let ((modes (-list modes))
(chars (plist-get rest :chars))
(words (plist-get rest :words)))
(when (or chars words)
(let ((fn-name (intern (format "doom--electric-%s" (s-join "-" (mapcar 'symbol-name modes))))))
`(progn
(defun ,fn-name ()
(electric-indent-local-mode +1)
,(if chars `(setq electric-indent-chars ',chars))
,(if words `(setq doom-electric-indent-words ',words)))
(add-hook! ,modes ',fn-name))))))
;;;###autoload
(defmacro def-rotate! (modes &rest rest)
"Declare :symbols, :words or :patterns that `rotate-text' will cycle through."
(declare (indent 1))
(let ((modes (if (listp modes) modes (list modes)))
(symbols (plist-get rest :symbols))
(words (plist-get rest :words))
(patterns (plist-get rest :patterns)))
(when (or symbols words patterns)
(let ((fn-name (intern (format "doom--rotate-%s" (s-join "-" (mapcar 'symbol-name modes))))))
`(progn
(defun ,fn-name ()
,(if symbols `(setq-local rotate-text-local-symbols ',symbols))
,(if words `(setq-local rotate-text-local-words ',words))
,(if patterns `(setq-local rotate-text-local-patterns ',patterns)))
(add-hook! ,modes ',fn-name))))))
(provide 'macros-editor)
;;; macros-editor.el ends here

View file

@ -1,23 +0,0 @@
;;; macros-eval.el
;;;###autoload
(defmacro def-builder! (mode command &optional build-file)
"Register major/minor MODE with build COMMAND. If FILES are provided, do an additional
check to make sure they exist in the project root."
(let ((fn (intern (format "doom--init-builder-%s" mode))))
`(progn
(defun ,fn ()
(when (or (null ,build-file)
(doom/project-has-files ,build-file))
(setq doom--build-command '(,command . ,build-file))))
,(when (eq major-mode mode)
(funcall fn))
(add-hook! ,mode ',fn))))
;;;###autoload
(defmacro def-repl! (mode command)
"Define a REPL for a mode."
`(push '(,mode . ,command) rtog/mode-repl-alist))
(provide 'macros-eval)
;;; macros-eval.el ends here

View file

@ -1,31 +0,0 @@
;;; macros-evil.el
;;;###autoload
(defsubst def-text-obj! (key inner-fn &optional outer-fn)
(define-key evil-inner-text-objects-map key inner-fn)
(define-key evil-outer-text-objects-map key (or outer-fn inner-fn)))
;;;###autoload
(defmacro def-tmp-excmd! (cmd-on cmd-off &rest commands)
"Creates a toggle for a set of ex commands, named CMD-ON and CMD-OFF."
(declare (indent 2))
`(progn
(defun ,cmd-on (&rest _)
(mapc (lambda (cmd) (evil-ex-define-cmd (car cmd) (cdr cmd)))
',commands))
(defun ,cmd-off (&rest _)
(mapc (lambda (cmd) (doom/evil-ex-undefine-cmd (car cmd)))
',commands))))
;; Shortcuts for the evil expression register
;;;###autoload
(defmacro $= (str &rest args) `(calc-eval (format ,str ,@args)))
;;;###autoload
(defmacro $r (char) `(evil-get-register ,char))
;;;###autoload
(defmacro $expand (path) `(evil-ex-replace-special-filenames ,path))
(provide 'macros-evil)
;;; macros-evil.el ends here

View file

@ -1,8 +0,0 @@
;;; macros-popups.el
;;;###autoload
(defmacro def-popup! (&rest params)
`(push ',params shackle-rules))
(provide 'macros-popups)
;;; macros-popups.el ends here

View file

@ -1,24 +0,0 @@
;;; macros-rotate-text.el
;;;###autoload
(defmacro def-rotate! (modes &rest rest)
(declare (indent 1))
(let ((modes (if (listp modes) modes (list modes)))
(symbols (plist-get rest :symbols))
(words (plist-get rest :words))
(patterns (plist-get rest :patterns))
fn-name)
(setq fn-name (intern (format "doom--rotate-%s"
(s-join "-" (mapcar 'symbol-name modes)))))
`(progn
(defun ,fn-name ()
,(when symbols
`(setq-local rotate-text-local-symbols ',symbols))
,(when words
`(setq-local rotate-text-local-words ',words))
,(when patterns
`(setq-local rotate-text-local-patterns ',patterns)))
(add-hook! ,modes ',fn-name))))
(provide 'macros-rotate-text)
;;; macros-rotate-text.el ends here

View file

@ -1,13 +0,0 @@
;;; macros-yasnippet.el
;;;###autoload
(defmacro def-yas-mode! (mode)
"Register minor MODES in yasnippet."
`(after! yasnippet
(add-hook! ,mode
(if ,mode
(yas-activate-extra-mode ,mode)
(yas-deactivate-extra-mode ,mode)))))
(provide 'macros-yasnippet)
;;; macros-yasnippet.el ends here