;; -*- lexical-binding: t; -*- (progn ; performance stuff: ;; delay initial gc until after loading init if possible (setq gc-cons-threshold most-positive-fixnum) (add-hook 'emacs-startup-hook (lambda () (setq gc-cons-threshold (expt 2 23))))) (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) (push "~/.emacs.d/site-lisp/" load-path) (package-initialize) (require 'use-package-ensure) (setq use-package-always-ensure t) (use-package benchmark-init :config ;; To disable collection of benchmark data after init is done. (add-hook 'after-init-hook 'benchmark-init/deactivate)) (defun toggle-frame-transparency () "Toggle transparency." (interactive) (let ((alpha-transparency 90)) (if (eq alpha-transparency (frame-parameter nil 'alpha-background)) (set-frame-parameter nil 'alpha-background 100) (set-frame-parameter nil 'alpha-background alpha-transparency)))) (defun wrap-region-paren () "Wraps the region in parens. Similar to pressing ( with the region active." (interactive) (let ((beg (region-beginning)) (end (region-end))) (save-excursion (goto-char beg) (insert "(") (goto-char (+ end 1)) (insert ")")))) (defun zap-whitespace () "Zaps (deletes) the whitespace around the point in both directions." (interactive) (push-mark) (skip-chars-backward " \t\n") (push-mark) (skip-chars-forward " \t\n") (delete-region (mark) (point)) (pop-mark) (goto-char (mark)) (pop-mark)) (defun wrap-sexp (&optional arg) "Wraps the following sexp in a pair of parens. Places inside the new pair, with prefix arg do the same backwards, pushing the mark. Does the same of ARG number sexps if given" (interactive "p") (message "%s" arg) (if arg (progn (push-mark) (insert-pair arg ?\( ?\))) (insert-pair 1 ?\( ?\)))) (defun close-or-kill () "If this is the sole frame, kill emacs. Otherwise close the frame." (interactive) (if (eq 1 (length (frame-list))) (save-buffers-kill-terminal) (delete-frame))) (defun my/toggle-window-other-reachability () "Toggle whether this window can be selected by `other-window'." (interactive) (let* ((win (get-buffer-window (current-buffer))) (current (window-parameter win 'no-other-window))) (set-window-parameter win 'no-other-window (not current)))) (defun my/clean-prog-file (buffer) "Fixes whitespace in buffer." (save-excursion (with-current-buffer buffer (untabify (point-min) (point-max)) (goto-char (point-min)) (while (re-search-forward " +$" nil t) (replace-match "" nil nil))))) (defun open-window-by-buffer (buffer) "Move focus to an extant window by the buffer it contains." (interactive "bBuffer: ") (let ((win (get-buffer-window buffer t))) (if win (select-window win) (switch-to-buffer buffer)))) (defun shorten-path (path) "Shortens each directory in PATH except for the last directory to its first character." (let* ((components (split-string path "/")) (last-component (-last (lambda (s) (not (string-empty-p s))) components)) (shortened-components (mapcar (lambda (comp) (if (or (string-equal comp last-component) (string-empty-p comp)) comp (substring comp 0 1))) components))) (mapconcat 'identity shortened-components "/"))) (defun swap-other-window-buffer () "Try to switch the buffer contents of the current window and the next in the cyclic ordering. Don't involve windows that are dedicated." (interactive) (let* ((cw (get-mru-window nil nil nil t)) (cb (window-buffer cw)) (ow (next-window)) (ob (window-buffer ow))) (unless (window-dedicated-p cw) (while (window-dedicated-p ow) (setq ow (next-window ow) ob (window-buffer ow))) (unless (eq cw ow) (progn (with-selected-window ow (switch-to-buffer cb)) (with-selected-window cw (switch-to-buffer ob))))))) (use-package server ; allow emacsclient :demand t :config (unless (server-running-p) (server-start))) (use-package proced ; process editor :commands (proced) :config ;; always auto update proced (setq-default proced-auto-update-flag t) (setq-default proced-auto-update-interval 1)) (use-package orderless ; ordering (minibuffer) completions :demand t :custom ;; (orderless-skip-highlighting t) (completion-styles '(orderless basic)) (orderless-matching-styles '(orderless-prefixes orderless-initialism orderless-literal orderless-regexp))) (use-package vertico ; better minibuffer complete :demand t :custom (vertico-cycle t) :config ;; (vertico-flat-mode) (vertico-mode 1)) (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 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 . corfu-commit-single) :config (global-corfu-mode 1)) (use-package corfu-terminal ; make corfu work on terminals :demand t :custom (corfu-terminal-disable-on-gui nil) :config (corfu-terminal-mode 1)) (use-package cape ; extend completion frameworks :demand t :bind ("C-c p" . cape-prefix-map) :config (advice-add 'pcomplete-completions-at-point :around 'cape-wrap-silent) (advice-add 'pcomplete-completions-at-point :around 'cape-wrap-purify) (setq-default completion-at-point-functions (apply 'cape-wrap-super (append '(tags-completion-at-point-function cape-dabbrev cape-dict) completion-at-point-functions)))) (use-package dabbrev ; dynamic abbreviations :demand t :config (add-to-list 'dabbrev-ignored-buffer-regexps "\\` ") ;; (add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode) ;; (add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode) ;; (add-to-list 'dabbrev-ignored-buffer-modes 'tags-table-mode) ) ;; TODO debug / test ;; (use-package tempel ;; :after (cape) ;; :custom ;; (tempel-path "~/.emacs.d/templates/*.eld") ;; ;; (tempel-trigger-prefix "<") ;; :bind (("M-+" . tempel-complete) ;; Alternative tempel-expand ;; ("M-*" . tempel-insert)) ;; :config ;; ;; Setup completion at point ;; (defun tempel-setup-capf () ;; ;; Add the Tempel Capf to `completion-at-point-functions'. ;; ;; `tempel-expand' only triggers on exact matches. Alternatively use ;; ;; `tempel-complete' if you want to see all matches, but then you ;; ;; should also configure `tempel-trigger-prefix', such that Tempel ;; ;; does not trigger too often when you don't expect it. NOTE: We add ;; ;; `tempel-expand' *before* the main programming mode Capf, such ;; ;; that it will be tried first. ;; (setq-local completion-at-point-functions ;; (cons #'tempel-expand ;; completion-at-point-functions))) ;; (add-hook 'conf-mode-hook 'tempel-setup-capf) ;; (add-hook 'prog-mode-hook 'tempel-setup-capf) ;; (add-hook 'text-mode-hook 'tempel-setup-capf) ;; ;; Optionally make the Tempel templates available to Abbrev, ;; ;; either locally or globally. `expand-abbrev' is bound to C-x '. ;; ;; (add-hook 'prog-mode-hook #'tempel-abbrev-mode) ;; ;; (global-tempel-abbrev-mode) ;; ) ;; (use-package tempel-collection ;; :after tempel) (progn ; dired directory editor (require 'dired) (defun dired-do-find-marked-files () (interactive) (seq-do 'find-file (dired-get-marked-files))) (define-key dired-mode-map (kbd "C-o") 'dired-display-file) (define-key dired-mode-map (kbd "F") 'dired-do-find-marked-files)) (use-package ibuffer ; give a nice list of buffers with extra info :commands (ibuffer) :custom (ibuffer-formats '((mark modified read-only " " (name 50 50 :left :elide) ; was originally 18 " " (size 9 -1 :right) " " (mode 16 16 :left :elide) " " filename-and-process) (mark " " (name 16 -1) " " filename))) :bind ("C-x C-b" . ibuffer)) (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 magit) (use-package free-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 recentf :config (recentf-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-S-w" . consult-buffer) ("C-S-y" . consult-yank-from-kill-ring) ("M-g M-g" . consult-goto-line) ("M-i" . consult-imenu-multi) ("C-s" . consult-line) ("C-S-s" . consult-line-multi) ("M-s g" . consult-grep) ("M-s G" . grep) ("M-s f" . consult-find)) (use-package embark-consult :after embark consult) (use-package hl-todo ; highlight certain keywords :hook (prog-mode . hl-todo-mode)) (use-package hl-line ; make it easier to find your point ;; TODO this doesn't work with buffers created after enabled :bind ("M-s h SPC" . global-hl-line-mode)) (use-package visible-mark ; make the mark visible ;; TODO make the attr list display dependent :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 (("C-'" . avy-goto-char-2) ("M-G" . avy-goto-char-2))) (use-package balanced-windows ; auto rebalance windows :bind ("C-x w b" . balanced-windows-mode)) (use-package eshell ; emacs shell :demand t :config (use-package esh-help) (require 'em-hist) (require 'em-term) (setup-esh-help-eldoc) ;; (keymap-set eshell-hist-mode-map "C-p" 'eshell-previous-input) ;; (keymap-set eshell-hist-mode-map "C-n" 'eshell-next-input) ;; (keymap-set eshell-hist-mode-map "C-c C-n" 'next-line) ;; (keymap-set eshell-hist-mode-map "C-c C-p" 'previous-line) :bind (:map eshell-mode-map ("C-l" . eshell/clear)) :hook (eshell-mode . eldoc-mode)) (use-package vterm) (use-package shelldon :demand t :config ;; (setf shell-command-switch "-ic") (setf enable-recursive-minibuffers t) ;; command codes -> ansi colors in emacs (add-hook 'shelldon-mode-hook 'ansi-color-for-comint-mode-on) (add-to-list 'comint-output-filter-functions 'ansi-color-process-output) (autoload 'ansi-color-for-comint-mode-on "ansi-color" nil t) (add-to-list 'display-buffer-alist '("*shelldon:" (display-buffer-reuse-window display-buffer-in-previous-window display-buffer-in-side-window display-buffer-pop-up-window) (side . right) (slot . 0) (window-width . 80))) :bind ("M-&" . 'shelldon) ("M-*" . 'shelldon-loop)) (use-package eat ; terminal override to make eshell behave better :demand t :config (eat-eshell-mode) (eat-eshell-visual-command-mode)) (progn ; comint, doesn't play with use-package (require 'comint) (setq-default comint-scroll-to-bottom-on-input t) (setq-default comint-scroll-to-bottom-on-output t)) (use-package bash-completion :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 treemacs ; file explorer :bind (("C-c t" . treemacs))) (use-package pass ; password integration :demand t :init (use-package password-store) (use-package auth-source-pass :init (auth-source-pass-enable)) :custom (pass-suppress-confirmations t) (epg-pinentry-mode 'loopback) :config (push '("\\*Password-Store\\*" display-buffer-in-side-window (side . right)) display-buffer-alist)) (use-package tramp ; remote access for files :demand t :custom (tramp-allow-unsafe-temporary-files t)) (use-package asm-mode ; asm comments and tags generation :demand t :custom (asm-comment-char ?#) ; prefer # over ; for asm comments :init (defun add-asm-label-tag-generation-hook () (add-hook 'after-save-hook (lambda () (shell-command "find . -iregex '.*\\.[sS]' -exec etags -l none -r '/\\([a-zA-Z0-9\\-_]+\\):/\1/' {} +")) 0 t)) :hook (asm-mode . 'add-asm-label-tag-generation-hook)) (use-package lsp-mode :commands (lsp) :init (use-package lsp-haskell) :custom (lsp-completion-provider :none) :config (defun corfu-lsp-setup () (setq-local completion-styles '(orderless) completion-category-defaults nil)) (add-hook 'lsp-completion-mode-hook #'corfu-lsp-setup)) (use-package pyvenv) (use-package sideline ; put warnings on the side of the same line :init (use-package sideline-flycheck) (use-package sideline-flymake) (use-package sideline-lsp) :custom (sideline-backends-right '(sideline-flycheck sideline-flymake sideline-lsp))) (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))) :hook (prog-mode . flycheck-mode)) (progn ; better commenting binds (global-set-key (kbd "C-x C-;") 'comment-or-uncomment-region) (global-set-key (kbd "C-x ;") 'comment-line) (global-set-key (kbd "C-x :") 'comment-set-column) ;; ^ never gonna use but whatever ) (use-package imenu ; jump to items in the current buffer :custom (imenu-auto-rescan t) (imenu-flatten t)) (use-package xref ; jump to syntactic elements in project ;; (add-hook 'xref-backend-functions 'gxref-xref-backend) :bind ("M-I" . xref-find-definitions)) (use-package ediff :custom (ediff-window-setup-function 'ediff-setup-windows-plain)) (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) (use-package fold-this ; fold arbitrary region :init (defun 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 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-c" . fold-this) ("C-e" . fold-this-unfold-at-point) ("f" . fold-this-fold-forward) ("b" . fold-this-fold-backward))) (use-package origami :demand t :init (global-origami-mode 1) :bind (:map my/fold-map ("t" . origami-forward-toggle-node) ("T" . origami-recursively-toggle-node) ("o" . origami-show-node) ("O" . origami-open-node-recursively) ("c" . origami-close-node) ("C" . origami-close-node-recursively) ("l" . origami-toggle-all-nodes))) (add-hook 'prog-mode-hook (lambda () (superword-mode 1) (modify-syntax-entry ?_ "w") (display-fill-column-indicator-mode 1) (add-hook 'before-save-hook (lambda () (if (not (eq major-mode 'makefile-gmake-mode)) (my/clean-prog-file (current-buffer))))))) (use-package haskell-mode :custom (haskell-tags-on-save t) (haskell-process-type 'cabal-repl) :hook (haskell-mode . interactive-haskell-mode)) (use-package ocp-indent) (let ((opam-share (ignore-errors (car (process-lines "opam" "var" "share"))))) (when (and opam-share (file-directory-p opam-share)) ;; Register Merlin (add-to-list 'load-path (expand-file-name "emacs/site-lisp" opam-share)) (autoload 'merlin-mode "merlin" nil t nil) ;; Automatically start it in OCaml buffers (add-hook 'tuareg-mode-hook 'merlin-mode t) (add-hook 'caml-mode-hook 'merlin-mode t) ;; Use opam switch to lookup ocamlmerlin binary (setq merlin-command 'opam) ;; To easily change opam switches within a given Emacs session, you can ;; install the minor mode https://github.com/ProofGeneral/opam-switch-mode ;; and use one of its "OPSW" menus. )) (use-package racket-mode) (use-package rustic :custom (rustic-lsp-setup-p nil)) (progn ; elisp (keymap-set emacs-lisp-mode-map "C-c r" 'raise-sexp)) (use-package compile :custom (compilation-always-kill t) (compilation-scroll-output t) :bind ("M-M" . 'recompile) :config ;; Allow compilation buffer to be dedicated across frames (push '("\\*compilation\\*" . (nil (reusable-frames . t))) display-buffer-alist)) ;; (use-package evil ;; :demand nil ;; :custom ;; (evil-want-keybinding nil) ;; (evil-want-integration t) ;; :config ;; (use-package evil-collection ;; :config (evil-collection-init)) ;; (use-package evil-easymotion ;; :config (evilem-default-keybindings "SPC")) ;; (use-package evil-surround ;; :config (global-evil-surround-mode 1)) ;; (use-package evil-snipe ;; :custom (evil-snipe-scope 'buffer) ;; :config ;; (evil-snipe-mode 1) ;; (evil-snipe-override-mode 1) ;; :bind ;; (:map evil-snipe-local-mode-map ;; ("z" . 'evil-snipe-s) ;; ("Z" . 'evil-snipe-S))) ;; (use-package treemacs-evil) ;; :hook ;; (eshell-mode-hook . (lambda () (evil-local-mode -1))) ;; (vterm-mode-hook . (lambda () (evil-local-mode -1))) ;; :bind ;; (:map evil-insert-state-map ;; ("C-d" . 'delete-char) ;; ("C-e" . 'move-end-of-line) ;; ("C-a" . 'move-beginning-of-line) ;; ("C-t" . 'transpose-chars)) ;; (:map evil-normal-state-map ;; ("M-." . 'xref-find-definitions) ;; ("M-Z" . 'suspend-frame) ;; ("C-t" . 'transpose-chars)) ;; (:map evil-motion-state-map ;; ("TAB" . 'indent-for-tab-command))) (use-package exwm ; emacs x window manager :demand t :config (require 'exwm-randr) (require 'exwm-xim) (require 'exwm-systemtray) (require 'exwm-manage) (add-to-list 'exwm-manage-configurations '((equal exwm-class-name "Slack") managed t)) (use-package exwm-modeline) ;;(exwm-xim-mode 1) (defun my/exwm-auto-workspace-montior () "Autopopulate exwm-randr-workspace-monitor-plist and attempt to have a workspace on each monitor. Try to keep up with xrandr changes." (let ((buf (generate-new-buffer "*xrandr-output*")) (out-plist nil)) (call-process-shell-command "xrandr --listmonitors -q" nil buf nil) (with-current-buffer buf (keep-lines "[^[:word:]]connected" (point-min) (point-max) nil) (let ((num-monitors (count-lines (point-min) (point-max))) (i 0)) (setq exwm-workspace-number num-monitors) (goto-char (point-min)) (while (< i num-monitors) (move-beginning-of-line 1) (push-mark) (search-forward-regexp " ") (backward-char) (push (buffer-substring (mark) (point)) out-plist) (push i out-plist) (setq i (+ i 1)) (pop-mark) (next-line)))) (kill-buffer buf) (setq exwm-randr-workspace-monitor-plist out-plist)) (while (> exwm-workspace-number (length exwm-workspace--list)) (exwm-workspace-add))) (add-hook 'exwm-randr-screen-change-hook #'my/exwm-auto-workspace-montior) (defun my/exwm-set-buffer-name () (if exwm-title (let* ((shortened-title (replace-regexp-in-string " - Mozilla Firefox" "" exwm-title)) (class-and-title (concat exwm-class-name "<" shortened-title ">"))) (setq-local exwm-title class-and-title) (exwm-workspace-rename-buffer exwm-title)))) (defun my/exwm-other-workspace (arg) "Focus other monitor's workspace." (interactive "p") ;; based on other-frame (let ((filter-f (function (lambda (f) (and (exwm-workspace--active-p f) (not (eq (selected-frame) f)))))) (sframe (selected-frame)) (frame (selected-frame))) (while (> arg 0) (setq frame (next-frame frame)) (while (and (not (eq frame sframe)) (not (eq (frame-visible-p frame) t)) (filter-f frame)) (setq frame (next-frame frame))) (setq arg (1- arg))) (while (< arg 0) (setq frame (previous-frame frame)) (while (and (not (eq frame sframe)) (not (eq (frame-visible-p frame) t)) (filter-f frame)) (setq frame (previous-frame frame))) (setq arg (1+ arg))) (exwm-workspace-switch frame))) (defun my/dmenu (command) (interactive (list (read-shell-command "$ "))) (start-process-shell-command command nil command)) (defun my/browser () (interactive) (start-process-shell-command "firefox" nil "firefox")) (exwm-randr-mode) (exwm-systemtray-mode) (push ?\C-\\ exwm-input-prefix-keys) ;;C-\ to switch input method (push ?\C-u exwm-input-prefix-keys) ;; send C-u to all windows too (push ?\M-L exwm-input-prefix-keys) (setq exwm-marked-buffer "*scratch*") ;; store the buffer we were at before a jump (when (equal window-system 'x) (exwm-enable)) :hook (exwm-update-class . my/exwm-set-buffer-name) (exwm-update-title . my/exwm-set-buffer-name) :custom (exwm-title-length 50) (exwm-workspace-show-all-buffers t) (exwm-layout-show-all-buffers t) (exwm-modeline-randr t) (exwm-modeline-short nil) (exwm-modeline-urgent t) (exwm-manage-force-tiling t) (exwm-input-global-keys `( ([?\M-r] . exwm-reset) ;; Bind "s-w" to window switcher ([?\M-W] . consult-buffer) ([?\M-o] . other-window) ([?\M-O] . my/exwm-other-workspace) ([?\M-D] . my/dmenu) ([?\M-E] . my/browser) ([M-return] . eshell) )) (exwm-input-simulation-keys '(;; movement ([?\C-b] . [left]) ([?\M-b] . [C-left]) ([?\C-f] . [right]) ([?\M-f] . [C-right]) ([?\C-p] . [up]) ([?\C-n] . [down]) ([?\C-a] . [home]) ([?\C-e] . [end]) ([?\M-v] . [prior]) ([?\C-v] . [next]) ;; edit, copy, paste ([?\C-d] . [delete]) ([?\C-k] . [S-end delete]) ([M-backspace] . [C-backspace]) ([?\M-w] . [?\C-c]) ([?\C-y] . [?\C-v]) ([?\C-s] . [?\C-f]))) :bind (:map exwm-mode-map ("C-q" . 'exwm-input-send-next-key) ("M-!" . 'shell-command))) (progn ; media/function keys ;; requires some custom shell scripts not included in my emacs config (defun my/brightnessdown () (interactive) (start-process "" nil "brightnessdown")) (defun my/brightnessup () (interactive) (start-process "" nil "brightnessup")) (defun my/mute () (interactive) (start-process "" nil "pactl" "set-sink-mute" "@DEFAULT_SINK@" "toggle")) (defun my/voldown () (interactive) (start-process "" nil "pactl" "set-sink-volume" "@DEFAULT_SINK@" "-5%")) (defun my/volup () (interactive) (start-process "" nil "pactl" "set-sink-volume" "@DEFAULT_SINK@" "+5%")) (global-set-key (kbd "") 'my/brightnessdown) (global-set-key (kbd "") 'my/brightnessup) (global-set-key (kbd "") 'my/mute) (global-set-key (kbd "") 'my/voldown) (global-set-key (kbd "") 'my/volup) (define-key exwm-mode-map (kbd "") 'my/brightnessdown) (define-key exwm-mode-map (kbd "") 'my/brightnessup) (define-key exwm-mode-map (kbd "") 'my/mute) (define-key exwm-mode-map (kbd "") 'my/voldown) (define-key exwm-mode-map (kbd "") 'my/volup)) (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 erc ; irc client :init (defun my/start-erc () "Start erc and autojoin various channels" (interactive) (erc :server "irc.libera.chat" :port 6667)) :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" "#emacs-social" "#linux" "#archlinux" "#haskell" "#invidious" "#duskos"))) (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)) (progn ; indent code when pasting, from ;; https://trey-jackson.blogspot.com/2008/03/emacs-tip-15-indent-yanked-code.html ;; automatically indenting yanked text if in programming-modes (defvar yank-indent-modes '(emacs-lisp-mode c-mode c++-mode tcl-mode sql-mode perl-mode cperl-mode java-mode jde-mode lisp-interaction-mode LaTeX-mode TeX-mode rust-mode rustic-mode) "Modes in which to indent regions that are yanked (or yank-popped).") (defun yank-advised-indent-function (beg end) "Do indentation, as long as the region isn't too large. BEG and END define the region." (indent-region beg end nil)) (defadvice yank (after yank-indent activate) "If current mode is one of 'yank-indent-modes, indent yanked text (with prefix arg don't indent)." (if (and (not (ad-get-arg 0)) (member major-mode yank-indent-modes)) (let ((transient-mark-mode nil)) (yank-advised-indent-function (region-beginning) (region-end))))) (defadvice yank-pop (after yank-pop-indent activate) "If current mode is one of 'yank-indent-modes, indent yanked text (with prefix arg don't indent)." (if (and (not (ad-get-arg 0)) (member major-mode yank-indent-modes)) (let ((transient-mark-mode nil)) (yank-advised-indent-function (region-beginning) (region-end)))))) (use-package minions :demand t :config (minions-mode 1) :custom (minions-prominent-modes '(persp-mode auto-fill-mode eldoc-mode eglot-mode lsp-mode))) (progn ; default modeline config additions (setq-default global-mode-string '("" (:eval (let ((str (concat (format " [%s] " (shorten-path default-directory))))) (add-face-text-property 0 (length str) '(:weight bold :foreground "green2") t str) str))))) (progn ; comfy scratch buffer (require 'iimage) (setq inhibit-startup-screen t) (setq initial-scratch-message (concat (propertize ";; " 'invisible t) " ;; scratch for lisp evaluation and unsaved text ")) (add-hook 'emacs-startup-hook (lambda () (with-current-buffer "*scratch*" (emacs-lock-mode 'kill) (iimage-mode 1))))) (progn ; confirm fewer things (setq kill-buffer-query-functions (delq 'process-kill-buffer-query-function kill-buffer-query-functions)) (setq confirm-kill-processes nil) ;; start additional async shell commands in new buffers without asking (setq async-shell-command-buffer 'new-buffer)) (use-package ispell ; spellchecker :demand t :custom (ispell-personal-dictionary "/home/tmu/.aspell.en.pws") :hook (text-mode . 'ispell-minor-mode)) (electric-pair-mode 1) ;; (setq x-super-keysym 'meta) (global-set-key (kbd "C-x C-C") 'save-buffers-kill-terminal) (global-set-key (kbd "C-x C-c") 'close-or-kill) (global-set-key (kbd "M-w") 'copy-region-as-kill) ; make copying not flash cursor (global-set-key (kbd "C-x -") 'swap-other-window-buffer) (global-set-key (kbd "M-(") 'wrap-region-paren) (global-set-key (kbd "M-z") 'zap-whitespace) (global-set-key (kbd "C-M-z") 'wrap-sexp) (global-set-key (kbd "M-o") 'other-window) (global-set-key (kbd "M-c") 'calc) (global-set-key (kbd "M-U") 'scroll-lock-mode) (global-set-key (kbd "M-Q") 'auto-fill-mode) (global-set-key (kbd "C-x w o") 'my/toggle-window-other-reachability) ;; (use-package single-header ;; :ensure nil ;; :demand t ;; :init ;; (use-package ednc ; notifications, required for single-header ;; ) ;; :config ;; (single-header-mode 1) ;; :bind ;; ("M-L d" . 'single-header-dismiss) ;; ("M-L t" . 'single-header-mode) ;; ;; (keymap-global-set "M-L d" 'single-header-dismiss) ;; ;; (keymap-global-set "M-L t" 'single-header-mode) ;; ) (use-package time :demand t :config (display-time-mode 1) :custom (display-time-day-and-date t) (display-time-24hr-format t)) (use-package ednc :demand t :config (when (eq window-system 'x) (ednc-mode 1))) ;; ---------------------------------------------------------------------- ;; theme stuff (require 'tmu-custom-theme) (push "~/.emacs.d/site-lisp/" custom-theme-load-path) (load-theme 'tmu-custom t) ;; ---------------------------------------------------------------------- ;; Things emacs sets programatically (put 'dired-find-alternate-file 'disabled nil) (put 'upcase-region 'disabled nil) (put 'downcase-region 'disabled nil) (put 'list-timers 'disabled nil) (put 'narrow-to-region 'disabled nil) (custom-set-variables ;; custom-set-variables was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(comment-style 'extra-line) '(connection-local-criteria-alist '(((:application eshell :protocol "ssh" :user "tmu" :machine "cnoserver") autogenerated-connection-local-profile/\(:application\ eshell\ :protocol\ \"ssh\"\ :user\ \"tmu\"\ :machine\ \"cnoserver\"\)) ((:application vc-git :protocol "ssh" :user "tmu" :machine "cnoserver") autogenerated-connection-local-profile/\(:application\ vc-git\ :protocol\ \"ssh\"\ :user\ \"tmu\"\ :machine\ \"cnoserver\"\)) ((:application vc-git) vc-git-connection-default-profile) ((:application tramp :protocol "kubernetes") tramp-kubernetes-connection-local-default-profile) ((:application tramp :protocol "flatpak") tramp-container-connection-local-default-flatpak-profile tramp-flatpak-connection-local-default-profile) ((:application tramp) tramp-connection-local-default-system-profile tramp-connection-local-default-shell-profile) ((:application eshell) eshell-connection-default-profile)) t) '(connection-local-profile-alist '((autogenerated-connection-local-profile/\(:application\ eshell\ :protocol\ \"ssh\"\ :user\ \"tmu\"\ :machine\ \"cnoserver\"\) (eshell-path-env-list "/bin" "/usr/bin" "/sbin" "/usr/sbin" "/usr/local/bin" "/usr/local/sbin")) (autogenerated-connection-local-profile/\(:application\ vc-git\ :protocol\ \"ssh\"\ :user\ \"tmu\"\ :machine\ \"cnoserver\"\) (vc-git--program-version . "2.48.1")) (vc-git-connection-default-profile (vc-git--program-version)) (tramp-flatpak-connection-local-default-profile (tramp-remote-path "/app/bin" tramp-default-remote-path "/bin" "/usr/bin" "/sbin" "/usr/sbin" "/usr/local/bin" "/usr/local/sbin" "/local/bin" "/local/freeware/bin" "/local/gnu/bin" "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin" "/opt/bin" "/opt/sbin" "/opt/local/bin")) (tramp-kubernetes-connection-local-default-profile (tramp-config-check . tramp-kubernetes--current-context-data) (tramp-extra-expand-args 97 (tramp-kubernetes--container (car tramp-current-connection)) 104 (tramp-kubernetes--pod (car tramp-current-connection)) 120 (tramp-kubernetes--context-namespace (car tramp-current-connection)))) (tramp-container-connection-local-default-flatpak-profile (tramp-remote-path "/app/bin" tramp-default-remote-path "/bin" "/usr/bin" "/sbin" "/usr/sbin" "/usr/local/bin" "/usr/local/sbin" "/local/bin" "/local/freeware/bin" "/local/gnu/bin" "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin" "/opt/bin" "/opt/sbin" "/opt/local/bin")) (tramp-connection-local-darwin-ps-profile (tramp-process-attributes-ps-args "-acxww" "-o" "pid,uid,user,gid,comm=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" "-o" "state=abcde" "-o" "ppid,pgid,sess,tty,tpgid,minflt,majflt,time,pri,nice,vsz,rss,etime,pcpu,pmem,args") (tramp-process-attributes-ps-format (pid . number) (euid . number) (user . string) (egid . number) (comm . 52) (state . 5) (ppid . number) (pgrp . number) (sess . number) (ttname . string) (tpgid . number) (minflt . number) (majflt . number) (time . tramp-ps-time) (pri . number) (nice . number) (vsize . number) (rss . number) (etime . tramp-ps-time) (pcpu . number) (pmem . number) (args))) (tramp-connection-local-busybox-ps-profile (tramp-process-attributes-ps-args "-o" "pid,user,group,comm=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" "-o" "stat=abcde" "-o" "ppid,pgid,tty,time,nice,etime,args") (tramp-process-attributes-ps-format (pid . number) (user . string) (group . string) (comm . 52) (state . 5) (ppid . number) (pgrp . number) (ttname . string) (time . tramp-ps-time) (nice . number) (etime . tramp-ps-time) (args))) (tramp-connection-local-bsd-ps-profile (tramp-process-attributes-ps-args "-acxww" "-o" "pid,euid,user,egid,egroup,comm=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" "-o" "state,ppid,pgid,sid,tty,tpgid,minflt,majflt,time,pri,nice,vsz,rss,etimes,pcpu,pmem,args") (tramp-process-attributes-ps-format (pid . number) (euid . number) (user . string) (egid . number) (group . string) (comm . 52) (state . string) (ppid . number) (pgrp . number) (sess . number) (ttname . string) (tpgid . number) (minflt . number) (majflt . number) (time . tramp-ps-time) (pri . number) (nice . number) (vsize . number) (rss . number) (etime . number) (pcpu . number) (pmem . number) (args))) (tramp-connection-local-default-shell-profile (shell-file-name . "/bin/sh") (shell-command-switch . "-c")) (tramp-connection-local-default-system-profile (path-separator . ":") (null-device . "/dev/null")) (eshell-connection-default-profile (eshell-path-env-list))) t) '(custom-safe-themes '("aee99e2118e960b53016623dc2345d88227d1236d28c6c34858e1d55575cf7c3" "6f5e3fd2b4245ffe660da69ea5c13ab392337e94776dfb23cc1d8d0f80e3baa2" "1b8c2fd98bf6777d8b95f8cf98fdaede88feee3419ec3e5008f94b56618ac6ca" "0cc5046b7981609166c28b64f6185fa5f73bcb00d21e037f304794c6aaa1f340" "9f2e4e8b2ddbfdd392eedbc123649d94654278dee5a53b899557224416413d35" "6dafb31ade9ff07229faaf05c41c2ae475c44731362b792f65f3930b1a2c9cfd" "dc77e008092a5a4aa6b6ed8e4826bebf8f2fb930a8de073bf7f458efd884cca8" "d1ff3e66028f9c527298580d2a64f9e3280f07f9e94d4dada72b67ef15069441" "3d4e3644e237a95683daa73e397c4c0d1ae06bbaaf8040104232591a28bc1315" "12a07bc38295e4b06a8965db261f51ea7ea61fbf91b3ef41298bbb549d1d9403" default)) '(ede-project-directories '("/home/tmu/Desktop/eway/sway" "/home/tmu/Desktop/eway/cage" "/home/tmu/Desktop/eway/wlroots" "/home/tmu/Desktop/eway/comp" "/home/tmu/Desktop/eway")) '(eglot-events-buffer-config '(:size 0 :format full)) '(fortune-dir "/usr/share/fortune/") '(gdb-non-stop-setting nil) '(helm-minibuffer-history-key "M-p") '(menu-bar-mode nil) '(package-selected-packages '(balanced-windows bash-completion benchmark-init cape consult corfu-terminal counsel-embark eat ednc embark embark-consult embark-counsel esh-help evil-collection evil-easymotion evil-snipe evil-surround exwm-modeline fold-this free-keys haskell-mode hl-todo ibuffer-vc lsp-haskell magit marginalia minions ocp-indent orderless pass pyvenv racket-mode rustic sdcv shelldon sideline-flycheck sideline-flymake sideline-lsp treemacs-evil vertico visible-mark vterm winum)) '(pyim-assistant-scheme 'cangjie) '(safe-local-variable-values '((LEXICAL-binding . t))) '(scroll-bar-mode nil) '(tags-revert-without-query t) '(tool-bar-mode nil) '(transient-mark-mode nil) '(whitespace-style '(face trailing tabs lines-tail missing-newline-at-eof indentation space-after-tab space-before-tab tab-mark) t)) (custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. )