From 40fd4964068d0b7628b6f699dab4aec200eadb0a Mon Sep 17 00:00:00 2001 From: Alan Pearce Date: Tue, 8 Oct 2019 21:40:33 +0200 Subject: Emacs: use single configuration file, compiled by home-manager --- user/emacs/.emacs.d/init.el | 848 +++++++++++++++++++++++++++++++++++++++++++- user/emacs/.emacs.d/main.el | 839 ------------------------------------------- user/modules/emacs.nix | 8 +- 3 files changed, 837 insertions(+), 858 deletions(-) delete mode 100644 user/emacs/.emacs.d/main.el diff --git a/user/emacs/.emacs.d/init.el b/user/emacs/.emacs.d/init.el index 48fc30a3..d4470242 100644 --- a/user/emacs/.emacs.d/init.el +++ b/user/emacs/.emacs.d/init.el @@ -1,26 +1,842 @@ -;;; init --- user init file -*- no-byte-compile: t -*- -;;; Commentary: -;; Entry point for Emacs init. -;; Ensures that main init code is up-to-date by loading the newest version. -;; -;;; Code: +;;; init --- user init file (setq inhibit-startup-echo-area-message "alan") -(setq load-prefer-newer t - package-user-dir (concat "~/.emacs.d/packages/" emacs-version "/elpa") - package-enable-at-startup nil - package-archives nil) +(setq inhibit-startup-screen t + initial-scratch-message "" + initial-major-mode 'text-mode + package-enable-at-startup nil) (package-initialize) -(require 'auto-compile nil :noerror) (defun reload-user-init-file () "Reload init file." (interactive) (load-file user-init-file)) -(when (featurep 'auto-compile) - (auto-compile-on-load-mode)) +(eval-when-compile + (require 'use-package) + (setq use-package-expand-minimally t)) +(setq use-package-always-demand (daemonp)) -(let ((gc-cons-threshold most-positive-fixnum)) - (load (expand-file-name "main.el" user-emacs-directory) :nomessage t)) -;;; init ends here +;;; Customize + +(setq custom-file "~/.emacs.d/custom.el") +(load custom-file :noerror :nomessage) + +(use-package crux + :defer 1 + :custom ((crux-reopen-as-root-mode nil))) + +;;; Styles + +(custom-set-variables + ;; I prefer an always-visible cursor. Feels less distracting. + '(blink-cursor-mode nil) + ;; Disable all the bars, unless on OSX, in which case, keep the menu bar. + '(menu-bar-mode nil) + '(scroll-bar-mode nil) + '(tool-bar-mode nil)) +(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) + (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))) + (let ((line (face-attribute 'mode-line :underline))) + (set-face-attribute 'mode-line nil :overline line) + (set-face-attribute 'mode-line-inactive nil :overline line) + (set-face-attribute 'mode-line-inactive nil :underline line) + (set-face-attribute 'mode-line nil :box nil) + (set-face-attribute 'mode-line-inactive nil :box nil)) + +;;; Chrome +(use-package minions + :custom ((minions-mode-line-lighter "#") + (minions-mode-line-delimiters nil) + (minions-mode t))) + +(setq-default mode-line-position nil + mode-line-mule-info nil + mode-line-client nil + mode-line-remote nil) + +(use-package moody + :config (progn + (setq x-underline-at-descent-line t) + (moody-replace-mode-line-buffer-identification) + (moody-replace-vc-mode) + (with-eval-after-load 'eyebrowse + (defvar eyebrowse-lighter-default + '(:eval (eyebrowse-mode-line-indicator))) + (defvar moody-replace-eyebrowse-lighter + '(:eval (moody-tab (eyebrowse-mode-line-indicator) 1 'up))) + (defun moody-replace-eyebrowse (&optional reverse) + (interactive "P") + (if (assoc 'eyebrowse-mode mode-line-misc-info) + (setcdr (assoc 'eyebrowse-mode mode-line-misc-info) + (list (if reverse + eyebrowse-lighter-default + moody-replace-eyebrowse-lighter))) + (push (list 'eyebrowse-mode moody-replace-eyebrowse-lighter) + (cdr (last mode-line-misc-info))))) + (moody-replace-eyebrowse nil)))) + +(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 + +(custom-set-variables + '(calendar-week-start-day 1) + '(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 + +;; I think =set-keyboard-coding-system= stops OS X from doing something +;; annoying to add accents. The modifier setup is to match my +;; re-arrangement of modifiers on OSX: Cmd on the outside, then +;; Option/alt, then Control. + +(when (eq system-type 'darwin) + (custom-set-variables + '(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 + :custom ((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 + :custom ((which-key-mode +1)) + :config (progn + (which-key-setup-side-window-right-bottom))) + +;;; Modeline + +(use-package relative-buffers + :defer 2 + :custom ((global-relative-buffers-mode t))) + +;;; Minibuffer + +(setq enable-recursive-minibuffers t) +(minibuffer-depth-indicate-mode t) + +(use-package hydra + :defer 2) +(use-package ivy + :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 smerge-mode + (unpackaged/smerge-hydra/body))))) + +(use-package swiper + :general ([remap isearch-forward] #'swiper-isearch)) + +;; transition smex history to amx +(let ((smex-save-file (concat user-emacs-directory "smex-items"))) + (use-package amx + :custom ((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 nil + split-width-threshold 160) + +(use-package eyebrowse + :after (evil) + :custom ((eyebrowse-new-workspace t) + (eyebrowse-mode t) + (eyebrowse-mode-line-left-delimiter "") + (eyebrowse-mode-line-right-delimiter "") + (eyebrowse-mode-line-separator " ") + (eyebrowse-mode-line-style 'always)) + :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 + :custom ((winner-mode t) + (winner-boring-buffers '("*Completions*" "*Help*" "*Apropos*" "*Buffer List*" "*info*" "*Compile-Log*"))) + :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) + :init (progn + (defvar evil-want-integration) + (defvar evil-want-keybinding) + (setq evil-want-integration t + evil-want-keybinding nil)) + :custom ((evil-shift-width 2) + (evil-mode-line-format nil)) + :config (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-collection + :after (evil) + :defer 3 + :demand t + :commands (evil-collection-init) + :custom ((evil-collection-company-use-tng nil)) + :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 + :custom ((evil-space-mode t))) + +(use-package evil-surround + :after evil + :defer 2 + :custom ((global-evil-surround-mode t))) + +(use-package evil-commentary + :after evil + :defer 2 + :custom ((evil-commentary-mode t))) + +(use-package evil-magit + :after magit + :custom ((evil-magit-use-y-for-yank nil))) + +(use-package evil-quickscope + :after evil + :commands (evil-quickscope-mode) + :ghook ('(magit-mode-hook git-rebase-mode-hook) #'turn-off-evil-quickscope-mode) + :custom ((global-evil-quickscope-mode t))) + +(use-package evil-org + :after org + :commands (evil-org-set-key-theme) + :ghook ('org-mode-hook #'evil-org-mode) + :gfhook #'evil-org-set-key-theme) + +(use-package evil-org-agenda + :after org + :ghook ('org-agenda-mode-hook #'evil-org-agenda-set-keys)) + +;;; Projects + +(use-package projectile + :defer 1 + :defines projectile-command-map + :custom ((projectile-mode +1) + (projectile-completion-system 'ivy)) + :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-project-root-files-functions '(projectile-root-local + projectile-root-top-down + projectile-root-bottom-up + projectile-root-top-down-recurring)) + (with-eval-after-load 'evil-ex + (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) + :custom ((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)) + :config (progn + (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 + :defer t) +(use-package git-gutter-fringe + :defer 5 + :config (progn + (global-git-gutter-mode 1) + ;; 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))) + +(use-package git-messenger + :commands (git-messenger:popup-message) + :defer 10 + :custom ((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) + :custom ((global-company-mode +1) + (company-idle-delay 0) + (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 '(?\ ?\( ?\) ?.))) + :general (:states 'insert + "TAB" #'company-indent-or-complete-common)) + +;; (use-package all-the-icons) + +(eval-when-compile (require 'subr-x)) +(eval-and-compile + (defun company-tabnine-load-path () + (string-trim-right (shell-command-to-string "ghq list -p company-tabnine")))) + +(use-package company-tabnine + :commands (company-tabnine) + :after (company) + :load-path (lambda () (list (company-tabnine-load-path))) + :custom ((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 + :custom ((global-eldoc-mode +1) + (eldoc-idle-delay 0.5))) + +(use-package eldoc-box + :after (eldoc eglot) + :custom ((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 + :custom ((global-auto-revert-mode t) + (auto-revert-verbose 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 + +(custom-set-variables + '(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))) + :custom ((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) + :custom ((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) + :custom ((fish-completion-fallback-on-bash-p t)) + :commands (global-fish-completion-mode) + :config (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-always-indent 'complete) + +(use-package ws-butler + :ghook ('prog-mode-hook)) + +;;; Major modes + +;;;; js +(custom-set-variables '(js-indent-level 2) + '(js-enabled-frameworks '(javascript))) + +;;;; typescript +(custom-set-variables '(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)) +(use-package sh-script + :mode (("\\.zsh\\'" . shell-script-mode) + ("zshenv\\'" . shell-script-mode) + ("zshrc\\'" . shell-script-mode)) + :config (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 +(custom-set-variables '(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.....")) + +(custom-set-variables '(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 +(custom-set-variables '(k8s-site-docs-version "v1.13")) + +;;;; beancount + +(use-package beancount + :load-path "~/projects/bitbucket.org/blais/beancount/editors/emacs") + +;;;; org + +(custom-set-variables '(org-ellipsis "…") + `(org-directory "~/Documents/org")) + +(use-package org-journal + :commands (org-journal-new-date-entry + org-journal-new-entry + org-journal-new-scheduled-entry) + :gfhook (#'variable-pitch-mode) + :custom ((org-journal-date-format "%A, %d %B %Y") + (org-journal-dir "~/Documents/journal"))) + +;;;; web modes (tsx, html) + +(use-package web-mode + :mode (("\\.tsx" . web-mode)) + :custom ((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))) + +;;; IDE features + +(fringe-helper-define 'left-vertical-bar '(center repeated) + "XXX.....") +(use-package flymake + :custom ((flymake-error-bitmap '(left-vertical-bar compilation-error)) + (flymake-warning-bitmap '(left-vertical-bar compilation-warning)))) +(use-package flymake-diagnostic-at-point + :custom ((flymake-diagnostic-at-point-diagnostic-function #'flymake-diagnostic-at-point-display-minibuffer)) + :ghook '(flymake-mode-hook)) + +(use-package lsp-mode + :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) + #'lsp) + :functions (lsp--flymake-setup) + :gfhook 'lsp--flymake-setup + :custom ((lsp-auto-guess-root t) + (lsp-auto-configure nil) + (lsp-prefer-flymake t) + (lsp-enable-symbol-highlighting nil)) + :config (progn + (add-to-list 'lsp-language-id-configuration '(js-mode . "javascript")))) + +(use-package lsp-clients + :after (lsp-mode)) + +(use-package lsp-ui + :after lsp-mode + :ghook ('lsp-mode-hook) + :custom ((lsp-ui-sideline-enable nil) + (lsp-ui-doc-mode nil) + (lsp-enable-snippet nil))) + +(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 + :ghook ('(js2-mode-hook typescript-mode-hook) #'add-node-modules-path)) + +;;;; Reformat on save + +(use-package prettier-js + :custom ((prettier-js-show-errors 'echo)) + :ghook ('(typescript-mode-hook) #'prettier-js-mode t) + :config (progn + (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) + :init (setq mail-user-agent #'mu4e-user-agent) + :custom ((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)) + :init (progn + (with-eval-after-load 'evil-ex + (evil-ex-define-cmd "mu[4e]" #'mu4e))) + :config (progn + (setq 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/Drafts") + (mu4e-sent-folder . "/satoshipay/Sent Mail") + (mu4e-refile-folder . "/satoshipay/All Mail") + (mu4e-trash-folder . "/satoshipay/Bin") + (mu4e-maildir-shortcuts . (("/satoshipay/INBOX" . ?i) + ("/satoshipay/All Mail" . ?a) + ("/satoshipay/Sent Mail" . ?s) + ("/satoshipay/Spam" . ?p))))))))) + +;;; 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) + "q" #'evil-delete-buffer + "p" projectile-command-map + "v" #'split-window-right + "o" #'other-window + "u" #'universal-argument + ";" #'counsel-M-x + "bb" #'ivy-switch-buffer + "bx" #'kill-this-buffer + "br" #'revert-buffer + "bk" #'kill-buffer + "dd" #'dired + "fs" #'save-buffer + "ff" #'find-file + "fw" #'write-file + "fd" #'crux-delete-file-and-buffer + "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) + +;; # Local Variables: +;; # flycheck-disabled-checkers: 'emacs-lisp-checkdoc +;; # End: diff --git a/user/emacs/.emacs.d/main.el b/user/emacs/.emacs.d/main.el deleted file mode 100644 index 4a30df6a..00000000 --- a/user/emacs/.emacs.d/main.el +++ /dev/null @@ -1,839 +0,0 @@ -(setq inhibit-startup-screen t - initial-scratch-message "" - initial-major-mode 'text-mode - package-enable-at-startup nil) - -(eval-when-compile - (require 'use-package) - (setq use-package-expand-minimally t)) -(setq use-package-always-demand (daemonp)) - -;;; Customize - -(setq custom-file "~/.emacs.d/custom.el") -(load custom-file :noerror :nomessage) - -(use-package crux - :defer 1 - :custom ((crux-reopen-as-root-mode nil))) - -;;; Styles - -(custom-set-variables - ;; I prefer an always-visible cursor. Feels less distracting. - '(blink-cursor-mode nil) - ;; Disable all the bars, unless on OSX, in which case, keep the menu bar. - '(menu-bar-mode nil) - '(scroll-bar-mode nil) - '(tool-bar-mode nil)) -(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) - (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))) - (let ((line (face-attribute 'mode-line :underline))) - (set-face-attribute 'mode-line nil :overline line) - (set-face-attribute 'mode-line-inactive nil :overline line) - (set-face-attribute 'mode-line-inactive nil :underline line) - (set-face-attribute 'mode-line nil :box nil) - (set-face-attribute 'mode-line-inactive nil :box nil)) - -;;; Chrome -(use-package minions - :custom ((minions-mode-line-lighter "#") - (minions-mode-line-delimiters nil) - (minions-mode t))) - -(setq-default mode-line-position nil - mode-line-mule-info nil - mode-line-client nil - mode-line-remote nil) - -(use-package moody - :config (progn - (setq x-underline-at-descent-line t) - (moody-replace-mode-line-buffer-identification) - (moody-replace-vc-mode) - (with-eval-after-load 'eyebrowse - (defvar eyebrowse-lighter-default - '(:eval (eyebrowse-mode-line-indicator))) - (defvar moody-replace-eyebrowse-lighter - '(:eval (moody-tab (eyebrowse-mode-line-indicator) 1 'up))) - (defun moody-replace-eyebrowse (&optional reverse) - (interactive "P") - (if (assoc 'eyebrowse-mode mode-line-misc-info) - (setcdr (assoc 'eyebrowse-mode mode-line-misc-info) - (list (if reverse - eyebrowse-lighter-default - moody-replace-eyebrowse-lighter))) - (push (list 'eyebrowse-mode moody-replace-eyebrowse-lighter) - (cdr (last mode-line-misc-info))))) - (moody-replace-eyebrowse nil)))) - -(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 - -(custom-set-variables - '(calendar-week-start-day 1) - '(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 - -;; I think =set-keyboard-coding-system= stops OS X from doing something -;; annoying to add accents. The modifier setup is to match my -;; re-arrangement of modifiers on OSX: Cmd on the outside, then -;; Option/alt, then Control. - -(when (eq system-type 'darwin) - (custom-set-variables - '(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 - :custom ((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 - :custom ((which-key-mode +1)) - :config (progn - (which-key-setup-side-window-right-bottom))) - -;;; Modeline - -(use-package relative-buffers - :defer 2 - :custom ((global-relative-buffers-mode t))) - -;;; Minibuffer - -(setq enable-recursive-minibuffers t) -(minibuffer-depth-indicate-mode t) - -(use-package hydra - :defer 2) -(use-package ivy - :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 smerge-mode - (unpackaged/smerge-hydra/body))))) - -(use-package swiper - :general ([remap isearch-forward] #'swiper-isearch)) - -;; transition smex history to amx -(let ((smex-save-file (concat user-emacs-directory "smex-items"))) - (use-package amx - :custom ((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 nil - split-width-threshold 160) - -(use-package eyebrowse - :after (evil) - :custom ((eyebrowse-new-workspace t) - (eyebrowse-mode t) - (eyebrowse-mode-line-left-delimiter "") - (eyebrowse-mode-line-right-delimiter "") - (eyebrowse-mode-line-separator " ") - (eyebrowse-mode-line-style 'always)) - :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 - :custom ((winner-mode t) - (winner-boring-buffers '("*Completions*" "*Help*" "*Apropos*" "*Buffer List*" "*info*" "*Compile-Log*"))) - :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) - :init (progn - (defvar evil-want-integration) - (defvar evil-want-keybinding) - (setq evil-want-integration t - evil-want-keybinding nil)) - :custom ((evil-shift-width 2) - (evil-mode-line-format nil)) - :config (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-collection - :after (evil) - :defer 3 - :demand t - :commands (evil-collection-init) - :custom ((evil-collection-company-use-tng nil)) - :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 - :custom ((evil-space-mode t))) - -(use-package evil-surround - :after evil - :defer 2 - :custom ((global-evil-surround-mode t))) - -(use-package evil-commentary - :after evil - :defer 2 - :custom ((evil-commentary-mode t))) - -(use-package evil-magit - :after magit - :custom ((evil-magit-use-y-for-yank nil))) - -(use-package evil-quickscope - :after evil - :commands (evil-quickscope-mode) - :ghook ('(magit-mode-hook git-rebase-mode-hook) #'turn-off-evil-quickscope-mode) - :custom ((global-evil-quickscope-mode t))) - -(use-package evil-org - :after org - :commands (evil-org-set-key-theme) - :ghook ('org-mode-hook #'evil-org-mode) - :gfhook #'evil-org-set-key-theme) - -(use-package evil-org-agenda - :after org - :ghook ('org-agenda-mode-hook #'evil-org-agenda-set-keys)) - -;;; Projects - -(use-package projectile - :defer 1 - :defines projectile-command-map - :custom ((projectile-mode +1) - (projectile-completion-system 'ivy)) - :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-project-root-files-functions '(projectile-root-local - projectile-root-top-down - projectile-root-bottom-up - projectile-root-top-down-recurring)) - (with-eval-after-load 'evil-ex - (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) - :custom ((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)) - :config (progn - (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 - :defer t) -(use-package git-gutter-fringe - :defer 5 - :config (progn - (global-git-gutter-mode 1) - ;; 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))) - -(use-package git-messenger - :commands (git-messenger:popup-message) - :defer 10 - :custom ((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) - :custom ((global-company-mode +1) - (company-idle-delay 0) - (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 '(?\ ?\( ?\) ?.))) - :general (:states 'insert - "TAB" #'company-indent-or-complete-common)) - -;; (use-package all-the-icons) - -(eval-when-compile (require 'subr-x)) -(eval-and-compile - (defun company-tabnine-load-path () - (string-trim-right (shell-command-to-string "ghq list -p company-tabnine")))) - -(use-package company-tabnine - :commands (company-tabnine) - :after (company) - :load-path (lambda () (list (company-tabnine-load-path))) - :custom ((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 - :custom ((global-eldoc-mode +1) - (eldoc-idle-delay 0.5))) - -(use-package eldoc-box - :after (eldoc eglot) - :custom ((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 - :custom ((global-auto-revert-mode t) - (auto-revert-verbose 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 - -(custom-set-variables - '(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))) - :custom ((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) - :custom ((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) - :custom ((fish-completion-fallback-on-bash-p t)) - :commands (global-fish-completion-mode) - :config (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-always-indent 'complete) - -(use-package ws-butler - :ghook ('prog-mode-hook)) - -;;; Major modes - -;;;; js -(custom-set-variables '(js-indent-level 2) - '(js-enabled-frameworks '(javascript))) - -;;;; typescript -(custom-set-variables '(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)) -(use-package sh-script - :mode (("\\.zsh\\'" . shell-script-mode) - ("zshenv\\'" . shell-script-mode) - ("zshrc\\'" . shell-script-mode)) - :config (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 -(custom-set-variables '(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.....")) - -(custom-set-variables '(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 -(custom-set-variables '(k8s-site-docs-version "v1.13")) - -;;;; beancount - -(use-package beancount - :load-path "~/projects/bitbucket.org/blais/beancount/editors/emacs") - -;;;; org - -(custom-set-variables '(org-ellipsis "…") - `(org-directory "~/Documents/org")) - -(use-package org-journal - :commands (org-journal-new-date-entry - org-journal-new-entry - org-journal-new-scheduled-entry) - :gfhook (#'variable-pitch-mode) - :custom ((org-journal-date-format "%A, %d %B %Y") - (org-journal-dir "~/Documents/journal"))) - -;;;; emacs-lisp - -(use-package auto-async-byte-compile - :custom ((auto-async-byte-compile-exclude-files-regexp "custom\\.el")) - :ghook ('emacs-lisp-mode-hook #'enable-auto-async-byte-compile-mode)) - -;;;; web modes (tsx, html) - -(use-package web-mode - :mode (("\\.tsx" . web-mode)) - :custom ((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))) - -;;; IDE features - -(fringe-helper-define 'left-vertical-bar '(center repeated) - "XXX.....") -(use-package flymake - :custom ((flymake-error-bitmap '(left-vertical-bar compilation-error)) - (flymake-warning-bitmap '(left-vertical-bar compilation-warning)))) -(use-package flymake-diagnostic-at-point - :custom ((flymake-diagnostic-at-point-diagnostic-function #'flymake-diagnostic-at-point-display-minibuffer)) - :ghook '(flymake-mode-hook)) - -(use-package lsp-mode - :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) - #'lsp) - :functions (lsp--flymake-setup) - :gfhook 'lsp--flymake-setup - :custom ((lsp-auto-guess-root t) - (lsp-auto-configure nil) - (lsp-prefer-flymake t) - (lsp-enable-symbol-highlighting nil)) - :config (progn - (add-to-list 'lsp-language-id-configuration '(js-mode . "javascript")))) - -(use-package lsp-clients - :after (lsp-mode)) - -(use-package lsp-ui - :after lsp-mode - :ghook ('lsp-mode-hook) - :custom ((lsp-ui-sideline-enable nil) - (lsp-ui-doc-mode nil) - (lsp-enable-snippet nil))) - -(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 - :ghook ('(js2-mode-hook typescript-mode-hook) #'add-node-modules-path)) - -;;;; Reformat on save - -(use-package prettier-js - :custom ((prettier-js-show-errors 'echo)) - :ghook ('(typescript-mode-hook) #'prettier-js-mode t) - :config (progn - (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) - :init (setq mail-user-agent #'mu4e-user-agent) - :custom ((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)) - :init (progn - (with-eval-after-load 'evil-ex - (evil-ex-define-cmd "mu[4e]" #'mu4e))) - :config (progn - (setq 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/Drafts") - (mu4e-sent-folder . "/satoshipay/Sent Mail") - (mu4e-refile-folder . "/satoshipay/All Mail") - (mu4e-trash-folder . "/satoshipay/Bin") - (mu4e-maildir-shortcuts . (("/satoshipay/INBOX" . ?i) - ("/satoshipay/All Mail" . ?a) - ("/satoshipay/Sent Mail" . ?s) - ("/satoshipay/Spam" . ?p))))))))) - -;;; 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) - "q" #'evil-delete-buffer - "p" projectile-command-map - "v" #'split-window-right - "o" #'other-window - "u" #'universal-argument - ";" #'counsel-M-x - "bb" #'ivy-switch-buffer - "bx" #'kill-this-buffer - "br" #'revert-buffer - "bk" #'kill-buffer - "dd" #'dired - "fs" #'save-buffer - "ff" #'find-file - "fw" #'write-file - "fd" #'crux-delete-file-and-buffer - "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) - -;; # Local Variables: -;; # flycheck-disabled-checkers: 'emacs-lisp-checkdoc -;; # End: diff --git a/user/modules/emacs.nix b/user/modules/emacs.nix index b6ac0395..9f542391 100644 --- a/user/modules/emacs.nix +++ b/user/modules/emacs.nix @@ -154,9 +154,11 @@ in home.sessionVariables = { EDITOR = "${editorScript}/bin/edit"; }; - home.file.".emacs.d/init.el".source = ../emacs/.emacs.d/init.el; - home.file.".emacs.d/main.el" = { - source = ../emacs/.emacs.d/main.el; + home.file.".emacs.d/init.el" = { + source = ../emacs/.emacs.d/init.el; + onChange = '' + ${config.programs.emacs.finalPackage}/bin/emacs -batch -f batch-byte-compile .emacs.d/init.el + ''; }; home.file.".emacs.d/eshell/" = { recursive = true; -- cgit 1.4.1