diff --git a/core/autoload/buffers.el b/core/autoload/buffers.el index ed44c5da9..e008dd3b0 100644 --- a/core/autoload/buffers.el +++ b/core/autoload/buffers.el @@ -244,8 +244,11 @@ ALL-P (universal argument), clean them up globally." (interactive) (let ((buffers (doom-buried-buffers buffer-list)) (n 0)) - (mapc #'kill-buffer buffers) - (setq n (+ n (length buffers) (doom/cleanup-buffer-processes))) + (dolist (buf buffers) + (unless (buffer-modified-p buf) + (kill-buffer buf) + (cl-incf n))) + (setq n (+ n (doom/cleanup-buffer-processes))) (dolist (hook doom-cleanup-hook) (let ((m (funcall hook))) (when (integerp m) diff --git a/core/autoload/modules.el b/core/autoload/modules.el index db1950764..ed71220b1 100644 --- a/core/autoload/modules.el +++ b/core/autoload/modules.el @@ -234,7 +234,7 @@ This should be run whenever your `doom!' block or update your packages." ;; Remove `load-path' and `auto-mode-alist' modifications (most of them, ;; at least); they are cached later, so all those membership checks are ;; unnecessary overhead. - (while (re-search-forward "^\\s-*\\((\\(?:add-to-list\\|when (boundp \\)\\s-+'\\(?:load-path\\|auto-mode-alist\\)\\)" nil t) + (while (re-search-forward "^\\s-*\\((\\(?:add-to-list\\|\\(?:when\\|if\\) (boundp\\)\\s-+'\\(?:load-path\\|auto-mode-alist\\)\\)" nil t) (goto-char (match-beginning 1)) (kill-sexp)) (print! (green "✓ Removed load-path/auto-mode-alist entries"))) @@ -280,7 +280,8 @@ If RECOMPILE-P is non-nil, only recompile out-of-date files." (":private" (push doom-private-dir targets)) (":plugins" (byte-recompile-directory package-user-dir 0 t) - (setq compile-plugins-p t)) + (setq compile-plugins-p t + modules (delete ":plugins" modules))) ((pred file-directory-p) (push module targets)) ((pred (string-match "^\\([^/]+\\)/\\([^/]+\\)$")) @@ -288,24 +289,33 @@ If RECOMPILE-P is non-nil, only recompile out-of-date files." (intern (format ":%s" (match-string 1 module))) (intern (match-string 2 module))) targets)))) - (unless (equal modules (list ":plugins")) - (let ((inhibit-message t) - noninteractive) - ;; But first we must be sure that Doom and your private config have been - ;; fully loaded. Which usually aren't so in an noninteractive session. - (doom//reload-autoloads) - (doom-initialize t))) - ;; If no targets were supplied, then we use your module list. - (unless targets - (doom-initialize-modules t) - (setq targets (append (list doom-core-dir) - (doom-module-load-path)))) - ;; Assemble el files we want to compile; taking into account that MODULES - ;; may be a list of MODULE/SUBMODULE strings from the command line. - (let ((target-files (doom-files-in targets :depth 2 :match "\\.el$"))) - (if (not target-files) - (unless compile-plugins-p + (cl-block 'byte-compile + ;; If we're just here to byte-compile our plugins, we're done! + (and (not modules) + compile-plugins-p + (cl-return-from 'byte-compile t)) + (unless targets + (let ((inhibit-message t) + noninteractive) + ;; But first we must be sure that Doom and your private config have + ;; been fully loaded. Which usually aren't so in an noninteractive + ;; session. + (doom//reload-autoloads) + (doom-initialize t))) + ;; If no targets were supplied, then we use your module list. + (unless modules + (doom-initialize-modules t) + (setq targets (append (list doom-core-dir) + (doom-module-load-path)))) + ;; Assemble el files we want to compile; taking into account that + ;; MODULES may be a list of MODULE/SUBMODULE strings from the command + ;; line. + (let ((target-files (doom-files-in targets :depth 2 :match "\\.el$"))) + (unless target-files + (if targets + (message "Couldn't find any valid targets") (message "No targets to %scompile" (if recompile-p "re" ""))) + (cl-return-from 'byte-compile)) (condition-case ex (let ((use-package-expand-minimally t)) ;; Always compile private init file diff --git a/core/core-dispatcher.el b/core/core-dispatcher.el index af8990177..2a27bb665 100644 --- a/core/core-dispatcher.el +++ b/core/core-dispatcher.el @@ -196,12 +196,7 @@ recompile. Run this whenever you: 2. Add or remove `package!' blocks to your config, 3. Add or remove autoloaded functions in module autoloaded files. 4. Update Doom outside of Doom (e.g. with git)" - (doom//reload-doom-autoloads) - (unwind-protect - (progn (doom//packages-autoremove) - (doom//packages-install)) - (doom//reload-package-autoloads) - (doom//byte-compile nil 'recompile))) + (doom//refresh)) ;; @@ -217,10 +212,22 @@ recompile. Run this whenever you: (with-temp-buffer (let ((default-directory dir)) (if (zerop (process-file "git" nil (current-buffer) nil - "status" "--porcelain")) + "status" "--porcelain" "-uno")) (string-match-p "[^ \t\n]" (buffer-string)) (error "Failed to check working tree in %s" dir))))) +(defun doom//refresh () + "Ensure Doom is in a working state by checking autoloads and packages, and +recompiling any changed compiled files. This is the shotgun solution to most +problems with doom." + (interactive) + (doom//reload-doom-autoloads) + (unwind-protect + (progn (doom//packages-autoremove) + (doom//packages-install)) + (doom//reload-package-autoloads) + (doom//byte-compile nil 'recompile))) + (defun doom//upgrade () "Upgrade Doom to the latest version." (interactive) @@ -263,7 +270,7 @@ recompile. Run this whenever you: (buffer-string))) (unless (equal (vc-git-working-revision doom-emacs-dir) rev) (error "Failed to checkout latest commit.\n\n%s" (buffer-string))) - (doom//reload) + (doom//refresh) (message "Done! Please restart Emacs for changes to take effect"))))))))) (defun doom//quickstart () diff --git a/core/core-keybinds.el b/core/core-keybinds.el index 3d9e1ed57..36d8d69fe 100644 --- a/core/core-keybinds.el +++ b/core/core-keybinds.el @@ -51,11 +51,12 @@ If any hook returns non-nil, all hooks after it are ignored.") which-key-sort-uppercase-first nil which-key-add-column-padding 1 which-key-max-display-columns nil - which-key-min-display-lines 5 + which-key-min-display-lines 6 which-key-side-window-slot -10) ;; embolden local bindings (set-face-attribute 'which-key-local-map-description-face nil :weight 'bold) (which-key-setup-side-window-bottom) + (setq-hook! 'which-key-init-buffer-hook line-spacing 3) (add-hook 'doom-post-init-hook #'which-key-mode)) @@ -152,6 +153,18 @@ For example, :nvi will map to (list 'normal 'visual 'insert). See (defvar doom--defer nil) (defvar doom--local nil) +(defmacro define-key! (keymap key def &rest rest) + "TODO" + (declare (indent defun)) + `(progn + (define-key ,keymap ,key ,def) + ,@(let (forms) + (while rest + (let ((key (pop rest)) + (def (pop rest))) + (push `(define-key ,keymap ,key ,def) forms))) + (nreverse forms)))) + (defmacro map! (&rest rest) "A nightmare of a key-binding macro that will use `evil-define-key*', `define-key', `local-set-key' and `global-set-key' depending on context and diff --git a/core/core-lib.el b/core/core-lib.el index 4935f871e..b21d0fcc8 100644 --- a/core/core-lib.el +++ b/core/core-lib.el @@ -355,10 +355,13 @@ The available conditions are: `(progn (defun ,hook-name () (when (and (fboundp ',mode) - (not ,mode) + (not (bound-and-true-p ,mode)) (and buffer-file-name (not (file-remote-p buffer-file-name))) ,(if match `(if buffer-file-name (string-match-p ,match buffer-file-name)) t) - ,(if files (doom--resolve-path-forms files '(doom-project-root)) t) + ,(if files (doom--resolve-path-forms + (if (stringp (car files)) (cons 'and files) files) + '(doom-project-root)) + t) ,(or pred-form t)) (,mode 1))) ,@(if (and modes (listp modes)) diff --git a/core/core.el b/core/core.el index 9ff645f42..57b48793e 100644 --- a/core/core.el +++ b/core/core.el @@ -115,6 +115,7 @@ else (except for `window-setup-hook').") tramp-persistency-file-name (concat doom-cache-dir "tramp-persistency.el") url-cache-directory (concat doom-cache-dir "url/") url-configuration-directory (concat doom-etc-dir "url/")) +(load custom-file t t t) ;; @@ -180,8 +181,8 @@ with functions that require it (like modeline segments)." this, you'll get stuttering and random freezes) and resets `file-name-handler-alist'." (setq file-name-handler-alist doom--file-name-handler-alist - gc-cons-threshold 8388608 - gc-cons-percentage 0.1)) + gc-cons-threshold 16777216 + gc-cons-percentage 0.2)) (add-hook 'emacs-startup-hook #'doom|finalize) (add-hook 'doom-reload-hook #'doom|finalize) diff --git a/init.example.el b/init.example.el index d8328ab96..027fcacd1 100644 --- a/init.example.el +++ b/init.example.el @@ -18,13 +18,12 @@ :completion (company ; the ultimate code completion backend - +auto ; as-you-type code completion - +childframe) ; a nicer company UI (Emacs 26+ only) + +auto) ; as-you-type code completion ;(helm ; the *other* search engine for love and life - ; +childframe) ; uses childframes for popups (Emacs 26+ only) + ; +fuzzy) ; enable fuzzy search backend for helm ;ido ; the other *other* search engine... (ivy ; a search engine for love and life - +childframe) ; uses childframes for popups (Emacs 26+ only) + +fuzzy) ; enable fuzzy search backend for ivy :ui doom ; what makes DOOM look the way it does diff --git a/modules/completion/company/autoload.el b/modules/completion/company/autoload.el index ae89ac809..46d922bad 100644 --- a/modules/completion/company/autoload.el +++ b/modules/completion/company/autoload.el @@ -5,7 +5,9 @@ "Toggle as-you-type code completion." (interactive) (require 'company) - (setq company-idle-delay (unless company-idle-delay 0.2))) + (setq company-idle-delay (unless company-idle-delay 0.2)) + (message "Auto completion %s" + (if company-idle-delay "enabled" "disabled"))) ;;;###autoload (defun +company/complete () diff --git a/modules/completion/helm/autoload/evil.el b/modules/completion/helm/autoload/evil.el index d1c1841bd..722c2e714 100644 --- a/modules/completion/helm/autoload/evil.el +++ b/modules/completion/helm/autoload/evil.el @@ -58,3 +58,31 @@ (let ((helm-ag-base-command "rg --no-heading --maxdepth 1")) (+helm--file-search beg end query default-directory (if bang (list "-uu"))))) + +;;;###autoload +(defun +helm--set-prompt-display (pos) + "TODO" + (let (beg state region-active m) + (with-selected-window (minibuffer-window) + (setq beg (save-excursion (vertical-motion 0 (helm-window)) (point)) + state evil-state + region-active (region-active-p) + m (mark t))) + (when region-active + (setq m (- m beg)) + ;; Increment pos to handle the space before prompt (i.e `pref'). + (put-text-property (1+ (min m pos)) (+ 2 (max m pos)) + 'face + (list :background (face-background 'region)) + header-line-format)) + (put-text-property + ;; Increment pos to handle the space before prompt (i.e `pref'). + (+ 1 pos) (+ 2 pos) + 'face + (if (eq state 'insert) + 'underline + ;; Don't just use 'cursor, this can hide the current character. + (list :inverse-video t + :foreground (face-background 'cursor) + :background (face-background 'default))) + header-line-format))) diff --git a/modules/completion/helm/config.el b/modules/completion/helm/config.el index e10c715cb..8487961c6 100644 --- a/modules/completion/helm/config.el +++ b/modules/completion/helm/config.el @@ -38,23 +38,13 @@ (def-package! helm :after helm-mode :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 + (setq helm-candidate-number-limit 50 ;; 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) + helm-mode-handle-completion-in-region nil) :config (setq projectile-completion-system 'helm) @@ -105,19 +95,38 @@ (let ((bg-color (face-background 'default nil))) `(:background ,bg-color :foreground ,bg-color))) (setq-local cursor-type nil)))) - (add-hook 'helm-minibuffer-set-up-hook #'+helm*hide-minibuffer-maybe) - - ) + (add-hook 'helm-minibuffer-set-up-hook #'+helm*hide-minibuffer-maybe)) -(def-package! helm-locate - :defer t - :init (defvar helm-generic-files-map (make-sparse-keymap)) - :config (set-keymap-parent helm-generic-files-map helm-map)) +(def-package! helm-flx + :when (featurep! +fuzzy) + :after helm + :init + (setq helm-candidate-number-limit 40 + helm-M-x-fuzzy-match t + helm-apropos-fuzzy-match t + helm-bookmark-show-location t + helm-buffers-fuzzy-matching t + helm-completion-in-region-fuzzy-match t + helm-file-cache-fuzzy-match t + helm-imenu-fuzzy-match t + helm-locate-fuzzy-match t + helm-flx-for-helm-locate t + helm-mode-fuzzy-match t + helm-projectile-fuzzy-match t + helm-recentf-fuzzy-match t + helm-semantic-fuzzy-match t) + :config + (helm-flx-mode +1)) -(after! helm-bookmark - (setq-default helm-bookmark-show-location t)) +;; `helm-locate' +(defvar helm-generic-files-map (make-sparse-keymap)) +(after! helm-locate (set-keymap-parent helm-generic-files-map helm-map)) + + +;; `helm-bookmark' +(setq helm-bookmark-show-location t) (after! helm-files @@ -131,9 +140,9 @@ :map helm-ag-edit-map [remap quit-window] #'helm-ag--edit-abort) -(after! helm-css-scss ; https://github.com/ShingoFukuyama/helm-css-scss - (setq helm-css-scss-split-direction #'split-window-vertically - helm-css-scss-split-with-multiple-windows t)) +;; `helm-css-scss' -- https://github.com/ShingoFukuyama/helm-css-scss +(setq helm-css-scss-split-direction #'split-window-vertically + helm-css-scss-split-with-multiple-windows t) (def-package! helm-swoop ; https://github.com/ShingoFukuyama/helm-swoop @@ -149,6 +158,71 @@ :commands wgrep-change-to-wgrep-mode :config (setq wgrep-auto-save-buffer t)) + (def-package! posframe - :after helm - :when (and EMACS26+ (featurep! +childframe))) + :when (and EMACS26+ (featurep! +childframe)) + :after helm) + + +;; +;; Evil integration +;; + +(when (featurep! :feature evil +everywhere) + (setq helm-default-prompt-display-function #'+helm--set-prompt-display) + + (map! (:after helm + :map helm-map + :ni "M-[" #'helm-previous-source + :ni "M-]" #'helm-next-source + :ni "M-l" #'helm-execute-persistent-action + :ni "M-j" #'helm-next-line + :ni "M-k" #'helm-previous-line + :ni "C-f" #'helm-next-page + :ni "C-b" #'helm-previous-page + :n "" #'helm-select-action ; TODO: Ivy has "ga". + :n "[" #'helm-previous-source + :n "]" #'helm-next-source + :n "gk" #'helm-previous-source + :n "gj" #'helm-next-source + :n "(" #'helm-prev-visible-mark + :n ")" #'helm-next-visible-mark + :n "j" #'helm-next-line + :n "k" #'helm-previous-line + :n "gg" #'helm-beginning-of-buffer + :n "G" #'helm-end-of-buffer + :n "/" #'helm-quit-and-find-file + :n "gr" #'helm-refresh + :n "yp" #'helm-yank-selection + :n "yP" #'helm-copy-to-buffer + :n "yy" #'helm-kill-selection-and-quit) + (:after helm-files + :map (helm-find-files-map helm-read-file-map) + :n "go" #'helm-ff-run-switch-other-window + :n "/" #'helm-ff-run-find-sh-command + :ni "S-" #'helm-ff-run-switch-other-window + :ni "M-h" #'helm-find-files-up-one-level + :n "=" #'helm-ff-run-ediff-file + :n "%" #'helm-ff-run-query-replace-regexp + :n "D" #'helm-ff-run-delete-file) ; Ivy has "D". + (:after helm-locate + :map helm-generic-files-map + :n "go" #'helm-ff-run-switch-other-window + :ni "S-" #'helm-ff-run-switch-other-window) + (:after helm-buffers + :map helm-buffer-map + :n "go" #'helm-buffer-switch-other-window + :n "gO" #'display-buffer + :ni "S-" #'helm-buffer-switch-other-window + :ni "M-" #'display-buffer + :n "=" #'helm-buffer-run-ediff + :n "%" #'helm-buffer-run-query-replace-regexp + :n "D" #'helm-buffer-run-kill-persistent) ; Ivy has "D". + (:after helm-regexp + :map helm-moccur-map + :n "go" #'helm-moccur-run-goto-line-ow + :ni "S-" #'helm-moccur-run-goto-line-ow) + (:after helm-grep + :map helm-grep-map + :n "go" #'helm-grep-run-other-window-action + :ni "S-" #'helm-grep-run-other-window-action))) diff --git a/modules/completion/helm/packages.el b/modules/completion/helm/packages.el index fb11d95b5..9144ff576 100644 --- a/modules/completion/helm/packages.el +++ b/modules/completion/helm/packages.el @@ -10,5 +10,7 @@ (package! helm-projectile) (package! helm-swoop) (package! wgrep) +(when (featurep! +fuzzy) + (package! helm-flx)) (when (and EMACS26+ (featurep! +childframe)) (package! posframe)) diff --git a/modules/completion/ivy/config.el b/modules/completion/ivy/config.el index 822434c23..702afd189 100644 --- a/modules/completion/ivy/config.el +++ b/modules/completion/ivy/config.el @@ -28,7 +28,6 @@ immediately runs it on the current candidate (ending the ivy session)." :after-call pre-command-hook :config (setq ivy-height 15 - ivy-do-completion-in-region nil ivy-wrap t ivy-fixed-height-minibuffer t projectile-completion-system 'ivy @@ -67,16 +66,8 @@ immediately runs it on the current candidate (ending the ivy session)." (ivy-set-display-transformer cmd '+ivy-buffer-transformer))) -(def-package! swiper :commands (swiper swiper-all)) - - (def-package! counsel - :commands (counsel-ag counsel-rg counsel-pt counsel-apropos counsel-bookmark - counsel-describe-function counsel-describe-variable - counsel-describe-face counsel-M-x counsel-file-jump - counsel-find-file counsel-find-library counsel-info-lookup-symbol - counsel-imenu counsel-recentf counsel-yank-pop - counsel-descbinds counsel-org-capture counsel-grep-or-swiper) + :commands counsel-describe-face :init (map! [remap apropos] #'counsel-apropos [remap bookmark-jump] #'counsel-bookmark @@ -127,9 +118,7 @@ immediately runs it on the current candidate (ending the ivy session)." ;; Used by `counsel-M-x' -(def-package! smex - :commands (smex smex-major-mode-commands) - :config +(after! smex (setq smex-save-file (concat doom-cache-dir "/smex-items")) (smex-initialize)) @@ -220,3 +209,64 @@ immediately runs it on the current candidate (ending the ivy session)." ;; posframe doesn't work well with async sources (dolist (fn '(swiper counsel-rg counsel-ag counsel-pt counsel-grep counsel-git-grep)) (map-put ivy-display-functions-alist fn nil))) + + +(def-package! flx + :when (featurep! +fuzzy) + :defer t ; is loaded by ivy + :init + (setq ivy-re-builders-alist + '((counsel-ag . ivy--regex-plus) + (counsel-rg . ivy--regex-plus) + (counsel-pt . ivy--regex-plus) + (counsel-grep-or-swiper . ivy--regex-plus) + (t . ivy--regex-fuzzy)) + ivy-initial-inputs-alist nil)) + + +;; +;; Evil key fixes +;; + +(map! :when (featurep! :feature evil +everywhere) + :after ivy + :map ivy-occur-mode-map + :n [mouse-1] #'ivy-occur-click + :n "" #'ivy-occur-press-and-switch + :m "j" #'ivy-occur-next-line + :m "k" #'ivy-occur-previous-line + :m "h" #'evil-backward-char + :m "l" #'evil-forward-char + :m "g" nil + :m "gg" #'evil-goto-first-line + :n "gf" #'ivy-occur-press + :n "ga" #'ivy-occur-read-action + :n "go" #'ivy-occur-dispatch + :n "gc" #'ivy-occur-toggle-calling + :n "gr" #'ivy-occur-revert-buffer + :n "q" #'quit-window + + :map ivy-occur-grep-mode-map + :v "j" #'evil-next-line + :v "k" #'evil-previous-line + :n "D" #'ivy-occur-delete-candidate + :n "C-d" #'evil-scroll-down + :n "d" #'ivy-occur-delete-candidate + :n "C-x C-q" #'ivy-wgrep-change-to-wgrep-mode + :n "i" #'ivy-wgrep-change-to-wgrep-mode + :n "gd" #'ivy-occur-delete-candidate + :n [mouse-1] #'ivy-occur-click + :n "" #'ivy-occur-press-and-switch + :m "j" #'ivy-occur-next-line + :m "k" #'ivy-occur-previous-line + :m "h" #'evil-backward-char + :m "l" #'evil-forward-char + :m "g" nil + :m "gg" #'evil-goto-first-line + :n "gf" #'ivy-occur-press + :n "gr" #'ivy-occur-revert-buffer + :n "ga" #'ivy-occur-read-action + :n "go" #'ivy-occur-dispatch + :n "gc" #'ivy-occur-toggle-calling + ;; quit + :n "q" #'quit-window) diff --git a/modules/completion/ivy/packages.el b/modules/completion/ivy/packages.el index 0d764a54d..b8b76609a 100644 --- a/modules/completion/ivy/packages.el +++ b/modules/completion/ivy/packages.el @@ -10,5 +10,8 @@ (package! ivy-rich) (package! wgrep) +(when (featurep! +fuzzy) + (package! flx)) + (when (and EMACS26+ (featurep! +childframe)) (package! ivy-posframe)) diff --git a/modules/config/default/+bindings.el b/modules/config/default/+bindings.el index 158399161..09d6deab7 100644 --- a/modules/config/default/+bindings.el +++ b/modules/config/default/+bindings.el @@ -72,262 +72,6 @@ "C-x p" #'+popup/other - ;; --- ------------------------------------- - (:leader - :desc "Ex command" :nv ";" #'evil-ex - :desc "M-x" :nv ":" #'execute-extended-command - :desc "Pop up scratch buffer" :nv "x" #'doom/open-scratch-buffer - :desc "Org Capture" :nv "X" #'org-capture - - ;; Most commonly used - :desc "Find file in project" :n "SPC" #'projectile-find-file - :desc "Switch workspace buffer" :n "," #'persp-switch-to-buffer - :desc "Switch buffer" :n "<" #'switch-to-buffer - :desc "Browse files" :n "." #'find-file - :desc "Toggle last popup" :n "~" #'+popup/toggle - :desc "Eval expression" :n "`" #'eval-expression - :desc "Blink cursor line" :n "DEL" #'+nav-flash/blink-cursor - :desc "Jump to bookmark" :n "RET" #'bookmark-jump - - ;; C-u is used by evil - :desc "Universal argument" :n "u" #'universal-argument - :desc "window" :n "w" evil-window-map - - (:desc "previous..." :prefix "[" - :desc "Text size" :nv "[" #'text-scale-decrease - :desc "Buffer" :nv "b" #'previous-buffer - :desc "Diff Hunk" :nv "d" #'git-gutter:previous-hunk - :desc "Todo" :nv "t" #'hl-todo-previous - :desc "Error" :nv "e" #'previous-error - :desc "Workspace" :nv "w" #'+workspace/switch-left - :desc "Smart jump" :nv "h" #'smart-backward - :desc "Spelling error" :nv "s" #'evil-prev-flyspell-error - :desc "Spelling correction" :n "S" #'flyspell-correct-previous-word-generic) - - (:desc "next..." :prefix "]" - :desc "Text size" :nv "]" #'text-scale-increase - :desc "Buffer" :nv "b" #'next-buffer - :desc "Diff Hunk" :nv "d" #'git-gutter:next-hunk - :desc "Todo" :nv "t" #'hl-todo-next - :desc "Error" :nv "e" #'next-error - :desc "Workspace" :nv "w" #'+workspace/switch-right - :desc "Spelling error" :nv "s" #'evil-next-flyspell-error - :desc "Spelling correction" :n "S" #'flyspell-correct-word-generic) - - (:desc "search" :prefix "/" - :desc "Project" :nv "p" #'+ivy/project-search - :desc "Directory" :nv "d" (λ! (+ivy/project-search t)) - :desc "Buffer" :nv "b" #'swiper - :desc "Symbols" :nv "i" #'imenu - :desc "Symbols across buffers" :nv "I" #'imenu-anywhere - :desc "Online providers" :nv "o" #'+lookup/online-select) - - (:desc "workspace" :prefix "TAB" - :desc "Display tab bar" :n "TAB" #'+workspace/display - :desc "New workspace" :n "n" #'+workspace/new - :desc "Load workspace from file" :n "l" #'+workspace/load - :desc "Load last session" :n "L" (λ! (+workspace/load-session)) - :desc "Save workspace to file" :n "s" #'+workspace/save - :desc "Autosave current session" :n "S" #'+workspace/save-session - :desc "Switch workspace" :n "." #'+workspace/switch-to - :desc "Kill all buffers" :n "x" #'doom/kill-all-buffers - :desc "Delete session" :n "X" #'+workspace/kill-session - :desc "Delete this workspace" :n "d" #'+workspace/delete - :desc "Load session" :n "L" #'+workspace/load-session - :desc "Rename workspace" :n "r" #'+workspace/rename - :desc "Next workspace" :n "]" #'+workspace/switch-right - :desc "Previous workspace" :n "[" #'+workspace/switch-left - :desc "Switch to 1st workspace" :n "1" (λ! (+workspace/switch-to 0)) - :desc "Switch to 2nd workspace" :n "2" (λ! (+workspace/switch-to 1)) - :desc "Switch to 3rd workspace" :n "3" (λ! (+workspace/switch-to 2)) - :desc "Switch to 4th workspace" :n "4" (λ! (+workspace/switch-to 3)) - :desc "Switch to 5th workspace" :n "5" (λ! (+workspace/switch-to 4)) - :desc "Switch to 6th workspace" :n "6" (λ! (+workspace/switch-to 5)) - :desc "Switch to 7th workspace" :n "7" (λ! (+workspace/switch-to 6)) - :desc "Switch to 8th workspace" :n "8" (λ! (+workspace/switch-to 7)) - :desc "Switch to 9th workspace" :n "9" (λ! (+workspace/switch-to 8)) - :desc "Switch to last workspace" :n "0" #'+workspace/switch-to-last) - - (:desc "buffer" :prefix "b" - :desc "New empty buffer" :n "n" #'evil-buffer-new - :desc "Switch workspace buffer" :n "b" #'persp-switch-to-buffer - :desc "Switch buffer" :n "B" #'switch-to-buffer - :desc "Kill buffer" :n "k" #'kill-this-buffer - :desc "Kill other buffers" :n "o" #'doom/kill-other-buffers - :desc "Save buffer" :n "s" #'save-buffer - :desc "Pop scratch buffer" :n "x" #'doom/open-scratch-buffer - :desc "Bury buffer" :n "z" #'bury-buffer - :desc "Next buffer" :n "]" #'next-buffer - :desc "Previous buffer" :n "[" #'previous-buffer - :desc "Sudo edit this file" :n "S" #'doom/sudo-this-file) - - (:desc "code" :prefix "c" - :desc "List errors" :n "x" #'flycheck-list-errors - :desc "Evaluate buffer/region" :n "e" #'+eval/buffer - :v "e" #'+eval/region - :desc "Evaluate & replace region" :nv "E" #'+eval:replace-region - :desc "Build tasks" :nv "b" #'+eval/build - :desc "Jump to definition" :n "d" #'+lookup/definition - :desc "Jump to references" :n "D" #'+lookup/references - :desc "Open REPL" :n "r" #'+eval/open-repl - :v "r" #'+eval:repl) - - (:desc "file" :prefix "f" - :desc "Find file" :n "." #'find-file - :desc "Sudo find file" :n ">" #'doom/sudo-find-file - :desc "Find file in project" :n "/" #'projectile-find-file - :desc "Find file from here" :n "?" #'counsel-file-jump - :desc "Find other file" :n "a" #'projectile-find-other-file - :desc "Open project editorconfig" :n "c" #'editorconfig-find-current-editorconfig - :desc "Find directory" :n "d" #'dired - :desc "Find file in emacs.d" :n "e" #'+default/find-in-emacsd - :desc "Browse emacs.d" :n "E" #'+default/browse-emacsd - :desc "Recent files" :n "r" #'recentf-open-files - :desc "Recent project files" :n "R" #'projectile-recentf - :desc "Yank filename" :n "y" #'+default/yank-buffer-filename - :desc "Find file in private config" :n "p" #'+default/find-in-config - :desc "Browse private config" :n "P" #'+default/browse-config) - - (:desc "git" :prefix "g" - :desc "Magit blame" :n "b" #'magit-blame - :desc "Magit commit" :n "c" #'magit-commit - :desc "Magit clone" :n "C" #'magit-clone - :desc "Magit dispatch" :n "d" #'magit-dispatch-popup - :desc "Magit find-file" :n "f" #'magit-find-file - :desc "Magit status" :n "g" #'magit-status - :desc "List gists" :n "G" #'+gist:list - :desc "Initialize repo" :n "i" #'magit-init - :desc "Browse issues tracker" :n "I" #'+vcs/git-browse-issues - :desc "Magit buffer log" :n "l" #'magit-log-buffer-file - :desc "List repositories" :n "L" #'magit-list-repositories - :desc "Browse remote" :n "o" #'+vcs/git-browse - :desc "Magit push popup" :n "p" #'magit-push-popup - :desc "Magit pull popup" :n "P" #'magit-pull-popup - :desc "Git revert hunk" :n "r" #'git-gutter:revert-hunk - :desc "Git revert file" :n "R" #'vc-revert - :desc "Git stage hunk" :n "s" #'git-gutter:stage-hunk - :desc "Git stage file" :n "S" #'magit-stage-file - :desc "Git time machine" :n "t" #'git-timemachine-toggle - :desc "Git unstage file" :n "U" #'magit-unstage-file - :desc "Next hunk" :nv "]" #'git-gutter:next-hunk - :desc "Previous hunk" :nv "[" #'git-gutter:previous-hunk) - - (:desc "help" :prefix "h" - :n "h" help-map - :desc "Apropos" :n "a" #'apropos - :desc "Open Bug Report" :n "b" #'doom/open-bug-report - :desc "Describe char" :n "c" #'describe-char - :desc "Describe DOOM module" :n "d" #'doom/describe-module - :desc "Open Doom manual" :n "D" #'doom//open-manual - :desc "Open vanilla sandbox" :n "E" #'doom/open-vanilla-sandbox - :desc "Describe function" :n "f" #'describe-function - :desc "Describe face" :n "F" #'describe-face - :desc "Info" :n "i" #'info-lookup-symbol - :desc "Describe key" :n "k" #'describe-key - :desc "Find documentation" :n "K" #'+lookup/documentation - :desc "Find library" :n "l" #'find-library - :desc "Command log" :n "L" #'global-command-log-mode - :desc "Toggle Emacs log" :n "m" #'view-echo-area-messages - :desc "Describe mode" :n "M" #'describe-mode - :desc "Toggle profiler" :n "p" #'doom/toggle-profiler - :desc "Reload theme" :n "r" #'doom//reload-theme - :desc "Reload private config" :n "R" #'doom//reload - :desc "Describe DOOM setting" :n "s" #'doom/describe-setting - :desc "Describe variable" :n "v" #'describe-variable - :desc "Print Doom version" :n "V" #'doom/version - :desc "Describe at point" :n "." #'helpful-at-point - :desc "What face" :n "'" #'doom/what-face - :desc "What minor modes" :n ";" #'doom/describe-active-minor-mode) - - (:desc "insert" :prefix "i" - :desc "From kill-ring" :nv "y" #'counsel-yank-pop - :desc "From evil registers" :nv "r" #'counsel-evil-registers - :desc "From snippet" :nv "s" #'yas-insert-snippet) - - (:desc "notes" :prefix "n" - :desc "Find file in notes" :n "n" #'+default/find-in-notes - :desc "Browse notes" :n "N" #'+default/browse-notes - :desc "Org capture" :n "x" #'org-capture) - - (:desc "open" :prefix "o" - :desc "Default browser" :n "b" #'browse-url-of-file - :desc "Debugger" :n "d" #'+debug/open - :desc "REPL" :n "r" #'+eval/open-repl - :v "r" #'+eval:repl - :desc "Neotree" :n "n" #'+neotree/open - :desc "Neotree: find file" :n "N" #'+neotree/find-this-file - :desc "Imenu sidebar" :nv "i" #'imenu-list-smart-toggle - :desc "Terminal" :n "t" #'+term/open - :desc "Terminal in popup" :n "T" #'+term/open-popup-in-project - :desc "Eshell" :n "e" #'+eshell/open - :desc "Eshell in popup" :n "E" #'+eshell/open-popup - - (:when (featurep! :collab floobits) - :desc "floobits" :prefix "f" - :n "c" #'floobits-clear-highlights - :n "f" #'floobits-follow-user - :n "j" #'floobits-join-workspace - :n "l" #'floobits-leave-workspace - :n "R" #'floobits-share-dir-private - :n "s" #'floobits-summon - :n "t" #'floobits-follow-mode-toggle - :n "U" #'floobits-share-dir-public) - - ;; macos - (:when IS-MAC - :desc "Reveal in Finder" :n "o" #'+macos/reveal-in-finder - :desc "Reveal project in Finder" :n "O" #'+macos/reveal-project-in-finder - :desc "Send to Transmit" :n "u" #'+macos/send-to-transmit - :desc "Send project to Transmit" :n "U" #'+macos/send-project-to-transmit - :desc "Send to Launchbar" :n "l" #'+macos/send-to-launchbar - :desc "Send project to Launchbar" :n "L" #'+macos/send-project-to-launchbar)) - - (:desc "project" :prefix "p" - :desc "Browse project" :n "." #'+default/browse-project - :desc "Find file in project" :n "/" #'projectile-find-file - :desc "Run cmd in project root" :nv "!" #'projectile-run-shell-command-in-root - :desc "Compile project" :n "c" #'projectile-compile-project - :desc "Find other file" :n "o" #'projectile-find-other-file - :desc "Switch project" :n "p" #'projectile-switch-project - :desc "Recent project files" :n "r" #'projectile-recentf - :desc "List project tasks" :n "t" #'+ivy/tasks - :desc "Invalidate cache" :n "x" #'projectile-invalidate-cache) - - (:desc "quit" :prefix "q" - :desc "Save and quit" :n "q" #'evil-save-and-quit - :desc "Quit (forget session)" :n "Q" #'+workspace/kill-session-and-quit - :desc "Restart Doom Emacs" :n "r" #'restart-emacs) - - (:when (featurep! :tools upload) - (:desc "remote" :prefix "r" - :desc "Upload local" :n "u" #'ssh-deploy-upload-handler - :desc "Upload local (force)" :n "U" #'ssh-deploy-upload-handler-forced - :desc "Download remote" :n "d" #'ssh-deploy-download-handler - :desc "Diff local & remote" :n "D" #'ssh-deploy-diff-handler - :desc "Browse remote files" :n "." #'ssh-deploy-browse-remote-handler - :desc "Detect remote changes" :n ">" #'ssh-deploy-remote-changes-handler)) - - (:when (featurep! :feature snippets) - (:desc "snippets" :prefix "s" - :desc "New snippet" :n "n" #'yas-new-snippet - :desc "Insert snippet" :nv "i" #'yas-insert-snippet - :desc "Find snippet" :n "s" #'+default/find-in-snippets - :desc "Find snippet for mode" :n "S" #'+default/browse-snippets - :desc "Find global snippet" :n "/" #'yas-visit-snippet-file)) - - (:desc "toggle" :prefix "t" - :desc "Flyspell" :n "s" #'flyspell-mode - :desc "Flycheck" :n "f" #'flycheck-mode - :desc "Line numbers" :n "l" #'doom/toggle-line-numbers - :desc "Frame fullscreen" :n "F" #'toggle-frame-fullscreen - :desc "Indent guides" :n "i" #'highlight-indentation-mode - :desc "Indent guides (column)" :n "I" #'highlight-indentation-current-column-mode - :desc "Impatient mode" :n "h" #'+impatient-mode/toggle - :desc "Big mode" :n "b" #'doom-big-font-mode - :desc "Evil goggles" :n "g" #'evil-goggles-mode - :desc "org-tree-slide mode" :n "p" #'+org-present/start)) - - ;; --- Personal vim-esque bindings ------------------ :nv "K" #'+lookup/documentation :n "zx" #'kill-this-buffer @@ -589,14 +333,12 @@ [right] #'forward-char [escape] #'helm-keyboard-quit [tab] #'helm-execute-persistent-action) - (:after helm-files (:map helm-generic-files-map :e "ESC" #'helm-keyboard-quit) (:map helm-find-files-map "C-w" #'helm-find-files-up-one-level "TAB" #'helm-execute-persistent-action)) - (:after helm-ag (:map helm-ag-map "" #'helm-ag-edit))) @@ -608,21 +350,11 @@ ;; ivy (:after ivy :map ivy-minibuffer-map - [escape] #'keyboard-escape-quit - "C-SPC" #'ivy-call-and-recenter - "M-z" #'undo - "M-v" #'yank - "C-v" #'yank - "C-r" #'evil-paste-from-register - "C-k" #'ivy-previous-line - "C-j" #'ivy-next-line - "C-A-k" #'ivy-scroll-down-command - "C-A-j" #'ivy-scroll-up-command - "C-l" #'ivy-alt-done - "C-w" #'ivy-backward-kill-word - "C-u" #'ivy-kill-line - "C-b" #'backward-word - "C-f" #'forward-word) + "C-SPC" #'ivy-call-and-recenter ; preview file + "C-l" #'ivy-alt-done + "M-z" #'undo + "M-v" #'yank + "C-v" #'yank) ;; neotree (:after neotree @@ -702,9 +434,10 @@ ;; --- Built-in plugins ----------------------------- - (:after comint - ;; TAB auto-completion in term buffers - :map comint-mode-map [tab] #'company-complete) + (:when (featurep! :completion company) + (:after comint + ;; TAB auto-completion in term buffers + :map comint-mode-map [tab] #'company-complete)) (:map* (help-mode-map helpful-mode-map) :n "o" #'ace-link-help @@ -718,6 +451,266 @@ [remap quit-window] #'kill-this-buffer)) +;; +;; +;; + +(map! :leader + :desc "Ex command" :nv ";" #'evil-ex + :desc "M-x" :nv ":" #'execute-extended-command + :desc "Pop up scratch buffer" :nv "x" #'doom/open-scratch-buffer + :desc "Org Capture" :nv "X" #'org-capture + + ;; Most commonly used + :desc "Find file in project" :n "SPC" #'projectile-find-file + :desc "Switch workspace buffer" :n "," #'persp-switch-to-buffer + :desc "Switch buffer" :n "<" #'switch-to-buffer + :desc "Browse files" :n "." #'find-file + :desc "Toggle last popup" :n "~" #'+popup/toggle + :desc "Eval expression" :n "`" #'eval-expression + :desc "Blink cursor line" :n "DEL" #'+nav-flash/blink-cursor + :desc "Jump to bookmark" :n "RET" #'bookmark-jump + + ;; C-u is used by evil + :desc "Universal argument" :n "u" #'universal-argument + :desc "window" :n "w" evil-window-map + + (:desc "previous..." :prefix "[" + :desc "Text size" :nv "[" #'text-scale-decrease + :desc "Buffer" :nv "b" #'previous-buffer + :desc "Diff Hunk" :nv "d" #'git-gutter:previous-hunk + :desc "Todo" :nv "t" #'hl-todo-previous + :desc "Error" :nv "e" #'previous-error + :desc "Workspace" :nv "w" #'+workspace/switch-left + :desc "Smart jump" :nv "h" #'smart-backward + :desc "Spelling error" :nv "s" #'evil-prev-flyspell-error + :desc "Spelling correction" :n "S" #'flyspell-correct-previous-word-generic) + + (:desc "next..." :prefix "]" + :desc "Text size" :nv "]" #'text-scale-increase + :desc "Buffer" :nv "b" #'next-buffer + :desc "Diff Hunk" :nv "d" #'git-gutter:next-hunk + :desc "Todo" :nv "t" #'hl-todo-next + :desc "Error" :nv "e" #'next-error + :desc "Workspace" :nv "w" #'+workspace/switch-right + :desc "Spelling error" :nv "s" #'evil-next-flyspell-error + :desc "Spelling correction" :n "S" #'flyspell-correct-word-generic) + + (:desc "search" :prefix "/" + :desc "Project" :nv "p" #'+ivy/project-search + :desc "Directory" :nv "d" (λ! (+ivy/project-search t)) + :desc "Buffer" :nv "b" #'swiper + :desc "Symbols" :nv "i" #'imenu + :desc "Symbols across buffers" :nv "I" #'imenu-anywhere + :desc "Online providers" :nv "o" #'+lookup/online-select) + + (:desc "workspace" :prefix "TAB" + :desc "Display tab bar" :n "TAB" #'+workspace/display + :desc "New workspace" :n "n" #'+workspace/new + :desc "Load workspace from file" :n "l" #'+workspace/load + :desc "Load last session" :n "L" (λ! (+workspace/load-session)) + :desc "Save workspace to file" :n "s" #'+workspace/save + :desc "Autosave current session" :n "S" #'+workspace/save-session + :desc "Switch workspace" :n "." #'+workspace/switch-to + :desc "Kill all buffers" :n "x" #'doom/kill-all-buffers + :desc "Delete session" :n "X" #'+workspace/kill-session + :desc "Delete this workspace" :n "d" #'+workspace/delete + :desc "Load session" :n "L" #'+workspace/load-session + :desc "Rename workspace" :n "r" #'+workspace/rename + :desc "Next workspace" :n "]" #'+workspace/switch-right + :desc "Previous workspace" :n "[" #'+workspace/switch-left + :desc "Switch to 1st workspace" :n "1" (λ! (+workspace/switch-to 0)) + :desc "Switch to 2nd workspace" :n "2" (λ! (+workspace/switch-to 1)) + :desc "Switch to 3rd workspace" :n "3" (λ! (+workspace/switch-to 2)) + :desc "Switch to 4th workspace" :n "4" (λ! (+workspace/switch-to 3)) + :desc "Switch to 5th workspace" :n "5" (λ! (+workspace/switch-to 4)) + :desc "Switch to 6th workspace" :n "6" (λ! (+workspace/switch-to 5)) + :desc "Switch to 7th workspace" :n "7" (λ! (+workspace/switch-to 6)) + :desc "Switch to 8th workspace" :n "8" (λ! (+workspace/switch-to 7)) + :desc "Switch to 9th workspace" :n "9" (λ! (+workspace/switch-to 8)) + :desc "Switch to last workspace" :n "0" #'+workspace/switch-to-last) + + (:desc "buffer" :prefix "b" + :desc "New empty buffer" :n "n" #'evil-buffer-new + :desc "Switch workspace buffer" :n "b" #'persp-switch-to-buffer + :desc "Switch buffer" :n "B" #'switch-to-buffer + :desc "Kill buffer" :n "k" #'kill-this-buffer + :desc "Kill other buffers" :n "o" #'doom/kill-other-buffers + :desc "Save buffer" :n "s" #'save-buffer + :desc "Pop scratch buffer" :n "x" #'doom/open-scratch-buffer + :desc "Bury buffer" :n "z" #'bury-buffer + :desc "Next buffer" :n "]" #'next-buffer + :desc "Previous buffer" :n "[" #'previous-buffer + :desc "Sudo edit this file" :n "S" #'doom/sudo-this-file) + + (:desc "code" :prefix "c" + :desc "List errors" :n "x" #'flycheck-list-errors + :desc "Evaluate buffer/region" :n "e" #'+eval/buffer + :v "e" #'+eval/region + :desc "Evaluate & replace region" :nv "E" #'+eval:replace-region + :desc "Build tasks" :nv "b" #'+eval/build + :desc "Jump to definition" :n "d" #'+lookup/definition + :desc "Jump to references" :n "D" #'+lookup/references + :desc "Open REPL" :n "r" #'+eval/open-repl + :v "r" #'+eval:repl) + + (:desc "file" :prefix "f" + :desc "Find file" :n "." #'find-file + :desc "Sudo find file" :n ">" #'doom/sudo-find-file + :desc "Find file in project" :n "/" #'projectile-find-file + :desc "Find file from here" :n "?" #'counsel-file-jump + :desc "Find other file" :n "a" #'projectile-find-other-file + :desc "Open project editorconfig" :n "c" #'editorconfig-find-current-editorconfig + :desc "Find directory" :n "d" #'dired + :desc "Find file in emacs.d" :n "e" #'+default/find-in-emacsd + :desc "Browse emacs.d" :n "E" #'+default/browse-emacsd + :desc "Recent files" :n "r" #'recentf-open-files + :desc "Recent project files" :n "R" #'projectile-recentf + :desc "Yank filename" :n "y" #'+default/yank-buffer-filename + :desc "Find file in private config" :n "p" #'+default/find-in-config + :desc "Browse private config" :n "P" #'+default/browse-config) + + (:desc "git" :prefix "g" + :desc "Magit blame" :n "b" #'magit-blame + :desc "Magit commit" :n "c" #'magit-commit + :desc "Magit clone" :n "C" #'+magit/clone + :desc "Magit dispatch" :n "d" #'magit-dispatch-popup + :desc "Magit find-file" :n "f" #'magit-find-file + :desc "Magit status" :n "g" #'magit-status + :desc "List gists" :n "G" #'+gist:list + :desc "Initialize repo" :n "i" #'magit-init + :desc "Browse issues tracker" :n "I" #'+vcs/git-browse-issues + :desc "Magit buffer log" :n "l" #'magit-log-buffer-file + :desc "List repositories" :n "L" #'magit-list-repositories + :desc "Browse remote" :n "o" #'+vcs/git-browse + :desc "Magit push popup" :n "p" #'magit-push-popup + :desc "Magit pull popup" :n "P" #'magit-pull-popup + :desc "Git revert hunk" :n "r" #'git-gutter:revert-hunk + :desc "Git revert file" :n "R" #'vc-revert + :desc "Git stage hunk" :n "s" #'git-gutter:stage-hunk + :desc "Git stage file" :n "S" #'magit-stage-file + :desc "Git time machine" :n "t" #'git-timemachine-toggle + :desc "Git unstage file" :n "U" #'magit-unstage-file + :desc "Next hunk" :nv "]" #'git-gutter:next-hunk + :desc "Previous hunk" :nv "[" #'git-gutter:previous-hunk) + + (:desc "help" :prefix "h" + :n "h" help-map + :desc "Apropos" :n "a" #'apropos + :desc "Open Bug Report" :n "b" #'doom/open-bug-report + :desc "Describe char" :n "c" #'describe-char + :desc "Describe DOOM module" :n "d" #'doom/describe-module + :desc "Open Doom manual" :n "D" #'doom//open-manual + :desc "Open vanilla sandbox" :n "E" #'doom/open-vanilla-sandbox + :desc "Describe function" :n "f" #'describe-function + :desc "Describe face" :n "F" #'describe-face + :desc "Info" :n "i" #'info-lookup-symbol + :desc "Describe key" :n "k" #'describe-key + :desc "Find documentation" :n "K" #'+lookup/documentation + :desc "Find library" :n "l" #'find-library + :desc "Command log" :n "L" #'global-command-log-mode + :desc "Toggle Emacs log" :n "m" #'view-echo-area-messages + :desc "Describe mode" :n "M" #'describe-mode + :desc "Toggle profiler" :n "p" #'doom/toggle-profiler + :desc "Reload theme" :n "r" #'doom//reload-theme + :desc "Reload private config" :n "R" #'doom//reload + :desc "Describe DOOM setting" :n "s" #'doom/describe-setting + :desc "Describe variable" :n "v" #'describe-variable + :desc "Print Doom version" :n "V" #'doom/version + :desc "Man pages" :n "w" #'+default/man-or-woman + :desc "Describe at point" :n "." #'helpful-at-point + :desc "What face" :n "'" #'doom/what-face + :desc "What minor modes" :n ";" #'doom/describe-active-minor-mode) + + (:desc "insert" :prefix "i" + :desc "From kill-ring" :nv "y" #'counsel-yank-pop + :desc "From evil registers" :nv "r" #'counsel-evil-registers + :desc "From snippet" :nv "s" #'yas-insert-snippet) + + (:desc "notes" :prefix "n" + :desc "Find file in notes" :n "n" #'+default/find-in-notes + :desc "Browse notes" :n "N" #'+default/browse-notes + :desc "Org capture" :n "x" #'org-capture) + + (:desc "open" :prefix "o" + :desc "Default browser" :n "b" #'browse-url-of-file + :desc "Debugger" :n "d" #'+debug/open + :desc "REPL" :n "r" #'+eval/open-repl + :v "r" #'+eval:repl + :desc "Neotree" :n "n" #'+neotree/open + :desc "Neotree: find file" :n "N" #'+neotree/find-this-file + :desc "Imenu sidebar" :nv "i" #'imenu-list-smart-toggle + :desc "Terminal" :n "t" #'+term/open + :desc "Terminal in popup" :n "T" #'+term/open-popup-in-project + :desc "Eshell" :n "e" #'+eshell/open + :desc "Eshell in popup" :n "E" #'+eshell/open-popup + + (:when (featurep! :collab floobits) + :desc "floobits" :prefix "f" + :n "c" #'floobits-clear-highlights + :n "f" #'floobits-follow-user + :n "j" #'floobits-join-workspace + :n "l" #'floobits-leave-workspace + :n "R" #'floobits-share-dir-private + :n "s" #'floobits-summon + :n "t" #'floobits-follow-mode-toggle + :n "U" #'floobits-share-dir-public) + + ;; macos + (:when IS-MAC + :desc "Reveal in Finder" :n "o" #'+macos/reveal-in-finder + :desc "Reveal project in Finder" :n "O" #'+macos/reveal-project-in-finder + :desc "Send to Transmit" :n "u" #'+macos/send-to-transmit + :desc "Send project to Transmit" :n "U" #'+macos/send-project-to-transmit + :desc "Send to Launchbar" :n "l" #'+macos/send-to-launchbar + :desc "Send project to Launchbar" :n "L" #'+macos/send-project-to-launchbar)) + + (:desc "project" :prefix "p" + :desc "Browse project" :n "." #'+default/browse-project + :desc "Find file in project" :n "/" #'projectile-find-file + :desc "Run cmd in project root" :nv "!" #'projectile-run-shell-command-in-root + :desc "Compile project" :n "c" #'projectile-compile-project + :desc "Find other file" :n "o" #'projectile-find-other-file + :desc "Switch project" :n "p" #'projectile-switch-project + :desc "Recent project files" :n "r" #'projectile-recentf + :desc "List project tasks" :n "t" #'+ivy/tasks + :desc "Invalidate cache" :n "x" #'projectile-invalidate-cache) + + (:desc "quit" :prefix "q" + :desc "Save and quit" :n "q" #'evil-save-and-quit + :desc "Quit (forget session)" :n "Q" #'+workspace/kill-session-and-quit + :desc "Restart Doom Emacs" :n "r" #'restart-emacs) + + (:when (featurep! :tools upload) + (:desc "remote" :prefix "r" + :desc "Upload local" :n "u" #'ssh-deploy-upload-handler + :desc "Upload local (force)" :n "U" #'ssh-deploy-upload-handler-forced + :desc "Download remote" :n "d" #'ssh-deploy-download-handler + :desc "Diff local & remote" :n "D" #'ssh-deploy-diff-handler + :desc "Browse remote files" :n "." #'ssh-deploy-browse-remote-handler + :desc "Detect remote changes" :n ">" #'ssh-deploy-remote-changes-handler)) + + (:when (featurep! :feature snippets) + (:desc "snippets" :prefix "s" + :desc "New snippet" :n "n" #'yas-new-snippet + :desc "Insert snippet" :nv "i" #'yas-insert-snippet + :desc "Find snippet" :n "s" #'+default/find-in-snippets + :desc "Find snippet for mode" :n "S" #'+default/browse-snippets + :desc "Find global snippet" :n "/" #'yas-visit-snippet-file)) + + (:desc "toggle" :prefix "t" + :desc "Flyspell" :n "s" #'flyspell-mode + :desc "Flycheck" :n "f" #'flycheck-mode + :desc "Line numbers" :n "l" #'doom/toggle-line-numbers + :desc "Frame fullscreen" :n "F" #'toggle-frame-fullscreen + :desc "Indent guides" :n "i" #'highlight-indentation-mode + :desc "Indent guides (column)" :n "I" #'highlight-indentation-current-column-mode + :desc "Impatient mode" :n "h" #'+impatient-mode/toggle + :desc "Big mode" :n "b" #'doom-big-font-mode + :desc "Evil goggles" :n "g" #'evil-goggles-mode + :desc "org-tree-slide mode" :n "p" #'+org-present/start)) + + ;; ;; Keybinding fixes ;; @@ -725,56 +718,70 @@ ;; This section is dedicated to "fixing" certain keys so that they behave ;; properly, more like vim, or how I like it. -(map! (:map input-decode-map - [S-iso-lefttab] [backtab] - (:unless window-system "TAB" [tab])) ; Fix TAB in terminal +(define-key input-decode-map [S-iso-lefttab] [backtab]) - ;; I want C-a and C-e to be a little smarter. C-a will jump to - ;; indentation. Pressing it again will send you to the true bol. Same goes - ;; for C-e, except it will ignore comments and trailing whitespace before - ;; jumping to eol. - :i "C-a" #'doom/backward-to-bol-or-indent - :i "C-e" #'doom/forward-to-last-non-comment-or-eol - :i "C-u" #'doom/backward-kill-to-bol-and-indent +;; Fix TAB in terminal +(unless window-system + (define-key input-decode-map (kbd "TAB") [tab])) - ;; textmate-esque newline insertion - :i [M-return] #'evil-open-below - :i [S-M-return] #'evil-open-above - ;; textmate-esque deletion - :ig [M-backspace] #'doom/backward-kill-to-bol-and-indent - ;; Emacsien motions for insert mode - :i "C-b" #'backward-word - :i "C-f" #'forward-word +(after! evil + (evil-define-key* 'insert 'global + ;; I want C-a and C-e to be a little smarter. C-a will jump to indentation. + ;; Pressing it again will send you to the true bol. Same goes for C-e, + ;; except it will ignore comments and trailing whitespace before jumping to + ;; eol. + "\C-a" #'doom/backward-to-bol-or-indent + "\C-e" #'doom/forward-to-last-non-comment-or-eol + "\C-u" #'doom/backward-kill-to-bol-and-indent + ;; textmate-esque newline insertion + [M-return] #'evil-open-below + [S-M-return] #'evil-open-above + ;; Emacsien motions for insert mode + "\C-b" #'backward-word + "\C-f" #'forward-word) - ;; Restore common editing keys (and ESC) in minibuffer - (:map (minibuffer-local-map - minibuffer-local-ns-map - minibuffer-local-completion-map - minibuffer-local-must-match-map - minibuffer-local-isearch-map - read-expression-map) - [escape] #'abort-recursive-edit - (:when (featurep 'evil) - "C-r" #'evil-paste-from-register) - "C-a" #'move-beginning-of-line - "C-w" #'backward-kill-word - "C-u" #'backward-kill-sentence - "C-b" #'backward-word - "C-f" #'forward-word - "C-z" (λ! (ignore-errors (call-interactively #'undo)))) + (evil-define-key* 'insert 'global + ;; textmate-esque deletion + [M-backspace] #'doom/backward-kill-to-bol-and-indent) - (:after evil - (:map evil-ex-completion-map - "C-a" #'move-beginning-of-line - "C-b" #'backward-word - "C-f" #'forward-word)) + (define-key! evil-ex-completion-map + "\C-a" #'move-beginning-of-line + "\C-b" #'backward-word + "\C-f" #'forward-word)) - (:after tabulated-list - (:map tabulated-list-mode-map - "q" #'quit-window)) +(after! tabulated-list + (define-key tabulated-list-mode-map "q" #'quit-window)) - (:after view - (:map view-mode-map "" #'View-quit-all))) +(after! view + (define-key view-mode-map (kbd "") #'View-quit-all)) + +;; Restore common editing keys (and ESC) in minibuffer +(defun +default|fix-minibuffer-in-map (map) + (evil-define-key* nil map + [escape] #'abort-recursive-edit + "\C-a" #'move-beginning-of-line + "\C-w" #'backward-kill-word + "\C-u" #'backward-kill-sentence + "\C-b" #'backward-word + "\C-f" #'forward-word + "\C-z" (λ! (ignore-errors (call-interactively #'undo)))) + (when (featurep! :feature evil +everywhere) + (evil-define-key* nil map + "\C-r" #'abort-recursive-edit + "\C-j" #'next-line + "\C-k" #'previous-line + "\C-d" #'scroll-down-command + "\C-u" #'scroll-up-command))) + +(mapc #'+default|fix-minibuffer-in-map + (list minibuffer-local-map + minibuffer-local-ns-map + minibuffer-local-completion-map + minibuffer-local-must-match-map + minibuffer-local-isearch-map + read-expression-map)) + +(after! ivy (+default|fix-minibuffer-in-map ivy-minibuffer-map)) ;; diff --git a/modules/config/default/autoload/default.el b/modules/config/default/autoload/default.el index 738ea0a7b..52943b47e 100644 --- a/modules/config/default/autoload/default.el +++ b/modules/config/default/autoload/default.el @@ -68,3 +68,12 @@ If ARG (universal argument), runs `compile' from the current directory." (if arg #'projectile-compile-project #'compile)))) + +;;;###autoload +(defun +default/man-or-woman () + "Invoke `man' if man is installed, otherwise use `woman'." + (interactive) + (call-interactively + (if (executable-find "man") + #'man + #'woman))) diff --git a/modules/emacs/dired/config.el b/modules/emacs/dired/config.el index 0dd520ae0..eb1bc9aab 100644 --- a/modules/emacs/dired/config.el +++ b/modules/emacs/dired/config.el @@ -59,3 +59,161 @@ (unless (file-remote-p default-directory) (apply orig-fn args))) (advice-add #'dired-k--highlight :around #'+dired*dired-k-highlight)) + + +;; +;; Evil integration +;; + +(map! :when (featurep! :feature evil +everywhere) + :after dired + :map dired-mode-map + :n "q" #'quit-window + :m "j" #'dired-next-line + :m "k" #'dired-previous-line + :n [mouse-2] 'dired-mouse-find-file-other-window + :n [follow-link] 'mouse-face + ;; Commands to mark or flag certain categories of files + :n "#" #'dired-flag-auto-save-files + :n "." #'dired-clean-directory + :n "~" #'dired-flag-backup-files + ;; Upper case keys (except !) for operating on the marked files + :n "A" #'dired-do-find-regexp + :n "C" #'dired-do-copy + :n "B" #'dired-do-byte-compile + :n "D" #'dired-do-delete + :n "gG" #'dired-do-chgrp ;; FIXME: This can probably live on a better binding. + :n "H" #'dired-do-hardlink + :n "L" #'dired-do-load + :n "M" #'dired-do-chmod + :n "O" #'dired-do-chown + :n "P" #'dired-do-print + :n "Q" #'dired-do-find-regexp-and-replace + :n "R" #'dired-do-rename + :n "S" #'dired-do-symlink + :n "T" #'dired-do-touch + :n "X" #'dired-do-shell-command + :n "Z" #'dired-do-compress + :n "c" #'dired-do-compress-to + :n "!" #'dired-do-shell-command + :n "&" #'dired-do-async-shell-command + ;; Comparison commands + :n "=" #'dired-diff + ;; Tree Dired commands + :n "M-C-?" #'dired-unmark-all-files + :n "M-C-d" #'dired-tree-down + :n "M-C-u" #'dired-tree-up + :n "M-C-n" #'dired-next-subdir + :n "M-C-p" #'dired-prev-subdir + ;; move to marked files + :n "M-{" #'dired-prev-marked-file + :n "M-}" #'dired-next-marked-file + ;; Make all regexp commands share a `%' prefix: + ;; We used to get to the submap via a symbol dired-regexp-prefix, but that + ;; seems to serve little purpose, and copy-keymap does a better job + ;; without it. + :n "%" nil + :n "%u" #'dired-upcase + :n "%l" #'dired-downcase + :n "%d" #'dired-flag-files-regexp + :n "%g" #'dired-mark-files-containing-regexp + :n "%m" #'dired-mark-files-regexp + :n "%r" #'dired-do-rename-regexp + :n "%C" #'dired-do-copy-regexp + :n "%H" #'dired-do-hardlink-regexp + :n "%R" #'dired-do-rename-regexp + :n "%S" #'dired-do-symlink-regexp + :n "%&" #'dired-flag-garbage-files + ;; mark + :n "*" nil + :n "**" #'dired-mark-executables + :n "*/" #'dired-mark-directories + :n "*@" #'dired-mark-symlinks + :n "*%" #'dired-mark-files-regexp + :n "*(" #'dired-mark-sexp + :n "*." #'dired-mark-extension + :n "*O" #'dired-mark-omitted + :n "*c" #'dired-change-marks + :n "*s" #'dired-mark-subdir-files + :n "*m" #'dired-mark + :n "*u" #'dired-unmark + :n "*?" #'dired-unmark-all-files + :n "*!" #'dired-unmark-all-marks + :n "U" #'dired-unmark-all-marks + :n "* " #'dired-unmark-backward + :n "* C-n" #'dired-next-marked-file + :n "* C-p" #'dired-prev-marked-file + :n "*t" #'dired-toggle-marks + ;; Lower keys for commands not operating on all the marked files + :n "a" #'dired-find-alternate-file + :n "d" #'dired-flag-file-deletion + :n "gf" #'dired-find-file + :n "C-m" #'dired-find-file + :n "gr" #'revert-buffer + :n "i" #'dired-toggle-read-only + :n "I" #'dired-maybe-insert-subdir + :n "J" #'dired-goto-file + :n "K" #'dired-do-kill-lines + :n "r" #'dired-do-redisplay + :n "m" #'dired-mark + :n "t" #'dired-toggle-marks + :n "u" #'dired-unmark ; also "*u" + :n "W" #'browse-url-of-dired-file + :n "x" #'dired-do-flagged-delete + :n "gy" #'dired-show-file-type ;; FIXME: This could probably go on a better key. + :n "Y" #'dired-copy-filename-as-kill + :n "+" #'dired-create-directory + ;; open + :n "" #'dired-find-file + :n "S-" #'dired-find-file-other-window + :n "M-" #'dired-display-file + :n "gO" #'dired-find-file-other-window + :n "go" #'dired-view-file + ;; sort + :n "o" #'dired-sort-toggle-or-edit + ;; moving + :m "gj" #'dired-next-dirline + :m "gk" #'dired-prev-dirline + :n "[" #'dired-prev-dirline + :n "]" #'dired-next-dirline + :n "<" #'dired-prev-dirline + :n ">" #'dired-next-dirline + :n "^" #'dired-up-directory + :n [?\S-\ ] 'dired-previous-line + :n [remap next-line] 'dired-next-line + :n [remap previous-line] 'dired-previous-line + ;; hiding + :n "g$" #'dired-hide-subdir ;; FIXME: This can probably live on a better binding. + :n "M-$" #'dired-hide-all + :n "(" #'dired-hide-details-mode + ;; isearch + :n "M-s a C-s" 'dired-do-isearch + :n "M-s a M-C-s" #'dired-do-isearch-regexp + :n "M-s f C-s" 'dired-isearch-filenames + :n "M-s f M-C-s" #'dired-isearch-filenames-regexp + ;; misc + :n [remap read-only-mode] 'dired-toggle-read-only + ;; `toggle-read-only' is an obsolete alias for `read-only-mode' + :n [remap toggle-read-only] 'dired-toggle-read-only + :n "g?" #'dired-summary + :n "" #'dired-unmark-backward + :n [remap undo] 'dired-undo + :n [remap advertised-undo] 'dired-undo + ;; thumbnail manipulation (image-dired) + :n "C-t d" #'image-dired-display-thumbs + :n "C-t t" #'image-dired-tag-files + :n "C-t r" #'image-dired-delete-tag + :n "C-t j" #'image-dired-jump-thumbnail-buffer + :n "C-t i" #'image-dired-dired-display-image + :n "C-t x" #'image-dired-dired-display-external + :n "C-t a" #'image-dired-display-thumbs-append + :n "C-t ." #'image-dired-display-thumb + :n "C-t c" #'image-dired-dired-comment-files + :n "C-t f" #'image-dired-mark-tagged-files + :n "C-t C-t" #'image-dired-dired-toggle-marked-thumbs + :n "C-t e" #'image-dired-dired-edit-comment-and-tags + ;; encryption and decryption (epa-dired) + :n ";d" #'epa-dired-do-decrypt + :n ";v" #'epa-dired-do-verify + :n ";s" #'epa-dired-do-sign + :n ";e" #'epa-dired-do-encrypt) diff --git a/modules/feature/evil/config.el b/modules/feature/evil/config.el index afd7262f0..26f48b42c 100644 --- a/modules/feature/evil/config.el +++ b/modules/feature/evil/config.el @@ -4,8 +4,13 @@ ;; strives to make Emacs a much better vim than vim was. (defvar +evil-collection-disabled-list - '(kotlin-mode ; doesn't do anything useful - simple) ; ditto + '(kotlin-mode ; doesn't do anything useful + simple + ;; we'll do these ourselves + dired + helm + ivy + anaconda-mode) "A list of `evil-collection' modules to disable. See the definition of this variable for an explanation of the defaults (in comments). See `evil-collection-mode-list' for a list of available options.") diff --git a/modules/feature/spellcheck/config.el b/modules/feature/spellcheck/config.el index 712877181..435d2c5f0 100644 --- a/modules/feature/spellcheck/config.el +++ b/modules/feature/spellcheck/config.el @@ -7,6 +7,9 @@ Since spellchecking can be slow in some buffers, this can be disabled with: (setq-hook! 'LaTeX-mode-hook +spellcheck-immediately nil)") +;; `ispell' +(defvar ispell-dictionary "english") + (def-package! flyspell ; built-in :defer t :init diff --git a/modules/feature/version-control/+git.el b/modules/feature/version-control/+git.el index d388c3ebe..b61708d5f 100644 --- a/modules/feature/version-control/+git.el +++ b/modules/feature/version-control/+git.el @@ -1,6 +1,9 @@ ;;; feature/version-control/+git.el -*- lexical-binding: t; -*- -(setq git-commit-fill-column 72) +;; see https://chris.beams.io/posts/git-commit/ +(setq git-commit-fill-column 72 + git-commit-summary-max-length 50 + git-commit-style-convention-checks '(overlong-summary-line non-empty-second-line)) (when (featurep! :feature evil) (add-hook 'git-commit-mode-hook #'evil-insert-state)) diff --git a/modules/feature/version-control/autoload.el b/modules/feature/version-control/autoload.el index 65734f350..8f01cff67 100644 --- a/modules/feature/version-control/autoload.el +++ b/modules/feature/version-control/autoload.el @@ -3,6 +3,7 @@ ;;;###autoload (defun +vcs-root () "Return the root git repo URL for the current file." + (require 'git-link) (let* ((remote (git-link--select-remote)) (remote-url (git-link--remote-url remote)) (remote-info (if remote-url (git-link--parse-remote remote-url)))) diff --git a/modules/lang/data/config.el b/modules/lang/data/config.el index 80134d84d..a7a8424f8 100644 --- a/modules/lang/data/config.el +++ b/modules/lang/data/config.el @@ -44,8 +44,8 @@ (def-project-mode! +data-ansible-mode :modes (yaml-mode) - :files "roles/") + :files ("roles/")) (def-project-mode! +data-vagrant-mode - :files "Vagrantfile") + :files ("Vagrantfile")) diff --git a/modules/lang/javascript/config.el b/modules/lang/javascript/config.el index adda012bc..58e89c416 100644 --- a/modules/lang/javascript/config.el +++ b/modules/lang/javascript/config.el @@ -210,10 +210,10 @@ :on-load (load! "+screeps")) (def-project-mode! +javascript-gulp-mode - :files "gulpfile.js") + :files ("gulpfile.js")) (def-project-mode! +javascript-npm-mode :modes (html-mode css-mode web-mode js2-mode markdown-mode) - :files "package.json" + :files ("package.json") :add-hooks (+javascript|add-node-modules-path)) diff --git a/modules/lang/latex/config.el b/modules/lang/latex/config.el index 20febcb30..750b988af 100644 --- a/modules/lang/latex/config.el +++ b/modules/lang/latex/config.el @@ -69,8 +69,6 @@ (add-hook 'TeX-update-style-hook #'rainbow-delimiters-mode) (when (featurep! :feature spellcheck) (add-hook 'LaTeX-mode-hook #'flyspell-mode)) - ;; Default language setting. - (setq ispell-dictionary "english") ;; Use chktex to search for errors in a latex file. (setcar (cdr (assoc "Check" TeX-command-list)) "chktex -v6 %s") ;; Set a custom item indentation diff --git a/modules/lang/ocaml/config.el b/modules/lang/ocaml/config.el index bdd4974d2..5902dd181 100644 --- a/modules/lang/ocaml/config.el +++ b/modules/lang/ocaml/config.el @@ -8,6 +8,6 @@ :after tuareg :hook (tuareg-mode . merlin-mode) :config - (set! :company-backend 'tuareg-mode 'merlin-compand-backend) + (set! :company-backend 'tuareg-mode 'merlin-company-backend) (after! company - (remove-hook 'company-backends 'merlin-compand-backend))) + (remove-hook 'company-backends 'merlin-company-backend))) diff --git a/modules/lang/org/+babel.el b/modules/lang/org/+babel.el index c4f4cc9d8..3b590d1a9 100644 --- a/modules/lang/org/+babel.el +++ b/modules/lang/org/+babel.el @@ -3,15 +3,20 @@ (add-hook 'org-load-hook #'+org|init-babel) (defvar +org-babel-mode-alist - '(("cpp" . C) - ("C++" . C) - ("D" . C) - ("sh" . shell) - ("bash" . shell) - ("matlab" . octave)) + '((cpp . C) + (C++ . C) + (D . C) + (sh . shell) + (bash . shell) + (matlab . octave)) "An alist that maps languages to babel libraries. This is necessary for babel libraries (ob-*.el) that don't match the name of the language.") +(defvar +org-babel-load-functions () + "A list of functions that are used to try to load the current executing src +block. They take one argument (the language specified in the src block, as +string). Stops at the first function to return non-nil.") + (defun +org|init-babel () (setq org-src-fontify-natively t ; make code pretty org-src-preserve-indentation t ; use native major-mode indentation @@ -19,19 +24,21 @@ libraries (ob-*.el) that don't match the name of the language.") org-src-window-setup 'current-window org-confirm-babel-evaluate nil) ; you don't need my permission - (defun +org*babel-execute-src-block (orig-fn &rest args) + (defun +org*babel-lazy-load-library (orig-fn info) "Load babel libraries as needed when babel blocks are executed." - (let* ((language (org-element-property :language (org-element-at-point))) - (lang-sym (intern language))) - (when (and (not (cdr (assq lang-sym org-babel-load-languages))) - (require - (intern (format "ob-%s" - (or (cdr (assoc (downcase language) +org-babel-mode-alist)) - language))) - nil t)) - (map-put org-babel-load-languages lang-sym t)) - (apply orig-fn args))) - (advice-add #'org-babel-execute-src-block :around #'+org*babel-execute-src-block) + (when (funcall orig-fn info) + (let* ((lang (nth 0 info)) + (lang (if (symbolp lang) lang (intern lang)))) + (when (and (not (cdr (assq lang org-babel-load-languages))) + (or (run-hook-with-args-until-success '+org-babel-load-functions lang) + (require + (intern (format "ob-%s" + (or (cdr (assq lang +org-babel-mode-alist)) + lang))) + nil t))) + (map-put org-babel-load-languages lang t)) + t))) + (advice-add #'org-babel-confirm-evaluate :around #'+org*babel-lazy-load-library) ;; I prefer C-c C-c for confirming over the default C-c ' (map! :map org-src-mode-map "C-c C-c" #'org-edit-src-exit) @@ -44,3 +51,47 @@ libraries (ob-*.el) that don't match the name of the language.") for p in params if (funcall fn (eq (car p) key)) collect p))) + + +;; +;; Plugins +;; + +(def-package! ob-ipython + :when (featurep! +ipython) + :defer t + :init + (defvar +ob-ipython-local-runtime-dir nil + "TODO") + + (setq ob-ipython-resources-dir ".ob-ipython-resrc") + + (defun +org|babel-load-ipython (lang) + (and (string-match-p "^jupyter-" (symbol-name lang)) + (require 'ob-ipython nil t))) + (add-hook '+org-babel-load-functions #'+org|babel-load-ipython) + :config + (set! :popups + '("^\\*Org Src" + ((size . 100) (side . right) (slot . -1) (window-height . 0.6)) + ((quit) (select . t) (modeline))) + '("^\\*Python" + ((slot . 0) (side . right) (size . 100)) + ((select) (quit) (transient))) + '("\\*ob-ipython.*" + ((slot . 2) (side . right) (size . 100) (window-height . 0.2)) + ((select) (quit) (transient))) + '("\\*Python:.*" + ((slot . 0) (side . right) (size . 100)) + ((select) (quit) (transient)))) + ;; TODO Add more popup styles + + ;; advices for remote kernel and org-src-edit + (advice-add 'org-babel-edit-prep:ipython :override #'+org*org-babel-edit-prep:ipython) + (advice-add 'org-babel-ipython-initiate-session :override #'+org*org-babel-ipython-initiate-session) + (advice-add 'ob-ipython--create-repl :override #'+org*ob-ipython--create-repl) + (advice-add 'org-babel-execute:ipython :override #'+org*org-babel-execute:ipython) + + ;; retina resolution image hack + (when (eq window-system 'ns) + (advice-add 'ob-ipython--write-base64-string :around #'+org*ob-ipython--write-base64-string))) diff --git a/modules/lang/org/autoload/ipython.el b/modules/lang/org/autoload/ipython.el new file mode 100644 index 000000000..4a602b6d5 --- /dev/null +++ b/modules/lang/org/autoload/ipython.el @@ -0,0 +1,152 @@ +;;; lang/org/autoload/ipython.el -*- lexical-binding: t; -*- +;;;###if (featurep! +ipython) + +;;;###autoload +(defun +org*org-babel-ipython-initiate-session (&optional session params) + "Create a session named SESSION according to PARAMS." + (if (string= session "none") + (error + "ob-ipython currently only supports evaluation using a session. +Make sure your src block has a :session param.") + (when (not (string-suffix-p ".json" session t)) + (ob-ipython--create-kernel + (ob-ipython--normalize-session + session) + (cdr (assoc :kernel params)))) + (ob-ipython--create-repl + (ob-ipython--normalize-session + session) + params))) + +;;;###autoload +(defun +org*ob-ipython--create-repl (name &optional params) + "Create repl based on NAME and PARAMS. +If PARAMS specifies remote kernel, copy the kernel config from remote server and +create a repl connecting to remote session." + (let ((cmd (string-join (ob-ipython--kernel-repl-cmd name) " "))) + (cond ((string= "default" name) + (run-python cmd nil nil) + (format "*%s*" python-shell-buffer-name)) + ((string-match "^remote-.*ssh.json" name) + (when (not (ignore-errors + (process-live-p + (get-process + (format + "Python:ob-ipython-%s" + name))))) + (let* ((remote (s-split "-" name)) + (remote-host (nth 1 remote)) + (remote-session (nth 3 remote))) + (+org/ob-ipython-generate-local-path-from-remote + remote-session + remote-host + params)))) + ((let* ((process-name (format "Python:ob-ipython-%s" name)) + (python-shell-prompt-detect-enabled nil) + (python-shell-completion-native-enable nil) + (buf (python-shell-make-comint cmd process-name t)) + (dir (cdr (assoc :pydir params)))) + (if dir + (with-current-buffer buf + (setq-local default-directory dir))) + (sleep-for 1) + (format "*%s*" process-name)))))) + +;;;###autoload +(defun +org*org-babel-execute:ipython (body params) + "Execute a BODY of IPython code with PARAMS in org-babel. +This function is called by `org-babel-execute-src-block'." + (message default-directory) + (let ((session (cdr (assoc :session params)))) + (org-babel-ipython-initiate-session session params)) + (ob-ipython--clear-output-buffer) + (if (cdr (assoc :async params)) + (ob-ipython--execute-async body params) + (ob-ipython--execute-sync body params))) + +;;;###autoload +(defun +org/ob-ipython-generate-local-path-from-remote (session host params) + "Given a remote SESSION with PARAMS and corresponding HOST, copy remote config to local, start a jupyter console to generate a new one." + (let* ((runtime-dir + (substring (shell-command-to-string (concat "ssh " host " jupyter --runtime-dir")) 0 -1)) + (runtime-file (concat runtime-dir "/" "kernel-" session ".json")) + (tramp-path (concat "/ssh:" host ":" runtime-file)) + (tramp-copy (concat (or +ob-ipython-local-runtime-dir + (substring (shell-command-to-string "jupyter --runtime-dir") + 0 -1)) + "/remote-" host "-kernel-" session ".json")) + (local-path + (concat + "Python:ob-ipython-" + (file-name-sans-extension (file-name-nondirectory tramp-copy)) + "-ssh.json"))) + ;; scp remote file to local + (copy-file tramp-path tramp-copy t) + ;; connect to remote use new config + (let* ((python-shell-interpreter-interactive-arg " console --simple-prompt") + (python-shell-prompt-detect-enabled nil) + (python-shell-completion-native-enable nil) + (buf (python-shell-make-comint + (concat ob-ipython-command + " console --simple-prompt --existing " + tramp-copy " --ssh " host) + (concat "" local-path) + t)) + (proc (get-buffer-process buf)) + (dir (cdr (assoc :pydir params)))) + (sleep-for 3) + (when dir + (with-current-buffer buf + (setq-local default-directory dir))) + (format "*%s*" proc)))) + +;; * org-src-edit +;;;###autoload +(defun +org*org-babel-edit-prep:ipython (info) + (let* ((params (nth 2 info)) + (session (cdr (assoc :session params)))) + (org-babel-ipython-initiate-session session params)) + ;; Support for python.el's "send-code" commands within edit buffers. + (setq-local python-shell-buffer-name + (format "Python:ob-ipython-%s" + (->> info (nth 2) (assoc :session) + cdr ob-ipython--normalize-session))) + (setq-local default-directory + (format "%s" + (->> info (nth 2) (assoc :pydir) + cdr ob-ipython--normalize-session))) + (ob-ipython-mode 1) + ;; hack on company mode to use company-capf rather than company-anaconda + (when (featurep! :completion company) + (setq-local company-backends + '(company-capf + company-dabbrev + company-files + company-yasnippet)) + (setq-local company-idle-delay nil)) + (when (featurep 'lpy) + (setq lispy-python-proc + (format "Python:ob-ipython-%s" + (->> info (nth 2) (assoc :session) + cdr ob-ipython--normalize-session)) + lispy--python-middleware-loaded-p nil) + (lispy--python-middleware-load))) + +;; * retina +;;;###autoload +(defun +org/ob-ipython-mac-2x-image-file-name (filename &optional scale) + "Return the name of high-resolution image file for FILENAME. +The optional arg SCALE is scale factor, and defaults to 2." + (let ((pos (or (string-match "\\.[^./]*\\'" filename) (length filename)))) + (format "%s@%dx%s" + (substring filename 0 pos) + (or scale 2) + (substring filename pos)))) + +;;;###autoload +(defun +org*ob-ipython--write-base64-string (oldfunc &rest args) + (let ((file (car args)) + (b64-string (cdr args))) + (let ((file2x (+org/ob-ipython-mac-2x-image-file-name file))) + (apply oldfunc file2x b64-string) + (shell-command (concat "convert " file2x " -resize 50% " file))))) diff --git a/modules/lang/org/autoload/org.el b/modules/lang/org/autoload/org.el index 0c890b61c..37d05addb 100644 --- a/modules/lang/org/autoload/org.el +++ b/modules/lang/org/autoload/org.el @@ -307,10 +307,11 @@ wrong places)." (defun +org|realign-table-maybe () "Auto-align table under cursor and re-calculate formulas." (when (and (org-at-table-p) org-table-may-need-update) - (save-excursion + (let ((pt (point))) (quiet! (org-table-recalculate) - (if org-table-may-need-update (org-table-align)))))) + (if org-table-may-need-update (org-table-align))) + (goto-char pt)))) ;;;###autoload (defun +org*realign-table-maybe (&rest _) diff --git a/modules/lang/org/packages.el b/modules/lang/org/packages.el index 91c73748e..da17aa643 100644 --- a/modules/lang/org/packages.el +++ b/modules/lang/org/packages.el @@ -29,7 +29,9 @@ (when (featurep! :lang restclient) (package! ob-restclient)) (when (featurep! :lang crystal) - (package! ob-crystal))) + (package! ob-crystal)) + (when (featurep! +ipython) + (package! ob-ipython))) (when (featurep! +export) (package! ox-pandoc) diff --git a/modules/lang/php/config.el b/modules/lang/php/config.el index bcbf730f4..8485d9521 100644 --- a/modules/lang/php/config.el +++ b/modules/lang/php/config.el @@ -98,5 +98,5 @@ (def-project-mode! +php-composer-mode :modes (web-mode php-mode) - :files "composer.json") + :files ("composer.json")) diff --git a/modules/lang/python/config.el b/modules/lang/python/config.el index 4e129b9d3..8219bb12b 100644 --- a/modules/lang/python/config.el +++ b/modules/lang/python/config.el @@ -25,7 +25,6 @@ is loaded.") (add-hook! 'python-mode-hook #'(flycheck-mode highlight-numbers-mode)) (set! :env "PYTHONPATH" "PYENV_ROOT") - (set! :company-backend 'python-mode '(company-anaconda)) (set! :electric 'python-mode :chars '(?:)) (set! :repl 'python-mode #'+python/repl) @@ -73,18 +72,19 @@ environment variables." (def-package! anaconda-mode - :hook python-mode + :after python :init (setq anaconda-mode-installation-directory (concat doom-etc-dir "anaconda/") anaconda-mode-eldoc-as-single-line t) :config + (add-hook 'python-mode-hook #'anaconda-mode) (add-hook 'anaconda-mode-hook #'anaconda-eldoc-mode) + (set! :company-backend 'python-mode '(company-anaconda)) (set! :popup "^\\*anaconda-mode" nil '((select))) (set! :lookup 'python-mode :definition #'anaconda-mode-find-definitions :references #'anaconda-mode-find-references :documentation #'anaconda-mode-show-doc) - (advice-add #'anaconda-mode-doc-buffer :after #'doom*anaconda-mode-doc-buffer) (defun +python|auto-kill-anaconda-processes () "Kill anaconda processes if this buffer is the last python buffer." @@ -93,13 +93,8 @@ environment variables." (doom-buffers-in-mode 'python-mode (buffer-list))))) (anaconda-mode-stop))) (add-hook! 'python-mode-hook - (add-hook 'kill-buffer-hook #'+python|auto-kill-anaconda-processes nil t))) + (add-hook 'kill-buffer-hook #'+python|auto-kill-anaconda-processes nil t)) - -(def-package! company-anaconda - :when (featurep! :completion company) - :after anaconda-mode - :config (map! :map anaconda-mode-map :localleader :prefix "f" @@ -130,3 +125,15 @@ environment variables." :n "O" #'nosetests-pdb-one :n "V" #'nosetests-pdb-module)) + +;; +;; Evil integration +;; + +(when (featurep! :feature evil +everywhere) + (add-hook 'anaconda-mode-hook #'evil-normalize-keymaps) + (map! :after anaconda-mode + :map anaconda-view-mode-map + :m "]]" #'anaconda-view-mode-next-definition + :m "[[" #'anaconda-view-mode-previous-definition + :n "q" #'quit-window)) diff --git a/modules/tools/ein/config.el b/modules/tools/ein/config.el index cb2ec56b9..3228632ff 100644 --- a/modules/tools/ein/config.el +++ b/modules/tools/ein/config.el @@ -8,9 +8,14 @@ ;; Plugins ;; -(def-package! ein - :defer t - :init +(after! ein + (setq ein:notebook-modes + '(ein:notebook-multilang-mode + ein:notebook-python-mode + ein:notebook-plain-mode) + ;; Slice images into rows; easier to navigate around images + ein:slice-image t) + (set! :popup "\\*ein: .*" :ignore) (set! :popup "\\*ein:tb .*" '((side . bottom) (size . 0.3)) @@ -19,20 +24,14 @@ '((side . left) (size . 50)) '((select))) - ;; Auto complete with company (when (featurep! :completion company) + ;; Code completion with company (setq ein:completion-backend 'ein:use-company-backend) (set! :company-backend '(ein:notebook-multilang-mode ein:notebook-python-mode ein:notebook-plain-mode) 'ein:company-backend)) - :config - (setq ein:notebook-modes - '(ein:notebook-multilang-mode ein:notebook-python-mode ein:notebook-plain-mode) - ;; Slice images into rows; easier to navigate around images - ein:slice-image t) - (after! ein-jupyter (setq ein:jupyter-server-args '("--no-browser")) (unless ein:jupyter-default-notebook-directory diff --git a/modules/tools/magit/autoload.el b/modules/tools/magit/autoload.el index c99088050..9645426e8 100644 --- a/modules/tools/magit/autoload.el +++ b/modules/tools/magit/autoload.el @@ -20,3 +20,50 @@ (kill-process process) (kill-buffer buf))))))) +(defvar +magit-clone-history nil + "History for `+magit/clone' prompt.") +;;;###autoload +(defun +magit/clone (url-or-repo dir) + "Delegates to `magit-clone' or `magithub-clone' depending on the repo url +format." + (interactive + (progn + (require 'magithub) + (let* ((user (ghubp-username)) + (repo (read-from-minibuffer + "Clone repository (user/repo or url): " + (if user (concat user "/")) + nil nil '+magit-clone-history)) + (name (car (last (split-string repo "/" t))))) + (list repo + (read-directory-name + "Destination: " + magithub-clone-default-directory + name nil name))))) + (require 'magithub) + (if (string-match "^\\([^/]+\\)/\\([^/]+\\)$" url-or-repo) + (let ((repo `((owner (login . ,(match-string 1 url-or-repo))) + (name . ,(match-string 2 url-or-repo))))) + (and (or (magithub-request + (ghubp-get-repos-owner-repo repo)) + (let-alist repo + (user-error "Repository %s/%s does not exist" + .owner.login .name))) + (magithub-clone repo dir))) + (magit-clone url-or-repo dir))) + + +;; +;; Advice +;; + +;;;###autoload +(defun +magit*hub-settings--format-magithub.enabled () + "Change the setting to display 'false' as its default." + (magit--format-popup-variable:choices "magithub.enabled" '("true" "false") "false")) + +;;;###autoload +(defun +magit*hub-enabled-p () + "Disables magithub by default." + (magithub-settings--value-or "magithub.enabled" nil + #'magit-get-boolean)) diff --git a/modules/tools/magit/config.el b/modules/tools/magit/config.el index 67d81c9a4..488d4a7a5 100644 --- a/modules/tools/magit/config.el +++ b/modules/tools/magit/config.el @@ -1,5 +1,18 @@ ;;; tools/magit/config.el -*- lexical-binding: t; -*- +(defvar +magit-hub-enable-by-default nil + "Whether or not to enable magithub features for all projects by default.") + +(defvar +magit-hub-features + '(pull-request-merge commit-browse completion) + "What features to initialize when `magithub' is loaded. Set this to `t' to +load everything.") + + +;; +;; Plugins +;; + (def-package! magit :defer t :config @@ -20,7 +33,6 @@ (def-package! magithub - :commands magithub-feature-autoinject :after magit :preface (setq magithub-dir (concat doom-etc-dir "magithub/")) @@ -28,7 +40,16 @@ (setq magithub-clone-default-directory "~/" magithub-preferred-remote-method 'clone_url) :config - (magithub-feature-autoinject t)) + (unless +magit-hub-enable-by-default + ;; Disable magit by default. Can be enabled through magithub settings popup, + ;; or setting `+magit-hub-enable-by-default'. + (advice-add #'magithub-enabled-p :override #'+magit*hub-enabled-p) + ;; I don't use `magithub-settings--simple' to redefine this because it + ;; changes the order of settings. Obnoxious, but the alternative is even + ;; more so. + (advice-add #'magithub-settings--format-magithub.enabled + :override #'+magit*hub-settings--format-magithub.enabled)) + (magithub-feature-autoinject +magit-hub-features)) (def-package! magit-gitflow @@ -36,7 +57,7 @@ (def-package! evil-magit - :when (featurep! :feature evil) + :when (featurep! :feature evil +everywhere) :after magit :init (setq evil-magit-state 'normal) :config diff --git a/modules/tools/magit/packages.el b/modules/tools/magit/packages.el index d510a8977..c96d9cfa0 100644 --- a/modules/tools/magit/packages.el +++ b/modules/tools/magit/packages.el @@ -2,7 +2,8 @@ ;;; tools/magit/packages.el (when (package! magit) - (package! magithub) (package! magit-gitflow) - (when (featurep! :feature evil) + (when (featurep! +hub) + (package! magithub)) + (when (featurep! :feature evil +everywhere) (package! evil-magit))) diff --git a/modules/ui/popup/autoload.el b/modules/ui/popup/autoload.el index c434a8a41..55b4c4ee2 100644 --- a/modules/ui/popup/autoload.el +++ b/modules/ui/popup/autoload.el @@ -257,15 +257,6 @@ Uses `shrink-window-if-larger-than-buffer'." ;; Minor mode ;; -;;;###autoload -(defvar +popup-mode-map (make-sparse-keymap) - "Active keymap in a session with the popup system enabled. See -`+popup-mode'.") - -;;;###autoload -(defvar +popup-buffer-mode-map (make-sparse-keymap) - "Active keymap in popup windows. See `+popup-buffer-mode'.") - ;;;###autoload (define-minor-mode +popup-mode "Global minor mode representing Doom's popup management system." @@ -291,7 +282,8 @@ Uses `shrink-window-if-larger-than-buffer'." window--sides-inhibit-check nil) (+popup|cleanup-rules) (dolist (prop +popup-window-parameters) - (map-delete window-persistent-parameters prop))))) + (setq window-persistent-parameters + (map-delete window-persistent-parameters prop)))))) ;;;###autoload (define-minor-mode +popup-buffer-mode @@ -482,7 +474,7 @@ should match the arguments of `+popup-define' or the :popup setting." (declare (indent defun)) `(let ((+popup--display-buffer-alist +popup--old-display-buffer-alist) display-buffer-alist) - ,@(cl-loop for rule in rules collect `(+popup-define ,@rule)) + ,@(cl-loop for rule in rules collect `(set! :popup ,@rule)) (when (bound-and-true-p +popup-mode) (setq display-buffer-alist +popup--display-buffer-alist)) ,@body)) diff --git a/modules/ui/popup/config.el b/modules/ui/popup/config.el index 552ed57c6..47ab76df9 100644 --- a/modules/ui/popup/config.el +++ b/modules/ui/popup/config.el @@ -97,6 +97,19 @@ a brief description of some native window parameters that Emacs uses: "The default time-to-live for transient buffers whose popup buffers have been deleted.") +(defvar +popup-mode-map (make-sparse-keymap) + "Active keymap in a session with the popup system enabled. See +`+popup-mode'.") + +(defvar +popup-buffer-mode-map + (let ((map (make-sparse-keymap))) + (when (featurep! :feature evil) + ;; for maximum escape coverage in emacs state buffers + (define-key map [escape] #'doom/escape) + (define-key map (kbd "ESC") #'doom/escape)) + map) + "Active keymap in popup windows. See `+popup-buffer-mode'.") + ;; ;; Default popup rules & bootstrap @@ -148,13 +161,6 @@ deleted.") +popup|set-modeline-on-enable +popup|unset-modeline-on-disable)) -(let ((map +popup-buffer-mode-map)) - (when (featurep! :feature evil) - ;; for maximum escape coverage in emacs state buffers - (define-key map [escape] #'doom/escape) - (define-key map (kbd "ESC") #'doom/escape)) - map) - ;; ;; Hacks