;;; init --- user init file -*- lexical-binding: t; -*- (setq inhibit-startup-echo-area-message "alan") (setq inhibit-startup-screen t initial-scratch-message "" initial-major-mode 'fundamental-mode package-enable-at-startup nil evil-want-keybinding nil frame-inhibit-implied-resize t) (let ((default-gc-cons-threshold (* 16 1024 1024)) (default-file-name-handler-alist file-name-handler-alist)) (setq gc-cons-threshold most-positive-fixnum gc-cons-percentage 0.6 file-name-handler-alist nil) (add-hook 'minibuffer-setup-hook (lambda () (setq gc-cons-threshold most-positive-fixnum))) (add-hook 'minibuffer-exit-hook (lambda () (setq gc-cons-threshold default-gc-cons-threshold))) (add-hook 'emacs-startup-hook (lambda () (setq file-name-handler-alist default-file-name-handler-alist))) (add-hook 'after-init-hook (lambda () (setq gc-cons-threshold default-gc-cons-threshold gc-cons-percentage 0.1)))) (package-initialize) (defun reload-user-init-file () "Reload init file." (interactive) (load-file user-init-file)) (eval-when-compile (require 'use-package) (setq use-package-expand-minimally t)) (setq use-package-always-demand (daemonp)) (defvar ap/path-configured nil) (when (and (eq system-type 'darwin) (not ap/path-configured)) (setq exec-path (delete-dups (append (parse-colon-path (elt (split-string-and-unquote (with-output-to-string (with-current-buffer standard-output (call-process "/usr/libexec/path_helper" nil t nil "-s"))) "[=;]") 1)) exec-path)) ap/path-configured t)) ;;; Customize (setq custom-file "~/.emacs.d/custom.el") (load custom-file :noerror :nomessage) (use-package crux :defer 1 :config (crux-reopen-as-root-mode -1)) ;;; Styles ;; I prefer an always-visible cursor. Feels less distracting. (blink-cursor-mode -1) ;; Disable all the bars, unless on OSX, in which case, keep the menu bar. (unless (eq system-type 'darwin) (menu-bar-mode -1)) (scroll-bar-mode -1) (tool-bar-mode -1) (set-fringe-mode '(4 . 4)) ;; Ring the bell sometimes, but not so often (setq ring-bell-function (lambda () (unless (memq this-command '(isearch-abort abort-recursive-edit exit-minibuffer keyboard-quit minibuffer-keyboard-quit undo-tree-undo)) (ding)))) (when (or (daemonp) window-system) (use-package almost-mono-themes :config (load-theme 'almost-mono-white t)) (if (eq window-system 'x) (setq-default line-spacing 0.2)) (setq frame-background-mode 'light) (mapc 'frame-set-background-mode (frame-list))) (setq font-lock-maximum-decoration '((t . 1))) ;;; Chrome (column-number-mode +1) (use-package doom-modeline :hook (emacs-startup . doom-modeline-mode) :config (progn (setq doom-modeline-buffer-file-name-style 'relative-from-project doom-modeline-buffer-icon nil doom-modeline-buffer-modification-icon nil doom-modeline-project-detection 'projectile doom-modeline-vcs-max-length 24 doom-modeline-env-version nil) (let ((foreground (face-attribute 'font-lock-comment-face :foreground))) (set-face-attribute 'doom-modeline-buffer-modified nil :foreground foreground)))) (when (eq system-type 'darwin) (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t)) (add-to-list 'default-frame-alist '(ns-appearance . 'light))) (add-to-list 'default-frame-alist '(width . 100)) (add-to-list 'default-frame-alist '(height . 40)) ;;; Dates & Times (defvar calendar-week-start-day 1) (defvar calendar-date-style 'iso) (defun insert-date (prefix) "Insert the current date. With PREFIX, use British format. With two prefix arguments, write out the day and month name." (interactive "P") (let ((format (cond ((not prefix) "%Y-%m-%d") ((equal prefix '(4)) "%d/%m/%Y") ((equal prefix '(16)) "%A, %d %B %Y")))) (insert (format-time-string format)))) (defun insert-datetime (prefix) "Insert current date and time. With PREFIX, use ISO8601 format." (interactive "P") (let ((format (cond ((not prefix) "%Y-%m-%d %H:%M:%S") ((equal prefix '(4)) "%Y-%m-%dT%H:%M:%SZ")))) (insert (format-time-string format)))) ;;; Keybindings (when (eq system-type 'darwin) (setq mac-option-modifier 'meta mac-right-option-modifier 'none mac-control-modifier 'control mac-right-control-modifier 'left mac-command-modifier 'super mac-right-command-modifier 'left mac-function-modifier 'hyper)) (use-package general :functions (general-unbind general-define-key) :config (progn (general-override-mode +1) (when (eq system-type 'darwin) (general-unbind "s-x")))) (use-package avy :defer 2 :config (setq avy-all-windows nil)) (use-package ace-link :after avy :commands (ace-link-setup-default) :config (ace-link-setup-default)) ;; Popup keybindings following a prefix automatically. (use-package which-key :defer 5 :config (progn (which-key-mode +1) (which-key-setup-side-window-right-bottom))) ;;; Minibuffer (setq enable-recursive-minibuffers t save-silently t uniquify-buffer-name-style 'forward) (minibuffer-depth-indicate-mode t) (use-package hydra :defer 2) (use-package ivy :defer 1 :config (progn (ivy-mode +1))) (use-package ivy-hydra :defer 2) (use-package smerge-mode :after magit :config (defhydra unpackaged/smerge-hydra (:color pink :hint nil :post (smerge-auto-leave)) " ^Move^ ^Keep^ ^Diff^ ^Other^ ^^-----------^^-------------------^^---------------------^^------- _n_ext _b_ase _<_: upper/base _C_ombine _p_rev _u_pper _=_: upper/lower _r_esolve ^^ _l_ower _>_: base/lower _k_ill current ^^ _a_ll _R_efine ^^ _RET_: current _E_diff " ("n" smerge-next) ("p" smerge-prev) ("b" smerge-keep-base) ("u" smerge-keep-upper) ("l" smerge-keep-lower) ("a" smerge-keep-all) ("RET" smerge-keep-current) ("\C-m" smerge-keep-current) ("<" smerge-diff-base-upper) ("=" smerge-diff-upper-lower) (">" smerge-diff-base-lower) ("R" smerge-refine) ("E" smerge-ediff) ("C" smerge-combine-with-next) ("r" smerge-resolve) ("k" smerge-kill-current) ("w" (lambda () (interactive) (save-buffer) (bury-buffer)) "Save and bury buffer" :color blue) ("q" nil "cancel" :color blue)) :hook (magit-diff-visit-file . (lambda () (when (bound-and-true-p smerge-mode) (unpackaged/smerge-hydra/body))))) (use-package swiper :general ([remap isearch-forward] #'swiper-isearch) :config (progn (setq ivy-count-format "%d/%d "))) (use-package amx :config (setq amx-history-length 100)) (use-package counsel :commands (counsel-unicode-char) :general ("M-x" #'counsel-M-x)) ;;; Windows (defun split-window-properly (&optional window) (let ((window (or window (selected-window)))) (or (and (window-splittable-p window) ;; Split window vertically. (with-selected-window window (split-window-below))) (and (window-splittable-p window t) ;; Split window horizontally. (with-selected-window window (split-window-right)))))) (setq split-window-preferred-function #'split-window-properly split-height-threshold 20 split-width-threshold 160) (use-package eyebrowse :after (evil) :config (progn (setq eyebrowse-new-workspace t eyebrowse-mode-line-left-delimiter "" eyebrowse-mode-line-right-delimiter "" eyebrowse-mode-line-separator " " eyebrowse-mode-line-style 'always) (eyebrowse-mode +1)) :general (:keymaps 'evil-window-map "0" #'eyebrowse-switch-to-window-config-0 "1" #'eyebrowse-switch-to-window-config-1 "2" #'eyebrowse-switch-to-window-config-2 "3" #'eyebrowse-switch-to-window-config-3 "4" #'eyebrowse-switch-to-window-config-4 "5" #'eyebrowse-switch-to-window-config-5 "6" #'eyebrowse-switch-to-window-config-6 "7" #'eyebrowse-switch-to-window-config-7 "8" #'eyebrowse-switch-to-window-config-8 "9" #'eyebrowse-switch-to-window-config-9) :ghook ('evil-after-load-hook #'eyebrowse-setup-evil-keys)) (use-package winner :after evil :defer 8 :config (progn (setq winner-boring-buffers '("*Completions*" "*Help*" "*Apropos*" "*Buffer List*" "*info*" "*Compile-Log*")) (winner-mode +1)) :general (:keymaps 'evil-window-map "u" #'winner-undo "r" #'winner-redo "C-r" #'winner-redo)) ;;; Evil (use-package evil :demand t :commands (evil-mode evil-delete-buffer evil-ex-define-cmd) :config (progn (setq-default evil-shift-width 2) (setq evil-mode-line-format nil) (add-to-list 'evil-emacs-state-modes 'eshell-mode) (add-to-list 'evil-emacs-state-modes 'ledger-reconcile-mode) (evil-mode +1)) :general (:states 'motion "C-;" #'evil-avy-goto-line) (:states 'normal ";" #'evil-ex) (:states '(normal motion) "g s" #'evil-avy-goto-symbol-1)) (use-package evil-anzu :defer 2 :after evil) (defvar evil-collection-company-use-tng t) (use-package evil-collection :after (evil) :defer 3 :demand t :commands (evil-collection-init) :config (progn (evil-collection-init))) (general-create-definer my-leader-def :keymaps 'override :states '(normal motion) :prefix ",") (use-package evil-space :defer 1 :after evil :config (evil-space-mode +1)) ;; this macro was copied from here: https://stackoverflow.com/a/22418983/4921402 (defmacro define-and-bind-quoted-text-object (name key start-regex end-regex) (let ((inner-name (make-symbol (concat "evil-inner-" name))) (outer-name (make-symbol (concat "evil-a-" name)))) `(progn (evil-define-text-object ,inner-name (count &optional beg end type) (evil-select-paren ,start-regex ,end-regex beg end type count nil)) (evil-define-text-object ,outer-name (count &optional beg end type) (evil-select-paren ,start-regex ,end-regex beg end type count t)) (define-key evil-inner-text-objects-map ,key #',inner-name) (define-key evil-outer-text-objects-map ,key #',outer-name)))) (use-package evil-surround :after evil :defer 2 :config (progn (define-and-bind-quoted-text-object "slash" "/" "\\/" "\\/") (push '(?\/ . ("/" . "/")) evil-surround-pairs-alist) (global-evil-surround-mode +1))) (use-package evil-embrace :after evil-surround :config (progn (setq evil-embrace-show-help-p nil) (push ?\/ evil-embrace-evil-surround-keys) (evil-embrace-enable-evil-surround-integration) (add-hook 'LaTeX-mode-hook #'embrace-LaTeX-mode-hook) (add-hook 'org-mode-hook #'embrace-org-mode-hook) (add-hook 'ruby-mode-hook #'embrace-ruby-mode-hook) (add-hook 'emacs-lisp-mode-hook #'embrace-emacs-lisp-mode-hook))) (use-package evil-commentary :after evil :defer 2 :config (evil-commentary-mode +1)) (use-package evil-magit :after magit :config (setq evil-magit-use-y-for-yank nil)) (use-package evil-matchit :after evil :defer 2 :config (progn (global-evil-matchit-mode +1))) (use-package evil-quickscope :after evil :commands (evil-quickscope-mode) :ghook ('(magit-mode-hook git-rebase-mode-hook) #'turn-off-evil-quickscope-mode) :config (global-evil-quickscope-mode +1)) (use-package evil-numbers :after evil :general (:states '(normal visual) "C-a" #'evil-numbers/inc-at-pt "C-q" #'evil-numbers/dec-at-pt)) (use-package evil-org :after org :commands (evil-org-set-key-theme) :init (progn (add-hook 'org-agenda-mode-hook #'evil-org-agenda-set-keys)) :ghook ('org-mode-hook #'evil-org-mode) :gfhook #'evil-org-set-key-theme) ;;; Projects (use-package ripgrep :config (progn (setq ripgrep-arguments '("--hidden")))) (use-package projectile :defer 1 :defines projectile-command-map :config (progn (add-to-list 'projectile-globally-ignored-files "package-lock.json") (add-to-list 'projectile-globally-ignored-files "pnpm-lock.yaml") (add-to-list 'projectile-project-root-files "package.json") (add-to-list 'projectile-project-root-files-bottom-up "pnpm-workspace.yaml") (setq projectile-completion-system 'ivy projectile-kill-buffers-filter 'kill-only-files projectile-sort-order 'modification-time projectile-project-root-files-functions '(projectile-root-local projectile-root-top-down projectile-root-bottom-up projectile-root-top-down-recurring)) (projectile-mode +1) (with-eval-after-load 'evil-ex (evil-ex-define-cmd "rg" #'ripgrep-regexp) (evil-ex-define-cmd "prg" #'projectile-ripgrep) (evil-ex-define-cmd "pesh[ell]" #'projectile-run-eshell)))) (use-package counsel-projectile :defer 1 :commands (counsel-projectile-switch-project counsel-projectile-rg counsel-projectile-switch-to-buffer counsel-projectile-mode) :general (:keymaps 'projectile-command-map "s s" #'counsel-projectile-rg "s r" #'counsel-projectile-rg) :config (progn (assq-delete-all #'projectile-ripgrep counsel-projectile-key-bindings) (counsel-projectile-mode +1) (with-eval-after-load 'evil-ex (evil-ex-define-cmd "cprg" #'counsel-projectile-rg) (evil-ex-define-cmd "pb" #'counsel-projectile-switch-to-buffer) (evil-ex-define-cmd "psw[itch]" #'counsel-projectile-switch-project)))) (use-package magit :defer 10 :commands (magit-status magit-dispatch) :config (progn (setq magit-auto-revert-mode nil magit-section-visibility-indicator nil magit-diff-refine-hunk 'all magit-display-buffer-function #'display-buffer magit-completing-read-function #'ivy-completing-read) (global-magit-file-mode +1) (remove-hook 'magit-section-highlight-hook 'magit-section-highlight) (remove-hook 'magit-section-highlight-hook 'magit-section-highlight-selection) (remove-hook 'magit-section-highlight-hook 'magit-diff-highlight))) (eval-when-compile (require 'fringe-helper)) (use-package git-gutter-fringe :defer 5 :config (progn (add-hook 'magit-post-refresh-hook #'git-gutter:update-all-windows) ;; places the git gutter outside the margins. (setq-default fringes-outside-margins nil) ;; thin fringe bitmaps (fringe-helper-define 'git-gutter-fr:added '(center repeated) ".XXX....") (fringe-helper-define 'git-gutter-fr:modified '(center repeated) ".XXX....") (fringe-helper-define 'git-gutter-fr:deleted '(center repeated) ".XXX....") (setq git-gutter-fr:side 'right-fringe) (global-git-gutter-mode 1))) (use-package git-messenger :commands (git-messenger:popup-message) :defer 10 :config (setq git-messenger:use-magit-popup t)) (use-package git-timemachine :commands (git-timemachine)) (use-package editorconfig :defer 2 :init (progn (unless (executable-find "editorconfig") (warn "Missing `editorconfig' executable."))) :config (editorconfig-mode +1)) ;;; Completion (use-package company :defer 2 :commands (company-explicit-action-p) :config (progn (setq company-idle-delay 0.2 company-tooltip-align-annotations t company-show-numbers t company-dabbrev-downcase nil company-dabbrev-ignore-case nil company-begin-commands '(self-insert-command) company-auto-complete #'company-explicit-action-p company-auto-complete-chars '(?\ ?\( ?\) ?.)) (global-company-mode +1) (general-unbind company-active-map "RET" [return])) :general (:states 'insert "TAB" #'company-indent-or-complete-common) (:keymaps 'company-active-map "TAB" #'company-complete-common-or-cycle "" #'company-complete-common-or-cycle "S-TAB" #'company-select-previous "" #'company-select-previous)) (use-package all-the-icons :config (setq all-the-icons-color-icons nil)) (use-package company-lsp :config (progn (setq company-lsp-enable-snippet nil) (add-to-list 'company-backends #'company-lsp))) (use-package company-tabnine :commands (company-tabnine) :after (company) :config (setq company-tabnine-binaries-folder "~/.local/tabnine") :general ("" #'company-tabnine-call-other-backends "" #'company-tabnine-call-other-backends) :init (progn (add-to-list 'company-backends #'company-tabnine))) ;;; Documentation (use-package eldoc :defer 5 :config (progn (setq eldoc-idle-delay 0.5) (global-eldoc-mode +1))) (use-package eldoc-box :after (eldoc eglot) :config (progn (eldoc-box-hover-mode +1) (eldoc-box-hover-at-point-mode +1))) (use-package ehelp :defer 15) (use-package helpful :after ehelp :general (ehelp-map "k" #'helpful-key "v" #'helpful-variable "f" #'helpful-callable)) ;;; Files ;;;; Auto-saving ;; Auto-save everything to a temporary directory, instead of cluttering ;; the filesystem. I don’t want emacs-specific lockfiles, either. (setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t)) create-lockfiles nil) ;;;; Auto-reloading (use-package autorevert :defer 10 :config (progn (setq auto-revert-verbose t auto-revert-use-notify t) (global-auto-revert-mode t))) ;;;; Backups ;; I like to keep my backups out of regular folders. I tell emacs to use ;; a subfolder of its configuration directory for that. Also, use the ;; trash for deleting on OS X. (let ((backup-dir (expand-file-name "~/.emacs.d/backups/"))) (unless (file-directory-p backup-dir) (make-directory backup-dir)) (setq backup-directory-alist `((".*" . ,backup-dir)) backup-by-copying-when-linked t backup-by-copying-when-mismatch t)) (setq delete-by-moving-to-trash t) (use-package goto-chg :defer 1) ;;; Directories (setq dired-dwim-target t dired-recursive-copies 'top dired-listing-switches "-alh" dired-recursive-deleted (if delete-by-moving-to-trash 'always 'top)) (add-hook 'dired-mode-hook (lambda () (dired-hide-details-mode))) (use-package dired-git-info :general (:keymaps 'dired-mode-map :states 'normal ")" #'dired-git-info-mode)) ;;; Shells (use-package eshell :defer 5 :commands (eshell) :functions (eshell/pwd) :init (progn (with-eval-after-load 'evil-ex (evil-ex-define-cmd "esh[ell]" #'eshell))) :config (setq eshell-prompt-function (lambda () (concat (eshell/pwd) "\n$ ")) eshell-prompt-regexp "^[$][[:blank:]]" eshell-cmpl-cycle-completions nil)) (use-package eshell-toggle :after projectile :commands (eshell-toggle) :general ("C-`" #'eshell-toggle) :config (setq eshell-toggle-use-projectile-root t)) (use-package esh-autosuggest :after eshell :ghook ('eshell-mode-hook)) (declare-function eshell-push-command "esh-buf-stack" (CMD)) (defun my-bind-esh-push () (general-define-key :states '(normal insert) :keymaps 'local "M-q" #'eshell-push-command)) (use-package esh-buf-stack :after (eshell) :ghook ('eshell-mode-hook #'my-bind-esh-push) :config (setup-eshell-buf-stack)) (use-package bash-completion :after (eshell)) (use-package fish-completion :when (executable-find "fish") :after (bash-completion) :commands (global-fish-completion-mode) :config (progn (setq fish-completion-fallback-on-bash-p t) (global-fish-completion-mode))) (use-package esh-help :after (eshell) :config (setup-esh-help-eldoc)) (use-package eshell-fringe-status :after eshell :ghook '(eshell-mode-hook)) (use-package eshell-up :after (eshell)) (use-package shell :defer t :general (:keymaps 'shell-mode-map "C-d" #'comint-delchar-or-maybe-eof)) (use-package comint :defer t :general (:keymaps 'comint-mode-map "C-c C-l" #'counsel-shell-history)) ;;; Editing (setq-default indent-tabs-mode nil tab-width 2 tab-always-indent 'complete) (use-package ws-butler :ghook ('prog-mode-hook)) ;;; Major modes ;;;; golang (use-package go-mode :defer t :config (progn (setq-default gofmt-command "goimports") (add-hook 'go-mode-hook (lambda () (add-hook 'before-save-hook #'gofmt-before-save) (if (not (string-match-p "go" compile-command)) (set (make-local-variable 'compile-command) "go build -v && go test && go vet")))))) ;;;; js (setq js-indent-level 2 js-enabled-frameworks '(javascript)) ;;;; typescript (setq typescript-indent-level 2) (autoload 'ansi-color-apply-on-region "ansi-color") (defun colorise-compilation-buffer () (ansi-color-apply-on-region compilation-filter-start (point-max))) (add-hook 'compilation-filter-hook #'colorise-compilation-buffer) ;;;; shell (general-add-hook 'sh-mode-hook (lambda () (general-add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p :append :local))) (add-to-list 'auto-mode-alist '("\\.env\\'" . conf-unix-mode)) (add-to-list 'auto-mode-alist '("\\.zsh\\'" . shell-script-mode)) (add-to-list 'auto-mode-alist '("zshenv\\'" . shell-script-mode)) (add-to-list 'auto-mode-alist '("zshrc\\'" . shell-script-mode)) (setq sh-shell-file "/usr/bin/env zsh" sh-basic-offset 2) (add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on) ;;;; make (general-add-hook 'makefile-mode-hook (lambda () (setq-local indent-tabs-mode t))) ;;;; nix (setq nix-indent-function #'nix-indent-line) (use-package nix-update :commands (nix-update-fetch)) ;;;; gitlab-ci.yml (with-eval-after-load 'git-gutter-fringe (fringe-helper-define 'flycheck-fringe-bitmap-double-arrow '(center repeated) "XXX.....")) (setq gitlab-ci-url "https://gitlab.satoshipay.tech") (use-package gitlab-ci-mode-flycheck :ghook ('gitlab-ci-mode-hook (list #'gitlab-ci-mode-flycheck-enable #'flycheck-mode))) ;;;; *ignore (use-package gitignore-mode :mode ((".dockerignore\\'" . gitignore-mode))) ;;;; kubernetes (setq k8s-site-docs-version "v1.13") (use-package kubel :defer t) (use-package kubel-evil :ghook 'kubel-mode-hook) ;;;; ledger (use-package ledger-mode :gfhook '(ledger-flymake-enable ws-butler-mode) :defer t :config (progn (setq ledger-reconcile-default-commodity "€" ledger-narrow-on-reconcile t ledger-clear-whole-transactions t ledger-reports `(("Monthly Expenses" "ledger -f %(ledger-file) reg -M \\^Expenses --real -X EUR -l \"payee != 'Opening Balances'\"") ("Total Expenses:This Month" "ledger -f %(ledger-file) bal \\^Expenses -p \"this month\"") ("Total Expenses:Past 90 Days" ,(concat "ledger -f %(ledger-file) balance ^Expenses -b " (format-time-string "%Y-%m-%d" (time-add (current-time) (days-to-time -90))))) ("Total Expenses:Past 180 Days" ,(concat "ledger -f %(ledger-file) balance ^Expenses -b " (format-time-string "%Y-%m-%d" (time-add (current-time) (days-to-time -180))))) ("Expenses:This Month" "ledger -f %(ledger-file) register \\^Expenses -p \"this month\"") ("Expenses:Past 90 Days (monthly)" ,(concat "ledger -f %(ledger-file) register --monthly ^Expenses -b " (format-time-string "%Y-%m-%d" (time-add (current-time) (days-to-time -90))))) ("Expenses:Past 180 Days (monthly)" ,(concat "ledger -f %(ledger-file) register --monthly ^Expenses -b " (format-time-string "%Y-%m-%d" (time-add (current-time) (days-to-time -180))))) ("All Account Balances" "ledger -f %(ledger-file) bal --current -R \\^Assets \\^Liabilities"))))) (use-package evil-ledger :after ledger-mode :ghook '(ledger-mode-hook)) ;;;; org (setq org-ellipsis "…" org-directory "~/Documents/org") (use-package org-journal :after org :commands (org-journal-new-date-entry org-journal-new-entry org-journal-new-scheduled-entry) :gfhook (#'variable-pitch-mode) :config (setq org-journal-date-format "%A, %d %B %Y" org-journal-dir "~/Documents/journal")) ;;;; web modes (tsx, html) (use-package css-mode :defer t :config (progn (setq css-indent-offset 2))) (use-package web-mode :mode (("\\.tsx\\'" . web-mode) ("\\.html?\\'" . web-mode)) :config (setq web-mode-enable-auto-pairing nil web-mode-code-indent-offset 2 web-mode-markup-indent-offset 2 web-mode-css-indent-offset 2 web-mode-style-padding 0 web-mode-script-padding 0)) (use-package emmet-mode :ghook '(web-mode-hook sgml-mode-hook)) ;;; IDE features (fringe-helper-define 'left-vertical-bar '(center repeated) "XXX.....") (use-package flymake :defer 5 :config (setq flymake-error-bitmap '(left-vertical-bar compilation-error) flymake-warning-bitmap '(left-vertical-bar compilation-warning))) (use-package flycheck :defer 5 :ghook ('(typescript-mode-hook dockerfile-mode-hook yaml-mode-hook js-mode-hook css-mode-hook scss-mode-hook html-mode-hook haskell-mode-hook)) :config (progn (setq flycheck-check-syntax-automatically '(save idle-buffer-switch mode-enabled) flycheck-highlighting-mode 'sexps) (flycheck-define-error-level 'error :severity 100 :compilation-level 2 :overlay-category 'flycheck-error-overlay :fringe-bitmap 'left-vertical-bar :fringe-face 'flycheck-fringe-error :error-list-face 'flycheck-error-list-error) (flycheck-define-error-level 'warning :severity 10 :compilation-level 1 :overlay-category 'flycheck-warning-overlay :fringe-bitmap 'left-vertical-bar :fringe-face 'flycheck-fringe-warning :warning-list-face 'flycheck-error-list-warning) (flycheck-define-error-level 'info :severity -10 :compilation-level 0 :overlay-category 'flycheck-info-overlay :fringe-bitmap 'left-vertical-bar :fringe-face 'flycheck-fringe-info :info-list-face 'flycheck-error-list-info))) (use-package treemacs :defer t :config (progn (setq treemacs-no-png-images t))) (use-package lsp-mode :defer 2 :general (:states 'normal :keymaps 'lsp-mode-map "gd" #'xref-find-definitions "gr" #'xref-find-references "C-t" #'xref-pop-marker-stack) :ghook ('(typescript-mode-hook dockerfile-mode-hook yaml-mode-hook js-mode-hook css-mode-hook go-mode-hook scss-mode-hook html-mode-hook haskell-mode-hook) #'lsp-deferred) :config (progn (require 'lsp-clients) (setq lsp-auto-guess-root t lsp-auto-configure nil lsp-idle-delay 0.5 lsp-enable-symbol-highlighting nil) (add-to-list 'lsp-language-id-configuration '(js-mode . "javascript")))) (use-package lsp-ui :after lsp-mode :ghook ('lsp-mode-hook) :general (:states 'normal :keymaps 'lsp-ui-mode-map "gd" #'lsp-ui-peek-find-definitions "gr" #'lsp-ui-peek-find-references "C-t" #'lsp-ui-peek-jump-backward) :config (progn (setq lsp-enable-snippet nil lsp-ui-sideline-show-code-actions nil lsp-ui-sideline-enable t lsp-ui-doc-enable nil))) (use-package lsp-ivy :after (lsp ivy)) (use-package lsp-haskell :after lsp-mode) ;; Inside a javascript project, it's common to install tools locally to ;; the project. This will allows emacs to find their executables. (use-package add-node-modules-path :config (setq add-node-modules-max-depth 6) :ghook ('(js2-mode-hook typescript-mode-hook) #'add-node-modules-path)) (use-package tide :after (typescript-mode company flycheck) :ghook ('typescript-mode-hook #'tide-setup) :config (progn ;; loading this package has the annoying effect of breaking my company configuration ;; upstream fix: https://github.com/ananthakumaran/tide/pull/384 (when (eq (car company-backends) 'company-tide) (setq company-backends (remq 'company-tide company-backends))))) ;;;; Reformat on save (use-package prettier-js :ghook ('(javascript-mode-hook typescript-mode-hook) #'prettier-js-mode t) :config (progn (setq prettier-js-show-errors 'echo) (if-let ((prettier_d (executable-find "prettier_d"))) (setq prettier-js-command prettier_d prettier-js-args '("--pkg-conf" "--parser" "typescript")) (message "prettier_d is not available")))) ;;; E-mail (declare-function sendmail-send-it "sendmail") (setq send-mail-function #'sendmail-send-it) (use-package mu4e :if (executable-find "mu") :commands (mu4e) :defines (mu4e-contexts) :general (:keymaps 'mu4e-headers-mode-map :states 'normal "d" #'mu4e-headers-mark-for-trash "T" #'mu4e-headers-mark-thread) (:keymaps 'mu4e-view-mode-map :states 'normal "d" #'mu4e-view-mark-for-trash) :init (progn (with-eval-after-load 'evil-ex (evil-ex-define-cmd "mu[4e]" #'mu4e))) :config (progn (setq mail-user-agent #'mu4e-user-agent mu4e-completing-read-function #'ivy-completing-read mu4e-maildir "~/mail" mu4e-context-policy 'pick-first mu4e-update-interval 600 mu4e-change-filenames-when-moving t mu4e-index-lazy-check t mu4e-hide-index-messages t mu4e-compose-format-flowed t mu4e-contexts (list (make-mu4e-context :name "SatoshiPay" :match-func (lambda (msg) (if msg (mu4e-message-contact-field-matches msg :to ".*@satoshipay.io") (string-equal (system-name) "satoshipad"))) :vars '((user-mail-address . "alan@satoshipay.io") (mu4e-sent-messages-behavior . delete) (mu4e-drafts-folder . "/satoshipay/[Gmail]/Drafts") (mu4e-sent-folder . "/satoshipay/[Gmail]/Sent Mail") (mu4e-refile-folder . "/satoshipay/[Gmail]/All Mail") (mu4e-trash-folder . "/satoshipay/[Gmail]/Bin") (mu4e-maildir-shortcuts . (("/satoshipay/INBOX" . ?i) ("/satoshipay/[Gmail]/All Mail" . ?a) ("/satoshipay/[Gmail]/Sent Mail" . ?s) ("/satoshipay/[Gmail]/Spam" . ?p) ("/satoshipay/[Gmail]/Spam" . ?j))))))))) ;;; Take me to my leader (my-leader-def "" nil "`" #'eshell-toggle "h" '(:keymap ehelp-map :package ehelp) "w" '(:keymap evil-window-map :package evil) "x" '(:keymap ctl-x-map) "c" (general-simulate-key "C-c") "l" '(:keymap lsp-command-map :package lsp-mode) "j" #'lsp-ivy-workspace-symbol "q" #'evil-delete-buffer "p" '(:keymap projectile-command-map :package projectile) "v" #'split-window-right "o" #'other-window "u" #'universal-argument ";" #'counsel-M-x "bb" #'counsel-switch-buffer "bx" #'kill-this-buffer "br" #'revert-buffer "bk" #'kill-buffer "dd" #'dired "fs" #'save-buffer "ff" #'find-file "fw" #'write-file "fd" #'delete-file "fr" #'crux-rename-file-and-buffer "gs" #'magit-status "gm" #'git-messenger:popup-message "gg" #'magit-dispatch "gn" #'git-gutter:next-hunk "gp" #'git-gutter:previous-hunk "gi" #'git-gutter:popup-hunk "gs" #'git-gutter:stage-hunk "go" #'git-gutter:revert-hunk "gt" #'git-timemachine "bi" #'ibuffer "bz" #'bury-buffer "iu" #'counsel-unicode-char) (load (expand-file-name "mail.el" user-emacs-directory) :noerror) ;; # Local Variables: ;; # flycheck-disabled-checkers: 'emacs-lisp-checkdoc ;; # End: