Now that we are loading package autoloads files (as part of the generated doom-package-autoload-file when running make autoloads), many :commands properties are redundant. In fact, many def-package! blocks are redundant. In some cases, we can do without a config.el file entirely, and can move into the autoloads file or rely entirely on package autoloads. Also, many settings have been moved in their module's autoloads files, which makes them available ASAP; their use no longer depends on module load order. This gained me a modest ~10% boost in startup speed.
354 lines
14 KiB
EmacsLisp
354 lines
14 KiB
EmacsLisp
;;; ui/doom-dashboard/config.el -*- lexical-binding: t; -*-
|
|
|
|
(defvar +doom-dashboard-name " *doom*"
|
|
"The name to use for the dashboard buffer.")
|
|
|
|
(defvar +doom-dashboard-functions '(doom-dashboard-widget-banner
|
|
doom-dashboard-widget-shortmenu
|
|
doom-dashboard-widget-loaded)
|
|
"List of widget functions to run in the dashboard buffer to construct the
|
|
dashboard. These functions take no arguments and the dashboard buffer is current
|
|
while they run.")
|
|
|
|
(defvar +doom-dashboard-inhibit-refresh nil
|
|
"If non-nil, the doom buffer won't be refreshed.")
|
|
|
|
(defvar +doom-dashboard-inhibit-functions ()
|
|
"A list of functions which take no arguments. If any of them return non-nil,
|
|
dashboard reloading is inhibited.")
|
|
|
|
(defvar +doom-dashboard-pwd-policy 'last-project
|
|
"The policy to use when setting the `default-directory' in the dashboard.
|
|
|
|
Possible values:
|
|
|
|
'last-project the `doom-project-root' of the last open buffer
|
|
'last the `default-directory' of the last open buffer
|
|
a FUNCTION a function run with the `default-directory' of the last
|
|
open buffer, that returns a directory path
|
|
a STRING a fixed path
|
|
nil `default-directory' will never change")
|
|
|
|
;;
|
|
(defvar +doom-dashboard--last-cwd nil)
|
|
(defvar +doom-dashboard--width 80)
|
|
(defvar +doom-dashboard--height 0)
|
|
(defvar +doom-dashboard--old-fringe-indicator fringe-indicator-alist)
|
|
(defvar +doom-dashboard--pwd-alist ())
|
|
|
|
(defvar all-the-icons-scale-factor)
|
|
(defvar all-the-icons-default-adjust)
|
|
|
|
|
|
;;
|
|
;; Bootstrap
|
|
;;
|
|
|
|
(setq doom-fallback-buffer-name +doom-dashboard-name
|
|
initial-buffer-choice #'+doom-dashboard-initial-buffer)
|
|
|
|
(add-hook 'window-setup-hook #'+doom-dashboard|init)
|
|
|
|
|
|
;;
|
|
;; Major mode
|
|
;;
|
|
|
|
(define-derived-mode +doom-dashboard-mode special-mode
|
|
(format "DOOM v%s" doom-version)
|
|
:syntax-table nil
|
|
:abbrev-table nil
|
|
"Major mode for the DOOM dashboard buffer."
|
|
(setq truncate-lines t
|
|
buffer-read-only t)
|
|
(setq-local whitespace-style nil)
|
|
(setq-local show-trailing-whitespace nil)
|
|
(cl-loop for (car . _cdr) in fringe-indicator-alist
|
|
collect (cons car nil) into alist
|
|
finally do (setq fringe-indicator-alist alist))
|
|
(add-hook 'post-command-hook #'+doom-dashboard|reposition-point nil t))
|
|
|
|
(map! :map +doom-dashboard-mode-map
|
|
"n" #'forward-button
|
|
:gn [down] #'forward-button
|
|
:gn "C-n" #'forward-button
|
|
:gn [tab] #'forward-button
|
|
:gn "TAB" #'forward-button
|
|
"p" #'backward-button
|
|
:gn [up] #'backward-button
|
|
:gn "C-p" #'backward-button
|
|
:gn [backtab] #'backward-button
|
|
:gn "S-TAB" #'backward-button
|
|
(:when (featurep! :feature evil)
|
|
:m "j" #'forward-button
|
|
:m "k" #'backward-button
|
|
|
|
[remap evil-delete] #'ignore
|
|
[remap evil-delete-line] #'ignore
|
|
[remap evil-insert] #'ignore
|
|
[remap evil-append] #'ignore
|
|
[remap evil-replace] #'ignore
|
|
[remap evil-replace-state] #'ignore
|
|
[remap evil-change] #'ignore
|
|
[remap evil-change-line] #'ignore
|
|
[remap evil-visual-char] #'ignore
|
|
[remap evil-visual-line] #'ignore))
|
|
|
|
|
|
;;
|
|
;; Hooks
|
|
;;
|
|
|
|
(defun +doom-dashboard|reposition-point ()
|
|
"Trap the point in the buttons."
|
|
(when (region-active-p)
|
|
(deactivate-mark t)
|
|
(when (bound-and-true-p evil-mode)
|
|
(evil-change-to-previous-state)))
|
|
(or (ignore-errors
|
|
(if (button-at (point))
|
|
(forward-button 0)
|
|
(backward-button 1)))
|
|
(progn (goto-char (point-min))
|
|
(forward-button 1))))
|
|
|
|
(defun +doom-dashboard|init ()
|
|
"Initializes Doom's dashboard."
|
|
(unless noninteractive
|
|
(add-hook 'window-configuration-change-hook #'+doom-dashboard|resize)
|
|
(add-hook 'window-size-change-functions #'+doom-dashboard|resize)
|
|
(add-hook 'kill-buffer-query-functions #'+doom-dashboard|reload-on-kill)
|
|
(add-hook 'doom-after-switch-buffer-hook #'+doom-dashboard|reload-on-kill)
|
|
(unless (daemonp)
|
|
(add-hook 'after-make-frame-functions #'+doom-dashboard|make-frame))
|
|
;; `persp-mode' integration: update `default-directory' when switching
|
|
(add-hook 'persp-created-functions #'+doom-dashboard|record-project)
|
|
(add-hook 'persp-activated-functions #'+doom-dashboard|detect-project)
|
|
(add-hook 'persp-before-switch-functions #'+doom-dashboard|record-project))
|
|
(+doom-dashboard-reload t))
|
|
|
|
(defun +doom-dashboard|reload-on-kill ()
|
|
"A `kill-buffer-query-functions' hook. If this isn't a dashboard buffer, move
|
|
along, but record its `default-directory' if the buffer is real. See
|
|
`doom-real-buffer-p' for an explanation for what 'real' means.
|
|
|
|
If this is the dashboard buffer, reload the dashboard."
|
|
(or (let ((buf (current-buffer)))
|
|
(unless (+doom-dashboard-p buf)
|
|
(when (doom-real-buffer-p buf)
|
|
(setq +doom-dashboard--last-cwd default-directory)
|
|
(+doom-dashboard-update-pwd))
|
|
t))
|
|
(ignore
|
|
(let (+doom-dashboard-inhibit-refresh)
|
|
(ignore-errors (+doom-dashboard-reload))))))
|
|
|
|
(defun +doom-dashboard|make-frame (frame)
|
|
"Reload the dashboard after a brief pause. This is necessary for new frames,
|
|
whose dimensions may not be fully initialized by the time this is run."
|
|
(run-with-timer 0.1 nil #'+doom-dashboard/open frame))
|
|
|
|
(defun +doom-dashboard|resize (&rest _)
|
|
"Recenter the dashboard, and reset its margins and fringes."
|
|
(let ((windows (get-buffer-window-list (doom-fallback-buffer) nil t)))
|
|
(dolist (win windows)
|
|
(set-window-start win 0)
|
|
(set-window-fringes win 0 0)
|
|
(set-window-margins
|
|
win (max 0 (/ (- (window-total-width win) +doom-dashboard--width) 2))))
|
|
(when windows
|
|
(with-current-buffer (doom-fallback-buffer)
|
|
(save-excursion
|
|
(with-silent-modifications
|
|
(goto-char (point-min))
|
|
(cond ((display-graphic-p)
|
|
(delete-region (line-beginning-position) (1+ (line-end-position)))
|
|
(insert (propertize
|
|
(char-to-string ?\uE001)
|
|
'display `((space :align-to 0
|
|
:height ,(max 0 (- (/ (window-height (get-buffer-window)) 2)
|
|
(/ (count-lines (point-min) (point-max)) 2.5))))))
|
|
"\n"))
|
|
(t
|
|
(while (string-empty-p (buffer-substring-no-properties (line-beginning-position) (line-end-position)))
|
|
(delete-region (line-beginning-position) (1+ (line-end-position))))
|
|
(insert
|
|
"\n"
|
|
(make-string (max 0 (- (/ (window-height (get-buffer-window)) 2)
|
|
(/ (count-lines (point-min) (point-max)) 2)))
|
|
?\n))))))))))
|
|
|
|
(defun +doom-dashboard|detect-project (&rest _)
|
|
"Check for a `last-project-root' parameter in the perspective, and set the
|
|
dashboard's `default-directory' to it if it exists.
|
|
|
|
This and `+doom-dashboard|record-project' provides `persp-mode' integration with
|
|
the Doom dashboard. It ensures that the dashboard is always in the correct
|
|
project (which may be different across perspective)."
|
|
(when (bound-and-true-p persp-mode)
|
|
(when-let* ((pwd (persp-parameter 'last-project-root)))
|
|
(+doom-dashboard-update-pwd pwd))))
|
|
|
|
(defun +doom-dashboard|record-project (&optional persp &rest _)
|
|
"Record the last `doom-project-root' for the current perspective. See
|
|
`+doom-dashboard|detect-project' for more information."
|
|
(when (bound-and-true-p persp-mode)
|
|
(set-persp-parameter
|
|
'last-project-root (doom-project-root)
|
|
(if (perspective-p persp) persp (get-current-persp)))))
|
|
|
|
|
|
;;
|
|
;; Library
|
|
;;
|
|
|
|
(defun +doom-dashboard-initial-buffer ()
|
|
"Returns buffer to display on startup. Designed for `initial-buffer-choice'."
|
|
(if (doom-real-buffer-p)
|
|
(current-buffer)
|
|
(doom-fallback-buffer)))
|
|
|
|
(defun +doom-dashboard-p (buffer)
|
|
"Returns t if BUFFER is the dashboard buffer."
|
|
(eq buffer (doom-fallback-buffer)))
|
|
|
|
(defun +doom-dashboard-update-pwd (&optional pwd)
|
|
"Update `default-directory' in the Doom dashboard buffer. What it is set to is
|
|
controlled by `+doom-dashboard-pwd-policy'."
|
|
(if pwd
|
|
(with-current-buffer (doom-fallback-buffer)
|
|
(setq-local default-directory pwd))
|
|
(let ((new-pwd (+doom-dashboard--get-pwd)))
|
|
(when (and new-pwd (file-directory-p new-pwd))
|
|
(unless (string-suffix-p "/" new-pwd)
|
|
(setq new-pwd (concat new-pwd "/")))
|
|
(+doom-dashboard-update-pwd new-pwd)))))
|
|
|
|
(defun +doom-dashboard-reload (&optional force)
|
|
"Update the DOOM scratch buffer (or create it, if it doesn't exist)."
|
|
(when (or (and (not +doom-dashboard-inhibit-refresh)
|
|
(get-buffer-window (doom-fallback-buffer))
|
|
(not (window-minibuffer-p (frame-selected-window)))
|
|
(not (run-hook-with-args-until-success '+doom-dashboard-inhibit-functions)))
|
|
force)
|
|
(with-current-buffer (doom-fallback-buffer)
|
|
(with-silent-modifications
|
|
(save-excursion
|
|
(unless (eq major-mode '+doom-dashboard-mode)
|
|
(+doom-dashboard-mode))
|
|
(erase-buffer)
|
|
(insert "\n")
|
|
(run-hooks '+doom-dashboard-functions)))
|
|
(+doom-dashboard|resize)
|
|
(+doom-dashboard|detect-project)
|
|
(+doom-dashboard-update-pwd)
|
|
(current-buffer))))
|
|
|
|
;; helpers
|
|
(defun +doom-dashboard--center (len s)
|
|
(concat (make-string (ceiling (max 0 (- len (length s))) 2) ? )
|
|
s))
|
|
|
|
(defun +doom-dashboard--get-pwd ()
|
|
(let ((lastcwd +doom-dashboard--last-cwd)
|
|
(policy +doom-dashboard-pwd-policy))
|
|
(cond ((null policy)
|
|
default-directory)
|
|
((stringp policy)
|
|
(expand-file-name policy lastcwd))
|
|
((functionp policy)
|
|
(funcall policy lastcwd))
|
|
((null lastcwd)
|
|
default-directory)
|
|
((eq policy 'last-project)
|
|
(let ((cwd default-directory)
|
|
(default-directory lastcwd))
|
|
(if (doom-project-p)
|
|
(doom-project-root)
|
|
cwd)))
|
|
((eq policy 'last)
|
|
lastcwd)
|
|
(t
|
|
(warn "`+doom-dashboard-pwd-policy' has an invalid value of '%s'"
|
|
policy)))))
|
|
|
|
|
|
;;
|
|
;; Widgets
|
|
;;
|
|
|
|
(defun doom-dashboard-widget-banner ()
|
|
(mapc (lambda (line)
|
|
(insert (propertize (+doom-dashboard--center +doom-dashboard--width line)
|
|
'face 'font-lock-comment-face) " ")
|
|
(insert "\n"))
|
|
'("================= =============== =============== ======== ========"
|
|
"\\\\ . . . . . . .\\\\ //. . . . . . .\\\\ //. . . . . . .\\\\ \\\\. . .\\\\// . . //"
|
|
"||. . ._____. . .|| ||. . ._____. . .|| ||. . ._____. . .|| || . . .\\/ . . .||"
|
|
"|| . .|| ||. . || || . .|| ||. . || || . .|| ||. . || ||. . . . . . . ||"
|
|
"||. . || || . .|| ||. . || || . .|| ||. . || || . .|| || . | . . . . .||"
|
|
"|| . .|| ||. _-|| ||-_ .|| ||. . || || . .|| ||. _-|| ||-_.|\\ . . . . ||"
|
|
"||. . || ||-' || || `-|| || . .|| ||. . || ||-' || || `|\\_ . .|. .||"
|
|
"|| . _|| || || || || ||_ . || || . _|| || || || |\\ `-_/| . ||"
|
|
"||_-' || .|/ || || \\|. || `-_|| ||_-' || .|/ || || | \\ / |-_.||"
|
|
"|| ||_-' || || `-_|| || || ||_-' || || | \\ / | `||"
|
|
"|| `' || || `' || || `' || || | \\ / | ||"
|
|
"|| .===' `===. .==='.`===. .===' /==. | \\/ | ||"
|
|
"|| .==' \\_|-_ `===. .===' _|_ `===. .===' _-|/ `== \\/ | ||"
|
|
"|| .==' _-' `-_ `=' _-' `-_ `=' _-' `-_ /| \\/ | ||"
|
|
"|| .==' _-' '-__\\._-' '-_./__-' `' |. /| | ||"
|
|
"||.==' _-' `' | /==.||"
|
|
"==' _-' E M A C S \\/ `=="
|
|
"\\ _-' `-_ /"
|
|
" `'' ``'")))
|
|
|
|
(defun doom-dashboard-widget-loaded ()
|
|
(insert
|
|
"\n\n"
|
|
(propertize
|
|
(+doom-dashboard--center
|
|
+doom-dashboard--width
|
|
(doom|display-benchmark 'return))
|
|
'face 'font-lock-comment-face)
|
|
"\n\n"))
|
|
|
|
(defun doom-dashboard-widget-shortmenu ()
|
|
(let ((all-the-icons-scale-factor 1.45)
|
|
(all-the-icons-default-adjust -0.02))
|
|
(insert "\n")
|
|
(mapc (lambda (btn)
|
|
(when btn
|
|
(cl-destructuring-bind (label icon fn) btn
|
|
(insert
|
|
(with-temp-buffer
|
|
(insert-text-button
|
|
(concat (all-the-icons-octicon icon :face 'font-lock-keyword-face)
|
|
(propertize (concat " " label) 'face 'font-lock-keyword-face))
|
|
'action `(lambda (_) ,fn)
|
|
'follow-link t)
|
|
(+doom-dashboard--center (- +doom-dashboard--width 2) (buffer-string)))
|
|
"\n\n"))))
|
|
`(("Homepage" "mark-github"
|
|
(browse-url "https://github.com/hlissner/doom-emacs"))
|
|
,(when (and (featurep! :feature workspaces)
|
|
(file-exists-p (expand-file-name persp-auto-save-fname persp-save-dir)))
|
|
'("Reload last session" "history"
|
|
(+workspace/load-session)))
|
|
,(when (featurep! :lang org)
|
|
'("See agenda for this week" "calendar"
|
|
(call-interactively #'org-agenda-list)))
|
|
("Recently opened files" "file-text"
|
|
(call-interactively (or (command-remapping #'recentf-open-files)
|
|
#'recentf-open-files)))
|
|
("Open project" "briefcase"
|
|
(call-interactively (or (command-remapping #'projectile-switch-project)
|
|
#'projectile-switch-project)))
|
|
("Jump to bookmark" "bookmark"
|
|
(call-interactively (or (command-remapping #'bookmark-jump)
|
|
#'bookmark-jump)))
|
|
,(when (file-directory-p doom-private-dir)
|
|
'("Open private configuration" "tools"
|
|
(doom-project-find-file doom-private-dir)))
|
|
("Edit my modules list" "settings"
|
|
(progn (make-directory doom-private-dir t)
|
|
(find-file (expand-file-name "init.el" doom-private-dir))))))))
|