;;; External packages: -*- lexical-binding: t; -*- (use-package orderless ; ordering (minibuffer) completions :demand t :custom (orderless-skip-highlighting t) (completion-styles '(orderless basic partial-completion emacs22)) (completion-category-defaults nil) (completion-category-overrides nil) (completion-ignore-case t) (read-file-name-completion-ignore-case t) (read-buffer-completion-ignore-case t) (orderless-smart-case nil) (orderless-matching-styles '(orderless-prefixes orderless-literal orderless-regexp))) (use-package vertico ; better minibuffer complete :demand t :custom (vertico-cycle t) :config (vertico-mode 1) (vertico-flat-mode) :bind (:map minibuffer-local-map ("M-v" . 'vertico-flat-mode))) (use-package marginalia ; more info in minibuffer menus :demand t :custom (marginalia-max-relative-age 0) (marginalia-align 'right) :bind (:map minibuffer-local-map ("M-A" . 'marginalia-cycle)) :config (marginalia-mode)) (use-package embark ; more actions from minibuffer :demand t :bind (("C-." . embark-act) ("C-," . embark-dwim) ("C-h B" . embark-bindings)) :config ;; Hide the mode line of the Embark live/completions buffers (add-to-list 'display-buffer-alist '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" nil (window-parameters (mode-line-format . none))))) (use-package corfu ; in buffer completion :demand t :custom (corfu-cycle t) (corfu-quit-no-match t) :bind (("M-/" . completion-at-point)) :init (defun my/corfu-commit-single () "Complete without asking if there is only one candidate." (when (and (corfu--popup-visible-p) (= (length corfu--candidates) 1)) (corfu-accept))) :hook (corfu-post-command . my/corfu-commit-single) :config (global-corfu-mode 1)) (use-package cape ; extend completion frameworks :demand t :after orderless corfu :bind ("C-c p" . cape-prefix-map) :config (advice-add 'pcomplete-completions-at-point :around 'cape-wrap-silent) (defvar my/completion-at-point-functions-always-include (list 'tags-completion-at-point-function 'cape-dabbrev 'tempel-complete)) (setq completion-at-point-functions my/completion-at-point-functions-always-include)) (use-package tempel ; templates :demand t :custom (tempel-path "~/.emacs.d/templates/*.eld") :bind (("M-+" . tempel-complete)) :config (keymap-set tempel-map " " #'tempel-next) (keymap-set tempel-map " " #'tempel-previous)) (use-package tempel-collection ; other people's templates :after tempel :demand t) (use-package ibuffer-vc ; group buffers by vcs directory :after ibuffer :demand t :hook (ibuffer . (lambda () (ibuffer-vc-set-filter-groups-by-vc-root) (unless (eq ibuffer-sorting-mode 'alphabetic) (ibuffer-do-sort-by-alphabetic))))) (use-package eldoc-box :after eldoc :demand t :custom (eldoc-box-clear-with-C-g t) :hook (eldoc-mode . eldoc-box-hover-mode)) (use-package free-keys ; display a list of unbound keys ) (use-package which-key ; show list of next keys after prefix & delay :demand t :config (which-key-mode 1)) (use-package winum ; binds for switching to windows by number :demand t :config (winum-mode 1)) ;; (use-package savehist ; preserve minibuffer history across sessions ;; :demand t ;; :init ;; (savehist-mode)) ;; (use-package consult ; more encompassing buffer switch and searching ;; :demand t ;; :custom ;; (consult-preview-excluded-buffers t) ;; (consult-narrow-key ",") ;; :bind ;; ("C-x b" . consult-buffer) ;; ("M-W" . consult-buffer) ;; ("C-S-y" . consult-yank-from-kill-ring) ;; ("M-g M-g" . consult-goto-line) ;; ("C-S-s" . consult-line-multi) ;; ("M-s g" . consult-grep) ;; ("M-s G" . grep) ;; ("M-s f" . consult-find) ;; ;; move some standard binds ;; ("M-s s" . consult-line)) ;; (use-package embark-consult ;; :after embark consult) (use-package projectile :config (projectile-mode 1) (define-key projectile-mode-map (kbd "C-x P") 'projectile-command-map)) (use-package hl-todo ; highlight certain keywords :hook (prog-mode . hl-todo-mode)) (use-package diff-hl :config (global-diff-hl-mode 1)) (use-package visible-mark ; make the mark visible :demand t :custom-face (visible-mark-active ((t . (:foreground "black" :background "deep pink" :box (:line-width (-1 . -1) :color "deep pink" :style nil))))) :custom (visible-mark-max 1) :config (global-visible-mark-mode 1)) (use-package avy ; goto location by char pair and jump list :bind (("M-G" . avy-goto-char-2)) :custom (avy-all-windows nil) (avy-all-windows-alt 'all-frames)) (use-package balanced-windows ; auto rebalance windows :bind ("C-x w b" . balanced-windows-mode)) (use-package eat ; terminal emu + make eshell behave better :demand t :custom (eat-enable-auto-line-mode t) :config (eat-eshell-mode) (eat-eshell-visual-command-mode) (let* ((desired-global-binds (my/keymap-keys my/keys-mode-map)) (desired-prefixes (mapcar (lambda (ks) (let ((k1 (elt ks 0)) (meta-mask ?\M-\0)) (if (numberp k1) (if (equal ?\e k1) (vector k1 (elt ks 1)) (let ((k-no-m (logand k1 (lognot meta-mask))) (k-has-m (not (zerop (logand k1 meta-mask))))) (if k-has-m (vector ?\e k-no-m) (vector k1)))) (vector k1)))) desired-global-binds))) (mapc (lambda (ks) (add-to-list 'eat-semi-char-non-bound-keys ks) (add-to-list 'eat-eshell-semi-char-non-bound-keys ks)) desired-prefixes) (eat-update-semi-char-mode-map) (eat-eshell-update-semi-char-mode-map))) (use-package bash-completion ; allow bash completion in eshell mostly :demand t :config (add-hook 'shell-dynamic-complete-functions 'bash-completion-dynamic-complete) :hook (eshell-mode . (lambda () (add-hook 'completion-at-point-functions 'bash-completion-capf-nonexclusive nil t)))) (use-package pinentry ; allow some passwords to be entered with emacs ) (use-package password-store ; gnu pass integration :demand t) (use-package auth-source-pass ; allow pass to act as auth within emacs :init (auth-source-pass-enable)) (use-package pass ; nice interface for gnu pass :demand t :after password-store auth-source-pass :custom (pass-suppress-confirmations t) (epg-pinentry-mode 'loopback) :config (add-to-list 'display-buffer-alist '("\\*Password-Store\\*" display-buffer-in-side-window (side . right)))) (use-package pyvenv ; respect python environments ) ;; (use-package sideline ; put warnings on the side of the same line ;; :init ;; (use-package sideline-flycheck) ;; (use-package sideline-flymake) ;; :custom ;; (sideline-backends-right '(sideline-flycheck sideline-flymake))) (use-package flycheck :config ;; flymake stuff to be less annoying ;; (face-spec-set 'flycheck-note '((t :underline nil))) ;; (face-spec-set 'flycheck-info '((t :underline nil))) ;; (face-spec-set 'flycheck-warning '((t :underline nil))) ;; (face-spec-set 'flycheck-error '((t :underline nil))) :custom (flycheck-check-syntax-automatically '(save mode-enabled)) ;; :hook ;; (prog-mode . flycheck-mode) ) ;; (progn ; collected folding binds, hs + fold this ;; (define-prefix-command 'my/fold-map) ;; (global-set-key (kbd "M-F") 'my/fold-map) ;; (define-keymap :full nil ;; :parent nil ;; :suppress nil ;; :keymap nil ;; :name "my/fold-map" ;; :prefix 'my/fold-map) ;; (progn ; hideshow folding ;; (keymap-set my/fold-map "t" 'hs-toggle-hiding) ;; (keymap-set my/fold-map "l" 'hs-hide-level) ;; (keymap-set my/fold-map "C-t" 'hs-hide-all) ;; (keymap-set my/fold-map "C-a" 'hs-show-all)) ;; (use-package fold-this ; fold arbitrary region ;; :init ;; (defun my/fold-this-fold-forward (&optional arg) ;; "Fold forward ARG number of sexps, defaulting to one." ;; (interactive "p") ;; (push-mark) ;; (forward-sexp arg) ;; (fold-this (mark) (point)) ;; (pop-mark)) ;; (defun my/fold-this-fold-backward (&optional arg) ;; "Fold backward ARG number of sexps, defaulting to one." ;; (interactive "p") ;; (push-mark) ;; (backward-sexp arg) ;; (fold-this (point) (mark)) ;; (pop-mark)) ;; :bind (:map my/fold-map ;; ("c" . fold-this) ;; ("e" . fold-this-unfold-at-point) ;; ("f" . my/fold-this-fold-forward) ;; ("b" . my/fold-this-fold-backward)))) (use-package clang-format ; let clang do c formatting ) (use-package rust-mode ; rust lang syntax ) (use-package mmm-mode :after haskell-mode :custom (mmm-submode-decoration-level 0) :hook ('haskell-literate-mode . 'my/mmm-mode) (haskell-literate-mode . 'mmm-ify-by-class) :init (defun my/mmm-mode () ;; go into mmm minor mode when class is given (make-local-variable 'mmm-global-mode) (setq mmm-global-mode 'true)) (mmm-add-classes '((literate-haskell-bird :submode text-mode :front "^[^>]" :include-front true :back "^>\\|$" ) (literate-haskell-latex :submode literate-haskell-mode :front "^\\\\begin{code}" :front-offset (end-of-line 1) :back "^\\\\end{code}" :include-back nil :back-offset (beginning-of-line -1) )))) (use-package haskell-mode ; haskell + cabal integrations :custom (haskell-tags-on-save t) (haskell-process-type 'cabal-repl) (haskell-process-auto-import-loaded-modules t) :hook (haskell-mode . interactive-haskell-mode) :config (add-to-list 'compilation-error-regexp-alist-alist (cons 'microhs (list "^mhs:.*error:\\s-*\"\\(.*\\)\":\\s-*line \\([0-9]*\\), col \\([0-9]*\\)" 1 2 3 2))) (add-to-list 'compilation-error-regexp-alist 'microhs)) (use-package opam-switch-mode ; make emacs mode respect switch :config (when (and (file-exists-p "~/.opam") (executable-find "opam")) (opam-switch-set-switch "default"))) (use-package tuareg ; ocaml mode :after opam-switch-mode) (use-package ocp-indent ; indentation for ocaml :after tuareg :hook (tuareg-mode . ocp-setup-indent)) (use-package merlin ; ocaml completion :after tuareg :hook (tuareg-mode . merlin-mode) :custom (merlin-command 'opam)) (use-package racket-mode ; basic racket integration ) (use-package sdcv ; dictionary, requires sdcv install :demand t :config (define-prefix-command 'dict-map) (define-keymap :full nil :parent nil :suppress nil :keymap nil :name "dict-map" :prefix 'dict-map (kbd "w") 'sdcv-search-input (kbd "c") (lambda () (interactive) (activate-input-method 'pyim) (sdcv-search-input (read-from-minibuffer "Chinese Word: " nil nil nil nil nil t)) (activate-input-method nil))) :bind (:map text-mode-map ("M-l" . 'dict-map))) (use-package olivetti ; center content per buffer ) ;; (use-package erc ; irc client ;; :init ;; (defun my/start-erc () ;; "Start erc and autojoin various channels" ;; (interactive) ;; (erc-tls :server "tccq.net" :port 4095 :nick "tccq")) ;; :custom ;; (erc-modules '(services autojoin button completion fill imenu irccontrols list match menu ;; move-to-prompt netsplit networks readonly ring stamp track)) ;; (erc-nick "tccq") ;; (erc-use-auth-source-for-nickserv-password t) ;; (erc-autojoin-channels-alist '(("libera.chat" ;; "#emacs" "#haskell" "#duskos" "#tcc"))) ;; (erc-hide-list '("JOIN" "PART" "QUIT")) ;; (erc-current-nick-highlight-type 'nick) ;; (erc-keywords nil) ;; (erc-track-exclude-types '("JOIN" "PART" "QUIT" "NICK" "MODE")) ;; (erc-track-use-faces t) ;; (erc-track-faces-priority-list '(erc-current-nick-face erc-keyword-face)) ;; (erc-track-priority-faces-only 'all)) (use-package minions ; show less on the modeline :demand t :config (minions-mode 1) :custom (minions-prominent-modes '(my/temp-nonmodal-mode persp-mode auto-fill-mode eldoc-mode eglot-mode lsp-mode))) (use-package ispell ; spellchecker :demand t :custom (ispell-personal-dictionary "/home/tmu/.aspell.en.pws") :config (defun ispell-mode (&optional arg) "Make some old packages work with modern ispell." (interactive) (ispell-minor-mode arg)) (advice-add 'ispell-mode :before 'debug) (setq-default text-mode-hook (cons 'ispell-minor-mode (remove 'ispell-mode text-mode-hook))))