From 5a4d467de1d980ca5fa95e137f7dff96a561bbd0 Mon Sep 17 00:00:00 2001 From: Levi Olson Date: Fri, 1 Feb 2019 13:41:12 -0600 Subject: [PATCH] Adding compiled files to git to make getting up and running faster. --- init.el | 1316 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ init.elc | Bin 0 -> 48779 bytes 2 files changed, 1316 insertions(+) create mode 100644 init.el create mode 100644 init.elc diff --git a/init.el b/init.el new file mode 100644 index 0000000..60690d2 --- /dev/null +++ b/init.el @@ -0,0 +1,1316 @@ +;;; -*- lexical-binding: t -*- +;;; DO NOT EDIT THIS FILE DIRECTLY +;;; EDIT ~init.org~ instead + +;; (setq byte-compile-warnings nil) +(defun tangle-init () + "If the current buffer is 'init.org' the code-blocks are tangled, and the tangled file is compiled." + (when (equal (buffer-file-name) + (expand-file-name (concat user-emacs-directory "init.org"))) + ;; Avoid running hooks when tangling. + (let ((prog-mode-hook nil)) + (org-babel-tangle) + (byte-compile-file (concat user-emacs-directory "init.el"))))) + +(add-hook 'after-save-hook 'tangle-init) + +(require 'package) + +(defvar my-packages + '(all-the-icons + anzu + base16-theme + better-defaults + company + company-go + counsel + counsel-projectile + diminish + dockerfile-mode + doom-themes + ein + eldoc-eval + elpy + expand-region + gitignore-mode + go-mode + go-playground + gorepl-mode + flycheck + iedit + ivy + ivy-hydra + json-mode + magit + material-theme + multiple-cursors + projectile + py-autopep8 + rainbow-delimiters + shrink-path + tide + typescript-mode + use-package + web-mode + which-key)) + +(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/")) +(add-to-list 'package-archives '("melpa-stable" . "http://stable.melpa.org/packages/")) + +(when (not package-archive-contents) + (package-refresh-contents)) +(package-initialize) + +(dolist (p my-packages) + (when (not (package-installed-p p)) + (package-install p))) + +(require 'better-defaults) + +;; Instead of the annoying giant warning icon, just flash the modeline. +;; (this happens when you do something like C-g) +(setq ring-bell-function + (lambda () + (let ((orig-fg (face-foreground 'mode-line))) + (set-face-foreground 'mode-line "#F2804F") + (run-with-idle-timer 0.1 nil + (lambda (fg) (set-face-foreground 'mode-line fg)) + orig-fg)))) + +(defvar backup-dir (expand-file-name "~/.emacs.d/backup/")) +(defvar autosave-dir (expand-file-name "~/.emacs.d/autosave/")) + +(setq inhibit-startup-message t + initial-scratch-message nil + backup-directory-alist (list (cons ".*" backup-dir)) + auto-save-list-file-prefix autosave-dir + auto-save-file-name-transforms `((".*" ,autosave-dir t))) + +(menu-bar-mode 0) +(scroll-bar-mode 0) +(tool-bar-mode 0) + + +;; (load-theme 'doom-city-lights t) +;; (load-theme 'doom-dracula t) +;; (load-theme 'doom-nord t) +(load-theme 'doom-one t) +;; (load-theme 'doom-spacegrey t) +;; (load-theme 'base16-ocean t) +(load-theme 'base16-onedark t) +(global-linum-mode t) +(global-auto-revert-mode t) + +(defalias 'yes-or-no-p 'y-or-n-p) + +(require 'which-key) +(which-key-setup-minibuffer) +(which-key-mode) + +(require 'company) +(add-hook 'after-init-hook 'global-company-mode) + +(require 'diminish) +(diminish 'auto-revert-mode) +(eval-after-load "company" '(diminish 'company-mode)) +(eval-after-load "counsel" '(diminish 'counsel-mode)) +(eval-after-load "elpy" '(diminish 'elpy-mode)) +(eval-after-load "go-mode" '(diminish 'go-mode)) +(eval-after-load "go-playground" '(diminish 'go-playground-mode)) +(eval-after-load "gorepl-mode" '(diminish 'gorepl-mode)) +(eval-after-load "flycheck" '(diminish 'flycheck-mode)) +(eval-after-load "ivy" '(diminish 'ivy-mode)) +(eval-after-load "projectile" '(diminish 'projectile-mode)) +(eval-after-load "which-key" '(diminish 'which-key-mode)) + +(defun dired-mode-setup () + "Will run as hook for `dired-mode'." + (dired-hide-details-mode 1)) +(add-hook 'dired-mode-hook 'dired-mode-setup) + +(require 'ivy-hydra) +(require 'ivy) +(require 'swiper) + +(ivy-mode 1) +(counsel-mode) +(setq ivy-use-virtual-buffers t + enable-recursive-minibuffers t + ivy-height 25 + ivy-initial-inputs-alist nil + ivy-extra-directories nil) + +(global-set-key (kbd "C-s") 'swiper) +(global-set-key (kbd "C-c C-r") 'ivy-resume) +(global-set-key (kbd "M-x") 'counsel-M-x) +(global-set-key (kbd "C-x C-f") 'counsel-find-file) +(global-set-key (kbd "C-c g") 'counsel-git) +(global-set-key (kbd "C-c j") 'counsel-git-grep) +(global-set-key (kbd "C-c k") 'counsel-ag) +(define-key minibuffer-local-map (kbd "C-r") 'counsel-minibuffer-history) + +(defun ivy-open-current-typed-path () + (interactive) + (when ivy--directory + (let* ((dir ivy--directory) + (text-typed ivy-text) + (path (concat dir text-typed))) + (delete-minibuffer-contents) + (ivy--done path)))) + +(define-key ivy-minibuffer-map (kbd "") 'ivy-alt-done) +(define-key ivy-minibuffer-map (kbd "C-f") 'ivy-open-current-typed-path) + +(require 'magit) +(global-set-key (kbd "C-x g") 'magit-status) +(global-set-key (kbd "C-c g") 'magit-status) +(setq magit-completing-read-function 'ivy-completing-read) + +(require 'projectile) +(require 'counsel-projectile) + +(projectile-mode) +(setq projectile-mode-line '(:eval (format " %s" (projectile-project-name))) + projectile-remember-window-configs t + projectile-completion-system 'ivy) +(counsel-projectile-mode) + +(require 'rainbow-delimiters) +(global-flycheck-mode) + +(add-hook 'before-save-hook 'delete-trailing-whitespace) +(add-hook 'prog-mode-hook 'rainbow-delimiters-mode) + +(setq-default indent-tabs-mode nil + tab-width 4) +(defvaralias 'c-basic-offset 'tab-width) +(defvaralias 'cperl-indent-level 'tab-width) + +(electric-pair-mode 1) +(show-paren-mode 1) + +(require 'dockerfile-mode) +(add-to-list 'auto-mode-alist '("Dockerfile*\\'" . dockerfile-mode)) + +(require 'gitignore-mode) +(add-to-list 'auto-mode-alist '("gitignore\\'" . gitignore-mode)) + +(require 'json-mode) +(add-to-list 'auto-mode-alist '("\\.json\\'" . json-mode)) + +(require 'web-mode) +(add-to-list 'auto-mode-alist '("\\.html\\'" . web-mode)) + +(elpy-enable) +(setq python-shell-interpreter "jupyter" + python-shell-interpreter-args "console --simple-prompt") + +(when (require 'flycheck nil t) + (setq elpy-modules (delq 'elpy-module-flymake elpy-modules)) + (add-hook 'elpy-mode-hook 'flycheck-mode)) + +(require 'py-autopep8) +(setq py-autopep8-options '("--ignore=E501")) +(add-hook 'elpy-mode-hook 'py-autopep8-enable-on-save) + +(require 'go-mode) +(require 'go-playground) +(require 'gorepl-mode) +(require 'company-go) + +(add-to-list 'auto-mode-alist '("\\.go\\'" . go-mode)) +(add-hook 'go-mode-hook (lambda () + (add-hook 'before-save-hook 'gofmnt-before-save) + (local-set-key (kbd "M-.") 'godef-jump) + (local-set-key (kbd "M-,") 'pop-tag-mark) + (set (make-local-variable 'company-backends) '(company-go)) + (setq company-tooltip-limit 20 + company-idle-delay .3 + company-echo-delay 0 + company-begin-commands '(self-insert-command)) + (gorepl-mode))) +(defun set-exec-path-from-shell-PATH () + (let ((path-from-shell (replace-regexp-in-string + "[ \t\n]*$" + "" + (shell-command-to-string "$SHELL --login -i -c 'echo $PATH'")))) + (setenv "PATH" path-from-shell) + (setq eshell-path-env path-from-shell) + (setq exec-path (split-string path-from-shell path-separator)))) + +(when window-system (set-exec-path-from-shell-PATH)) + +(setenv "GOPATH" "/home/leviolson/go") +(add-to-list 'exec-path "/home/leviolson/go/bin") + +(defun setup-tide-mode () + "Tide setup function." + (interactive) + (tide-setup) + (flycheck-mode +1) + (setq flycheck-check-syntax-automatically '(save mode-enabled)) + (eldoc-mode +1) + (tide-hl-identifier-mode +1) + (company-mode +1)) + +;; aligns annotation to the right hand side +(setq company-tooltip-align-annotations t) + +;; formats the buffer before saving +(add-hook 'before-save-hook 'tide-format-before-save) + +(add-hook 'typescript-mode-hook #'setup-tide-mode) + +(require 'typescript-mode) +(require 'tide) + +(add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-mode)) +(add-hook 'typescript-mode-hook + '(lambda () + (set (make-local-variable 'company-backends) '(company-tide)) + (setq company-tooltip-limit 20 + company-idle-delay .3 + company-echo-delay 0 + company-begin-commands '(self-insert-command) + tide-format-options '(:insertSpaceAfterFunctionKeywordForAnonymousFunctions t :placeOpenBraceOnNewLineForFunctions nil)) + (tide-setup))) + +(require 'web-mode) +(add-to-list 'auto-mode-alist '("\\.tsx\\'" . web-mode)) +(add-hook 'web-mode-hook + (lambda () + (when (string-equal "tsx" (file-name-extension buffer-file-name)) + (setup-tide-mode)))) +;; enable typescript-tslint checker +(flycheck-add-mode 'typescript-tslint 'web-mode) + +(require 'web-mode) +(add-to-list 'auto-mode-alist '("\\.jsx\\'" . web-mode)) +(add-hook 'web-mode-hook + (lambda () + (when (string-equal "jsx" (file-name-extension buffer-file-name)) + (setup-tide-mode)))) +;; configure jsx-tide checker to run after your default jsx checker +(flycheck-add-mode 'javascript-eslint 'web-mode) +(flycheck-add-next-checker 'javascript-eslint 'jsx-tide 'append) + +(org-babel-do-load-languages + 'org-babel-load-languages + '((js . t) + (shell . t) + (emacs-lisp . t))) + +(defvar org-src-tab-acts-natively) +(setq org-src-tab-acts-natively t) +;; (setenv "NODE_PATH" +;; (getenv "NODE_PATH")) + +(defvar org-confirm-babel-evaluate) + +(defun my-org-confirm-babel-evaluate (lang body) + "Execute certain languages without confirming. + Takes LANG to allow and BODY to execute." + (not (or (string= lang "js") + (string= lang "restclient") + (string= lang "emacs-lisp") + (string= lang "shell")))) +(setq org-confirm-babel-evaluate #'my-org-confirm-babel-evaluate) +(add-to-list 'org-structure-template-alist + (list "e" (concat "#+BEGIN_SRC emacs-lisp :results silent\n" + "\n" + "#+END_SRC"))) +(add-to-list 'org-structure-template-alist + (list "j" (concat "#+BEGIN_SRC js :cmd \"babel-node\"\n" + "\n" + "#+END_SRC"))) +(add-to-list 'org-structure-template-alist + (list "r" (concat "#+BEGIN_SRC restclient :results raw\n" + "\n" + "#+END_SRC"))) + +(defun find-user-init-file () + "Edit the `~/.emacs.d/init.org' file." + (interactive) + (find-file "~/.emacs.d/init.org")) + +(defun load-user-init-file () + "Reload the `~/.emacs.d/init.elc' file." + (interactive) + (load-file "~/.emacs.d/init.elc")) + +(defun jump-to-symbol-internal (&optional backwardp) + "Jumps to the next symbol near the point if such a symbol exists. If BACKWARDP is non-nil it jumps backward." + (let* ((point (point)) + (bounds (find-tag-default-bounds)) + (beg (car bounds)) (end (cdr bounds)) + (str (isearch-symbol-regexp (find-tag-default))) + (search (if backwardp 'search-backward-regexp + 'search-forward-regexp))) + (goto-char (if backwardp beg end)) + (funcall search str nil t) + (cond ((<= beg (point) end) (goto-char point)) + (backwardp (forward-char (- point beg))) + (t (backward-char (- end point)))))) + +(defun jump-to-previous-like-this () + "Jumps to the previous occurrence of the symbol at point." + (interactive) + (jump-to-symbol-internal t)) + +(defun jump-to-next-like-this () + "Jumps to the next occurrence of the symbol at point." + (interactive) + (jump-to-symbol-internal)) + + +(defun kill-this-buffer-unless-scratch () + "Works like `kill-this-buffer' unless the current buffer is the *scratch* buffer. In which case the buffer content is deleted and the buffer is buried." + (interactive) + (if (not (string= (buffer-name) "*scratch*")) + (kill-this-buffer) + (delete-region (point-min) (point-max)) + (switch-to-buffer (other-buffer)) + (bury-buffer "*scratch*"))) + +(defun backward-delete-to-word (arg) + "Delete words backward. With ARG, do this many times." + (interactive "p") + (delete-region (point) (progn (backward-to-word arg) (point)))) + +(defun comment-or-uncomment-region-or-line () + "Comments or uncomments the region or the current line if there's no active region." + (interactive) + (let (beg end) + (if (region-active-p) + (setq beg (region-beginning) end (region-end)) + (setq beg (line-beginning-position) end (line-end-position))) + (comment-or-uncomment-region beg end))) + +(defun new-line-below () + "Create a new line below current line." + (interactive) + (move-end-of-line 1) + (newline-and-indent)) + +(defun new-line-above () + "Create a new line above current line." + (interactive) + (move-beginning-of-line 1) + (newline) + (forward-line -1)) + +(defun duplicate-thing (comment) + "Duplicates the current line, or the region if active. If an argument (COMMENT) is given, the duplicated region will be commented out." + (interactive "P") + (save-excursion + (let ((start (if (region-active-p) (region-beginning) (point-at-bol))) + (end (if (region-active-p) (region-end) (point-at-eol)))) + (goto-char end) + (unless (region-active-p) + (newline)) + (insert (buffer-substring start end)) + (when comment (comment-region start end))))) + +(defun tidy () + "Ident, untabify and unwhitespacify current buffer, or region if active." + (interactive) + (let ((beg (if (region-active-p) (region-beginning) (point-min))) + (end (if (region-active-p) (region-end) (point-max)))) + (if (region-active-p) (message "Indenting Region") (message "Indenting File")) + (let ((inhibit-message t)) + (indent-region beg end)) + (whitespace-cleanup) + (untabify beg (if (< end (point-max)) end (point-max))))) + +(defun phil-columns () + "Good 'ol Phil-Columns." + (interactive) + (message "Good 'ol fill-columns") + (with-output-to-temp-buffer "*PHIL-COLUMN*" + (shell-command "mpv --no-video 'https://www.youtube.com/watch?v=YkADj0TPrJA&t=3m16s' > /dev/null 2>&1 & sleep 7; pkill mpv")) + (other-window 1) + (delete-window)) + +(declare-function first "Goto FIRST shell.") +(declare-function goto-non-shell-buffer "Goto something other than a shell buffer.") +(declare-function switch-shell "Switch shell.") + +(let ((last-shell "")) + (defun toggle-shell () + (interactive) + (cond ((string-match-p "^\\*shell<[1-9][0-9]*>\\*$" (buffer-name)) + (goto-non-shell-buffer)) + ((get-buffer last-shell) (switch-to-buffer last-shell)) + (t (shell (setq last-shell "*shell<1>*"))))) + + (defun switch-shell (n) + (let ((buffer-name (format "*shell<%d>*" n))) + (setq last-shell buffer-name) + (cond ((get-buffer buffer-name) + (switch-to-buffer buffer-name)) + (t (shell buffer-name) + (rename-buffer buffer-name))))) + + (defun goto-non-shell-buffer () + (let* ((r "^\\*shell<[1-9][0-9]*>\\*$") + (shell-buffer-p (lambda (b) (string-match-p r (buffer-name b)))) + (non-shells (cl-remove-if shell-buffer-p (buffer-list)))) + (when non-shells + (switch-to-buffer (first non-shells)))))) + + +(defadvice shell (after kill-with-no-query nil activate) + "." + (set-process-query-on-exit-flag (get-buffer-process ad-return-value) nil)) + +(declare-function comint-truncate-buffer ".") +(defun clear-comint () + "Run `comint-truncate-buffer' with the `comint-buffer-maximum-size' set to zero." + (interactive) + (let ((comint-buffer-maximum-size 0)) + (comint-truncate-buffer))) + +(defun c-setup () + "Compile." + (local-set-key (kbd "C-c C-c") 'compile)) + +(require 'company) +(add-hook 'comint-mode-hook (lambda () (local-set-key (kbd "C-l") 'clear-comint))) +(add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode) +(add-hook 'lisp-interaction-mode-hook 'turn-on-eldoc-mode) +(add-hook 'c-mode-common-hook 'c-setup) +(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode)) + +(defvar company-active-map (make-keymap) + "Company Mode keymap.") +(defvar custom-bindings (make-keymap) + "A keymap of custom bindings.") + +(define-key global-map (kbd "M-p") 'jump-to-previous-like-this) +(define-key global-map (kbd "M-n") 'jump-to-next-like-this) +(define-key global-map (kbd "M-") 'switch-to-next-buffer) +(define-key global-map (kbd "M-")'backward-delete-to-word) +(define-key global-map (kbd "C-")'backward-delete-to-word) + +(global-set-key (kbd "C-S-") 'mc/mark-next-like-this) +(global-set-key (kbd "C->") 'mc/mark-next-like-this) +(global-set-key (kbd "C-S-") 'mc/mark-previous-like-this) +(global-set-key (kbd "C-<") 'mc/mark-previous-like-this) +(global-set-key (kbd "C-c C->") 'mc/mark-all-like-this) +;; (dolist (n (number-sequence 1 9)) +;; (global-set-key (kbd (concat "M-" (int-to-string n))) +;; (lambda () (interactive) (switch-shell n)))) + +(define-key company-active-map (kbd "C-d") 'company-show-doc-buffer) +(define-key company-active-map (kbd "C-n") 'company-select-next) +(define-key company-active-map (kbd "C-p") 'company-select-previous) +(define-key company-active-map (kbd "") 'company-complete) + +(define-key custom-bindings (kbd "C-c p") 'counsel-projectile-switch-project) +(define-key custom-bindings (kbd "C-c f") 'counsel-projectile-find-file) +(define-key custom-bindings (kbd "C-c m") 'magit-status) +(define-key custom-bindings (kbd "C-c D") 'define-word-at-point) +(define-key custom-bindings (kbd "C-@") 'er/expand-region) +(define-key custom-bindings (kbd "C-#") 'er/contract-region) +(define-key custom-bindings (kbd "C-S-c C-S-c") 'mc/edit-lines) +(define-key custom-bindings (kbd "C-c b") 'ivy-switch-buffer) +(define-key custom-bindings (kbd "C-c l") 'org-store-link) +(define-key custom-bindings (kbd "C-c t") 'org-set-tags) +(define-key custom-bindings (kbd "M-u") 'upcase-dwim) +(define-key custom-bindings (kbd "M-c") 'capitalize-dwim) +(define-key custom-bindings (kbd "M-l") 'downcase-dwim) +(define-key custom-bindings (kbd "M-o") 'other-window) +(define-key custom-bindings (kbd "C-c s") 'ispell-word) +(define-key custom-bindings (kbd "C-c C-d") 'org-capture) +(define-key custom-bindings (kbd "C-c ") 'windmove-up) +(define-key custom-bindings (kbd "C-c ") 'windmove-down) +(define-key custom-bindings (kbd "C-c ") 'windmove-left) +(define-key custom-bindings (kbd "C-c ") 'windmove-right) +(define-key custom-bindings (kbd "C-c a") (lambda () (interactive) (org-agenda nil "n"))) +(define-key custom-bindings (kbd "C-c e") 'find-user-init-file) +(define-key custom-bindings (kbd "C-x f") 'phil-columns) +(define-key custom-bindings (kbd "C-x k") 'kill-this-buffer-unless-scratch) +(define-key custom-bindings (kbd "C-c d") 'duplicate-thing) +(define-key custom-bindings (kbd "C-c c") 'comment-or-uncomment-region-or-line) +(define-key custom-bindings (kbd "C-;") 'comment-or-uncomment-region-or-line) +(define-key custom-bindings (kbd "C-o") 'new-line-below) +(define-key custom-bindings (kbd "C-S-o") 'new-line-above) +(define-key custom-bindings (kbd "") 'tidy) +(define-key custom-bindings (kbd "M-q") 'kill-this-buffer) +(define-key custom-bindings (kbd "M-RET") '(lambda () (interactive) (term (getenv "SHELL")))) + + +(define-minor-mode custom-bindings-mode + "A mode that activates custom-bindings." + t nil custom-bindings) + +(cond ((member "PragmataPro" (font-family-list)) + (set-face-attribute 'default nil :font "PragmataPro-14"))) + +(require 'use-package) +(require 'anzu) +(require 'eldoc-eval) +(require 'iedit) +(require 'projectile) +(require 'all-the-icons) + +(defsubst doom--prepare-modeline-segments (segments) + (cl-loop for seg in segments + if (stringp seg) + collect seg + else + collect (list (intern (format "doom-modeline-segment--%s" (symbol-name seg)))))) + +(defvar doom--transient-counter 0) +(defmacro add-transient-hook! (hook &rest forms) + "Attaches transient forms to a HOOK. + +HOOK can be a quoted hook or a sharp-quoted function (which will be advised). + +These forms will be evaluated once when that function/hook is first invoked, +then it detaches itself." + (declare (indent 1)) + (let ((append (eq (car forms) :after)) + (fn (intern (format "doom-transient-hook-%s" (cl-incf doom--transient-counter))))) + `(when ,hook + (fset ',fn + (lambda (&rest _) + ,@forms + (cond ((functionp ,hook) (advice-remove ,hook #',fn)) + ((symbolp ,hook) (remove-hook ,hook #',fn))) + (unintern ',fn nil))) + (cond ((functionp ,hook) + (advice-add ,hook ,(if append :after :before) #',fn)) + ((symbolp ,hook) + (add-hook ,hook #',fn ,append)))))) + + +(defmacro add-hook! (&rest args) + "A convenience macro for `add-hook'. Takes, in order: + 1. Optional properties :local and/or :append, which will make the hook + buffer-local or append to the list of hooks (respectively), + 2. The hooks: either an unquoted major mode, an unquoted list of major-modes, + a quoted hook variable or a quoted list of hook variables. If unquoted, the + hooks will be resolved by appending -hook to each symbol. + 3. A function, list of functions, or body forms to be wrapped in a lambda. +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! :append (one-mode second-mode) 'enable-something) + (add-hook! :local (one-mode second-mode) 'enable-something) + (add-hook! (one-mode second-mode) (setq v 5) (setq a 2)) + (add-hook! :append :local (one-mode second-mode) (setq v 5) (setq a 2)) +Body forms can access the hook's arguments through the let-bound variable +`args'." + (declare (indent defun) (debug t)) + (let ((hook-fn 'add-hook) + append-p local-p) + (while (keywordp (car args)) + (pcase (pop args) + (:append (setq append-p t)) + (:local (setq local-p t)) + (:remove (setq hook-fn 'remove-hook)))) + (let ((hooks (doom--resolve-hook-forms (pop args))) + (funcs + (let ((val (car args))) + (if (memq (car-safe val) '(quote function)) + (if (cdr-safe (cadr val)) + (cadr val) + (list (cadr val))) + (list args)))) + forms) + (dolist (fn funcs) + (setq fn (if (symbolp fn) + `(function ,fn) + `(lambda (&rest _) ,@args))) + (dolist (hook hooks) + (push (if (eq hook-fn 'remove-hook) + `(remove-hook ',hook ,fn ,local-p) + `(add-hook ',hook ,fn ,append-p ,local-p)) + forms))) + `(progn ,@(nreverse forms))))) + +(defmacro def-modeline-segment! (name &rest forms) + "Defines a modeline segment and byte compiles it." + (declare (indent defun) (doc-string 2)) + (let ((sym (intern (format "doom-modeline-segment--%s" name)))) + `(progn + (defun ,sym () ,@forms) + ,(unless (bound-and-true-p byte-compile-current-file) + `(let (byte-compile-warnings) + (byte-compile #',sym)))))) + +(defmacro def-modeline! (name lhs &optional rhs) + "Defines a modeline format and byte-compiles it. NAME is a symbol to identify +it (used by `doom-modeline' for retrieval). LHS and RHS are lists of symbols of +modeline segments defined with `def-modeline-segment!'. +Example: + (def-modeline! minimal + (bar matches \" \" buffer-info) + (media-info major-mode)) + (doom-set-modeline 'minimal t)" + (let ((sym (intern (format "doom-modeline-format--%s" name))) + (lhs-forms (doom--prepare-modeline-segments lhs)) + (rhs-forms (doom--prepare-modeline-segments rhs))) + `(progn + (defun ,sym () + (let ((lhs (list ,@lhs-forms)) + (rhs (list ,@rhs-forms))) + (let ((rhs-str (format-mode-line rhs))) + (list lhs + (propertize + " " 'display + `((space :align-to (- (+ right right-fringe right-margin) + ,(+ 1 (string-width rhs-str)))))) + rhs-str)))) + ,(unless (bound-and-true-p byte-compile-current-file) + `(let (byte-compile-warnings) + (byte-compile #',sym)))))) + +(defun doom-modeline (key) + "Returns a mode-line configuration associated with KEY (a symbol). Throws an +error if it doesn't exist." + (let ((fn (intern (format "doom-modeline-format--%s" key)))) + (when (functionp fn) + `(:eval (,fn))))) + +(defun doom-set-modeline (key &optional default) + "Set the modeline format. Does nothing if the modeline KEY doesn't exist. If +DEFAULT is non-nil, set the default mode-line for all buffers." + (when-let ((modeline (doom-modeline key))) + (setf (if default + (default-value 'mode-line-format) + (buffer-local-value 'mode-line-format (current-buffer))) + modeline))) + +(use-package eldoc-eval + :config + (defun +doom-modeline-eldoc (text) + (concat (when (display-graphic-p) + (+doom-modeline--make-xpm + (face-background 'doom-modeline-eldoc-bar nil t) + +doom-modeline-height + +doom-modeline-bar-width)) + text)) + + ;; Show eldoc in the mode-line with `eval-expression' + (defun +doom-modeline--show-eldoc (input) + "Display string STR in the mode-line next to minibuffer." + (with-current-buffer (eldoc-current-buffer) + (let* ((str (and (stringp input) input)) + (mode-line-format (or (and str (or (+doom-modeline-eldoc str) str)) + mode-line-format)) + mode-line-in-non-selected-windows) + (force-mode-line-update) + (sit-for eldoc-show-in-mode-line-delay)))) + (setq eldoc-in-minibuffer-show-fn #'+doom-modeline--show-eldoc) + + (eldoc-in-minibuffer-mode +1)) + +;; anzu and evil-anzu expose current/total state that can be displayed in the +;; mode-line. +(use-package anzu + :init + ;; (add-transient-hook! #'ex-start-search (require 'anzu)) + ;; (add-transient-hook! #'ex-start-word-search (require 'anzu)) + :config + (setq anzu-cons-mode-line-p nil + anzu-minimum-input-length 1 + anzu-search-threshold 250) + ;; Avoid anzu conflicts across buffers + (mapc #'make-variable-buffer-local + '(anzu--total-matched anzu--current-position anzu--state + anzu--cached-count anzu--cached-positions anzu--last-command + anzu--last-isearch-string anzu--overflow-p)) + ;; Ensure anzu state is cleared when searches & iedit are done + (add-hook 'isearch-mode-end-hook #'anzu--reset-status t) + ;; (add-hook '+evil-esc-hook #'anzu--reset-status t) + (add-hook 'iedit-mode-end-hook #'anzu--reset-status)) + + +;; Keep `+doom-modeline-current-window' up-to-date +(defvar +doom-modeline-current-window (frame-selected-window)) +(defun +doom-modeline|set-selected-window (&rest _) + "Sets `+doom-modeline-current-window' appropriately" + (when-let ((win (frame-selected-window))) + (unless (minibuffer-window-active-p win) + (setq +doom-modeline-current-window win)))) + +(add-hook 'window-configuration-change-hook #'+doom-modeline|set-selected-window) +(add-hook 'focus-in-hook #'+doom-modeline|set-selected-window) +(advice-add #'handle-switch-frame :after #'+doom-modeline|set-selected-window) +(advice-add #'select-window :after #'+doom-modeline|set-selected-window) + +;; fish-style modeline +(use-package shrink-path + :commands (shrink-path-prompt shrink-path-file-mixed)) + + +;; +;; Variables +;; + +(defvar +doom-modeline-height 29 + "How tall the mode-line should be (only respected in GUI emacs).") + +(defvar +doom-modeline-bar-width 3 + "How wide the mode-line bar should be (only respected in GUI emacs).") + +(defvar +doom-modeline-vspc + (propertize " " 'face 'variable-pitch) + "TODO") + +(defvar +doom-modeline-buffer-file-name-style 'truncate-upto-project + "Determines the style used by `+doom-modeline-buffer-file-name'. + +Given ~/Projects/FOSS/emacs/lisp/comint.el +truncate-upto-project => ~/P/F/emacs/lisp/comint.el +truncate-upto-root => ~/P/F/e/lisp/comint.el +truncate-all => ~/P/F/e/l/comint.el +relative-from-project => emacs/lisp/comint.el +relative-to-project => lisp/comint.el +file-name => comint.el") + +;; externs +(defvar anzu--state nil) +(defvar evil-mode nil) +(defvar evil-state nil) +(defvar evil-visual-selection nil) +(defvar iedit-mode nil) +(defvar all-the-icons-scale-factor) +(defvar all-the-icons-default-adjust) + + +;; +;; Custom faces +;; + +(defgroup +doom-modeline nil + "" + :group 'doom) + +(defface doom-modeline-buffer-path + '((t (:inherit (mode-line-emphasis bold)))) + "Face used for the dirname part of the buffer path." + :group '+doom-modeline) + +(defface doom-modeline-buffer-file + '((t (:inherit (mode-line-buffer-id bold)))) + "Face used for the filename part of the mode-line buffer path." + :group '+doom-modeline) + +(defface doom-modeline-buffer-modified + '((t (:inherit (error bold) :background nil))) + "Face used for the 'unsaved' symbol in the mode-line." + :group '+doom-modeline) + +(defface doom-modeline-buffer-major-mode + '((t (:inherit (mode-line-emphasis bold)))) + "Face used for the major-mode segment in the mode-line." + :group '+doom-modeline) + +(defface doom-modeline-highlight + '((t (:inherit mode-line-emphasis))) + "Face for bright segments of the mode-line." + :group '+doom-modeline) + +(defface doom-modeline-panel + '((t (:inherit mode-line-highlight))) + "Face for 'X out of Y' segments, such as `+doom-modeline--anzu', `+doom-modeline--evil-substitute' and +`iedit'" + :group '+doom-modeline) + +(defface doom-modeline-info + `((t (:inherit (success bold)))) + "Face for info-level messages in the modeline. Used by `*vc'." + :group '+doom-modeline) + +(defface doom-modeline-warning + `((t (:inherit (warning bold)))) + "Face for warnings in the modeline. Used by `*flycheck'" + :group '+doom-modeline) + +(defface doom-modeline-urgent + `((t (:inherit (error bold)))) + "Face for errors in the modeline. Used by `*flycheck'" + :group '+doom-modeline) + +;; Bar +(defface doom-modeline-bar '((t (:inherit highlight))) + "The face used for the left-most bar on the mode-line of an active window." + :group '+doom-modeline) + +(defface doom-modeline-eldoc-bar '((t (:inherit shadow))) + "The face used for the left-most bar on the mode-line when eldoc-eval is +active." + :group '+doom-modeline) + +(defface doom-modeline-inactive-bar '((t (:inherit warning :inverse-video t))) + "The face used for the left-most bar on the mode-line of an inactive window." + :group '+doom-modeline) + + +;; +;; Modeline helpers +;; + +(defsubst active () + (eq (selected-window) +doom-modeline-current-window)) + +;; Inspired from `powerline's `pl/make-xpm'. +(defun +doom-modeline--make-xpm (color height width) + "Create an XPM bitmap." + (propertize + " " 'display + (let ((data (make-list height (make-list width 1))) + (color (or color "None"))) + (create-image + (concat + (format "/* XPM */\nstatic char * percent[] = {\n\"%i %i 2 1\",\n\". c %s\",\n\" c %s\"," + (length (car data)) + (length data) + color + color) + (apply #'concat + (cl-loop with idx = 0 + with len = (length data) + for dl in data + do (cl-incf idx) + collect + (concat "\"" + (cl-loop for d in dl + if (= d 0) collect (string-to-char " ") + else collect (string-to-char ".")) + (if (eq idx len) "\"};" "\",\n"))))) + 'xpm t :ascent 'center)))) + +(defun +doom-modeline-buffer-file-name () + "Propertized `buffer-file-name' based on `+doom-modeline-buffer-file-name-style'." + (propertize + (pcase +doom-modeline-buffer-file-name-style + ('truncate-upto-project (+doom-modeline--buffer-file-name 'shrink)) + ('truncate-upto-root (+doom-modeline--buffer-file-name-truncate)) + ('truncate-all (+doom-modeline--buffer-file-name-truncate t)) + ('relative-to-project (+doom-modeline--buffer-file-name-relative)) + ('relative-from-project (+doom-modeline--buffer-file-name-relative 'include-project)) + ('file-name (propertize (file-name-nondirectory buffer-file-name) + 'face + (let ((face (or (and (buffer-modified-p) + 'doom-modeline-buffer-modified) + (and (active) + 'doom-modeline-buffer-file)))) + (when face `(:inherit ,face)))))) + 'help-echo buffer-file-truename)) + +(defun +doom-modeline--buffer-file-name-truncate (&optional truncate-tail) + "Propertized `buffer-file-name' that truncates every dir along path. +If TRUNCATE-TAIL is t also truncate the parent directory of the file." + (let ((dirs (shrink-path-prompt (file-name-directory buffer-file-truename))) + (active (active))) + (if (null dirs) + (propertize "%b" 'face (if active 'doom-modeline-buffer-file)) + (let ((modified-faces (if (buffer-modified-p) 'doom-modeline-buffer-modified))) + (let ((dirname (car dirs)) + (basename (cdr dirs)) + (dir-faces (or modified-faces (if active 'doom-modeline-project-root-dir))) + (file-faces (or modified-faces (if active 'doom-modeline-buffer-file)))) + (concat (propertize (concat dirname + (if truncate-tail (substring basename 0 1) basename) + "/") + 'face (if dir-faces `(:inherit ,dir-faces))) + (propertize (file-name-nondirectory buffer-file-name) + 'face (if file-faces `(:inherit ,file-faces))))))))) + +(defun +doom-modeline--buffer-file-name-relative (&optional include-project) + "Propertized `buffer-file-name' showing directories relative to project's root only." + (let ((root (projectile-project-root)) + (active (active))) + (if (null root) + (propertize "%b" 'face (if active 'doom-modeline-buffer-file)) + (let* ((modified-faces (if (buffer-modified-p) 'doom-modeline-buffer-modified)) + (relative-dirs (file-relative-name (file-name-directory buffer-file-truename) + (if include-project (concat root "../") root))) + (relative-faces (or modified-faces (if active 'doom-modeline-buffer-path))) + (file-faces (or modified-faces (if active 'doom-modeline-buffer-file)))) + (if (equal "./" relative-dirs) (setq relative-dirs "")) + (concat (propertize relative-dirs 'face (if relative-faces `(:inherit ,relative-faces))) + (propertize (file-name-nondirectory buffer-file-truename) + 'face (if file-faces `(:inherit ,file-faces)))))))) + +(defun +doom-modeline--buffer-file-name (truncate-project-root-parent) + "Propertized `buffer-file-name'. +If TRUNCATE-PROJECT-ROOT-PARENT is t space will be saved by truncating it down +fish-shell style. + +Example: +~/Projects/FOSS/emacs/lisp/comint.el => ~/P/F/emacs/lisp/comint.el" + (let* ((project-root (projectile-project-root)) + (file-name-split (shrink-path-file-mixed project-root + (file-name-directory buffer-file-truename) + buffer-file-truename)) + (active (active))) + (if (null file-name-split) + (propertize "%b" 'face (if active 'doom-modeline-buffer-file)) + (pcase-let ((`(,root-path-parent ,project ,relative-path ,filename) file-name-split)) + (let ((modified-faces (if (buffer-modified-p) 'doom-modeline-buffer-modified))) + (let ((sp-faces (or modified-faces (if active 'font-lock-comment-face))) + (project-faces (or modified-faces (if active 'font-lock-string-face))) + (relative-faces (or modified-faces (if active 'doom-modeline-buffer-path))) + (file-faces (or modified-faces (if active 'doom-modeline-buffer-file)))) + (let ((sp-props `(,@(if sp-faces `(:inherit ,sp-faces)) ,@(if active '(:weight bold)))) + (project-props `(,@(if project-faces `(:inherit ,project-faces)) ,@(if active '(:weight bold)))) + (relative-props `(,@(if relative-faces `(:inherit ,relative-faces)))) + (file-props `(,@(if file-faces `(:inherit ,file-faces))))) + (concat (propertize (if truncate-project-root-parent + root-path-parent + (abbreviate-file-name project-root)) + 'face sp-props) + (propertize (concat project "/") 'face project-props) + (if relative-path (propertize relative-path 'face relative-props)) + (propertize filename 'face file-props))))))))) + + +;; +;; Segments +;; + +(def-modeline-segment! buffer-default-directory + "Displays `default-directory'. This is for special buffers like the scratch +buffer where knowing the current project directory is important." + (let ((face (if (active) 'doom-modeline-buffer-path))) + (concat (if (display-graphic-p) " ") + (all-the-icons-octicon + "file-directory" + :face face + :v-adjust -0.05 + :height 1.25) + (propertize (concat " " (abbreviate-file-name default-directory)) + 'face face)))) + +;; +(def-modeline-segment! buffer-info + "Combined information about the current buffer, including the current working +directory, the file name, and its state (modified, read-only or non-existent)." + (concat (cond (buffer-read-only + (concat (all-the-icons-octicon + "lock" + :face 'doom-modeline-warning + :v-adjust -0.05) + " ")) + ((buffer-modified-p) + (concat (all-the-icons-faicon + "floppy-o" + :face 'doom-modeline-buffer-modified + :v-adjust -0.0575) + " ")) + ((and buffer-file-name + (not (file-exists-p buffer-file-name))) + (concat (all-the-icons-octicon + "circle-slash" + :face 'doom-modeline-urgent + :v-adjust -0.05) + " ")) + ((buffer-narrowed-p) + (concat (all-the-icons-octicon + "fold" + :face 'doom-modeline-warning + :v-adjust -0.05) + " "))) + (if buffer-file-name + (+doom-modeline-buffer-file-name) + "%b"))) + +;; +(def-modeline-segment! buffer-info-simple + "Display only the current buffer's name, but with fontification." + (propertize + "%b" + 'face (cond ((and buffer-file-name (buffer-modified-p)) + 'doom-modeline-buffer-modified) + ((active) 'doom-modeline-buffer-file)))) + +;; +(def-modeline-segment! buffer-encoding + "Displays the encoding and eol style of the buffer the same way Atom does." + (concat (pcase (coding-system-eol-type buffer-file-coding-system) + (0 "LF ") + (1 "CRLF ") + (2 "CR ")) + (let ((sys (coding-system-plist buffer-file-coding-system))) + (cond ((memq (plist-get sys :category) '(coding-category-undecided coding-category-utf-8)) + "UTF-8") + (t (upcase (symbol-name (plist-get sys :name)))))) + " ")) + +;; +(def-modeline-segment! major-mode + "The major mode, including process, environment and text-scale info." + (propertize + (concat (format-mode-line mode-name) + (when (stringp mode-line-process) + mode-line-process) + (and (featurep 'face-remap) + (/= text-scale-mode-amount 0) + (format " (%+d)" text-scale-mode-amount))) + 'face (if (active) 'doom-modeline-buffer-major-mode))) + +;; +(def-modeline-segment! vcs + "Displays the current branch, colored based on its state." + (when (and vc-mode buffer-file-name) + (let* ((backend (vc-backend buffer-file-name)) + (state (vc-state buffer-file-name backend))) + (let ((face 'mode-line-inactive) + (active (active)) + (all-the-icons-default-adjust -0.1)) + (concat " " + (cond ((memq state '(edited added)) + (if active (setq face 'doom-modeline-info)) + (all-the-icons-octicon + "git-compare" + :face face + :v-adjust -0.05)) + ((eq state 'needs-merge) + (if active (setq face 'doom-modeline-info)) + (all-the-icons-octicon "git-merge" :face face)) + ((eq state 'needs-update) + (if active (setq face 'doom-modeline-warning)) + (all-the-icons-octicon "arrow-down" :face face)) + ((memq state '(removed conflict unregistered)) + (if active (setq face 'doom-modeline-urgent)) + (all-the-icons-octicon "alert" :face face)) + (t + (if active (setq face 'font-lock-doc-face)) + (all-the-icons-octicon + "git-compare" + :face face + :v-adjust -0.05))) + " " + (propertize (substring vc-mode (+ (if (eq backend 'Hg) 2 3) 2)) + 'face (if active face)) + " "))))) + +;; +(defun +doom-ml-icon (icon &optional text face voffset) + "Displays an octicon ICON with FACE, followed by TEXT. Uses +`all-the-icons-octicon' to fetch the icon." + (concat (if vc-mode " " " ") + (when icon + (concat + (all-the-icons-material icon :face face :height 1.1 :v-adjust (or voffset -0.2)) + (if text +doom-modeline-vspc))) + (when text + (propertize text 'face face)) + (if vc-mode " " " "))) + +(def-modeline-segment! flycheck + "Displays color-coded flycheck error status in the current buffer with pretty +icons." + (when (boundp 'flycheck-last-status-change) + (pcase flycheck-last-status-change + ('finished (if flycheck-current-errors + (let-alist (flycheck-count-errors flycheck-current-errors) + (let ((sum (+ (or .error 0) (or .warning 0)))) + (+doom-ml-icon "do_not_disturb_alt" + (number-to-string sum) + (if .error 'doom-modeline-urgent 'doom-modeline-warning) + -0.25))) + (+doom-ml-icon "check" nil 'doom-modeline-info))) + ('running (+doom-ml-icon "access_time" nil 'font-lock-doc-face -0.25)) + ('no-checker (+doom-ml-icon "sim_card_alert" "-" 'font-lock-doc-face)) + ('errored (+doom-ml-icon "sim_card_alert" "Error" 'doom-modeline-urgent)) + ('interrupted (+doom-ml-icon "pause" "Interrupted" 'font-lock-doc-face))))) +;; ('interrupted (+doom-ml-icon "x" "Interrupted" 'font-lock-doc-face))))) + +;; +(defsubst doom-column (pos) + (save-excursion (goto-char pos) + (current-column))) + +(def-modeline-segment! selection-info + "Information about the current selection, such as how many characters and +lines are selected, or the NxM dimensions of a block selection." + (when (and (active) (or mark-active (eq evil-state 'visual))) + (let ((reg-beg (region-beginning)) + (reg-end (region-end))) + (propertize + (let ((lines (count-lines reg-beg (min (1+ reg-end) (point-max))))) + (cond ((or (bound-and-true-p rectangle-mark-mode) + (eq 'block evil-visual-selection)) + (let ((cols (abs (- (doom-column reg-end) + (doom-column reg-beg))))) + (format "%dx%dB" lines cols))) + ((eq 'line evil-visual-selection) + (format "%dL" lines)) + ((> lines 1) + (format "%dC %dL" (- (1+ reg-end) reg-beg) lines)) + (t + (format "%dC" (- (1+ reg-end) reg-beg))))) + 'face 'doom-modeline-highlight)))) + + +;; +(defun +doom-modeline--macro-recording () + "Display current Emacs or evil macro being recorded." + (when (and (active) (or defining-kbd-macro executing-kbd-macro)) + (let ((sep (propertize " " 'face 'doom-modeline-panel))) + (concat sep + (propertize (if (bound-and-true-p evil-this-macro) + (char-to-string evil-this-macro) + "Macro") + 'face 'doom-modeline-panel) + sep + (all-the-icons-octicon "triangle-right" + :face 'doom-modeline-panel + :v-adjust -0.05) + sep)))) + +(defsubst +doom-modeline--anzu () + "Show the match index and total number thereof. Requires `anzu', also +`evil-anzu' if using `evil-mode' for compatibility with `evil-search'." + (when (and anzu--state (not iedit-mode)) + (propertize + (let ((here anzu--current-position) + (total anzu--total-matched)) + (cond ((eq anzu--state 'replace-query) + (format " %d replace " total)) + ((eq anzu--state 'replace) + (format " %d/%d " here total)) + (anzu--overflow-p + (format " %s+ " total)) + (t + (format " %s/%d " here total)))) + 'face (if (active) 'doom-modeline-panel)))) + +(defsubst +doom-modeline--evil-substitute () + "Show number of matches for evil-ex substitutions and highlights in real time." + (when (and evil-mode + (or (assq 'evil-ex-substitute evil-ex-active-highlights-alist) + (assq 'evil-ex-global-match evil-ex-active-highlights-alist) + (assq 'evil-ex-buffer-match evil-ex-active-highlights-alist))) + (propertize + (let ((range (if evil-ex-range + (cons (car evil-ex-range) (cadr evil-ex-range)) + (cons (line-beginning-position) (line-end-position)))) + (pattern (car-safe (evil-delimited-arguments evil-ex-argument 2)))) + (if pattern + (format " %s matches " (how-many pattern (car range) (cdr range))) + " - ")) + 'face (if (active) 'doom-modeline-panel)))) + +(defun doom-themes--overlay-sort (a b) + (< (overlay-start a) (overlay-start b))) + +(defsubst +doom-modeline--iedit () + "Show the number of iedit regions matches + what match you're on." + (when (and iedit-mode iedit-occurrences-overlays) + (propertize + (let ((this-oc (or (let ((inhibit-message t)) + (iedit-find-current-occurrence-overlay)) + (progn (iedit-prev-occurrence) + (iedit-find-current-occurrence-overlay)))) + (length (length iedit-occurrences-overlays))) + (format " %s/%d " + (if this-oc + (- length + (length (memq this-oc (sort (append iedit-occurrences-overlays nil) + #'doom-themes--overlay-sort))) + -1) + "-") + length)) + 'face (if (active) 'doom-modeline-panel)))) + +(def-modeline-segment! matches + "Displays: 1. the currently recording macro, 2. A current/total for the +current search term (with anzu), 3. The number of substitutions being conducted +with `evil-ex-substitute', and/or 4. The number of active `iedit' regions." + (let ((meta (concat (+doom-modeline--macro-recording) + (+doom-modeline--anzu) + (+doom-modeline--evil-substitute) + (+doom-modeline--iedit)))) + (or (and (not (equal meta "")) meta) + (if buffer-file-name " %I ")))) + +;; TODO Include other information +(def-modeline-segment! media-info + "Metadata regarding the current file, such as dimensions for images." + (cond ((eq major-mode 'image-mode) + (cl-destructuring-bind (width . height) + (image-size (image-get-display-property) :pixels) + (format " %dx%d " width height))))) + +(def-modeline-segment! bar + "The bar regulates the height of the mode-line in GUI Emacs. +Returns \"\" to not break --no-window-system." + (if (display-graphic-p) + (+doom-modeline--make-xpm + (face-background (if (active) + 'doom-modeline-bar + 'doom-modeline-inactive-bar) + nil t) + +doom-modeline-height + +doom-modeline-bar-width) + "")) + + +;; +;; Mode lines +;; + +(def-modeline! main + (bar matches " " buffer-info " %l:%c %p " selection-info) + (buffer-encoding major-mode vcs flycheck)) + +(def-modeline! minimal + (bar matches " " buffer-info) + (media-info major-mode)) + +(def-modeline! special + (bar matches " " buffer-info-simple " %l:%c %p " selection-info) + (buffer-encoding major-mode flycheck)) + +(def-modeline! project + (bar buffer-default-directory) + (major-mode)) + +(def-modeline! media + (bar " %b ") + (media-info major-mode)) + + +;; +;; Hooks +;; + +(defun +doom-modeline|init () + "Set the default modeline." + (doom-set-modeline 'main t) + + ;; This scratch buffer is already created and doesn't get a modeline. For the + ;; love of Emacs, someone give the man a modeline! + (with-current-buffer "*scratch*" + (doom-set-modeline 'main))) + +(defun +doom-modeline|set-special-modeline () + (doom-set-modeline 'special)) + +(defun +doom-modeline|set-media-modeline () + (doom-set-modeline 'media)) + +(defun +doom-modeline|set-project-modeline () + (doom-set-modeline 'project)) + + +;; +;; Bootstrap +;; + +(add-hook 'emacs-startup-hook #'+doom-modeline|init) +;; (add-hook 'doom-scratch-buffer-hook #'+doom-modeline|set-special-modeline) +;; (add-hook '+doom-dashboard-mode-hook #'+doom-modeline|set-project-modeline) + +(add-hook 'image-mode-hook #'+doom-modeline|set-media-modeline) +(add-hook 'org-src-mode-hook #'+doom-modeline|set-special-modeline) +(add-hook 'circe-mode-hook #'+doom-modeline|set-special-modeline) diff --git a/init.elc b/init.elc new file mode 100644 index 0000000000000000000000000000000000000000..0fc83361a7742a4df9d28c031bf4d73b4d7b51b8 GIT binary patch literal 48779 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 literal 0 HcmV?d00001