123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460 |
- ;;; init.el --- Configuration entry point -*- lexical-binding: t -*-
- ;;; Commentary:
- ;;; Code:
- ;; Some other config files
- (add-to-list 'load-path "~/.emacs.d/elisp")
- ;; Set package dir to follow no-littering conventions
- (setq package-user-dir "~/.emacs.d/var/elpa")
- ;; Use melpa
- (require 'package)
- (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
- (package-initialize)
- ;; Ensure use-package is installed
- (unless (package-installed-p 'use-package)
- (package-refresh-contents)
- (package-install 'use-package))
- ;; use-package
- (eval-when-compile
- (require 'use-package)
- (setq use-package-always-ensure t
- package-user-dir "~/.emacs.d/var/elpa"))
- ;; no-littering
- (use-package no-littering
- :autoload (no-littering-theme-backups
- no-littering-expand-etc-file-name)
- :init
- (no-littering-theme-backups)
- (setq custom-file (no-littering-expand-etc-file-name "custom.el")))
- ;; diminish
- (use-package diminish
- :config
- (diminish 'visual-line-mode)
- (diminish 'abbrev-mode))
- ;; Private config loading
- (require 'private nil t)
- (defun my/get-private (key)
- "Get the private config variable KEY from the private configuration file."
- (alist-get key my/private-config))
- ;; basic stuff
- (use-package emacs
- :hook (;;(emacs-lisp-mode . my/-emacs-lisp-mode-setup-evil-lookup)
- ;;(prog-mode . electric-pair-local-mode)
- ((text-mode tex-mode prog-mode) . auto-fill-mode)
- ((text-mode tex-mode prog-mode) . my/-enable-show-trailing-whitespace))
- :init
- (defun my/-enable-show-trailing-whitespace ()
- (setq-local show-trailing-whitespace t))
- ;; (defun my/-emacs-lisp-mode-setup-evil-lookup ()
- ;; (setq-local evil-lookup-func
- ;; #'my/describe-symbol-at-point))
- (defun my/describe-symbol-at-point ()
- "Calls `describe-symbol' on the return value of `symbol-at-point'."
- (interactive)
- (let ((form (symbol-at-point)))
- (if (consp form)
- (describe-symbol (cadr form))
- (describe-symbol form))))
- ;; Increase responsiveness
- (setq gc-cons-threshold 80000000
- read-process-output-max (* 1024 1024)) ;; 1mb
- (global-so-long-mode 1)
- ;; Terminal mouse support
- (xterm-mouse-mode 1)
- ;; Make cursor more visible
- (global-hl-line-mode 1)
- (blink-cursor-mode -1)
- ;; Enable all disabled stuff
- (setq disabled-command-function nil)
- ;; Stop some annoying stuff
- (setq extended-command-suggest-shorter nil
- suggest-key-bindings nil)
- ;; Better scrolling
- (setq mouse-scroll-delay 0
- scroll-conservatively 10
- scroll-margin 2
- scroll-preserve-screen-position t)
- ;; Make show paren instant
- (setq show-paren-delay 0)
- (show-paren-mode 1)
- ;; Display line numbers
- (global-display-line-numbers-mode 1)
- ;; Allow the frame to be any size
- (setq frame-resize-pixelwise t)
- ;; Don't use a gtk file picker
- (setq use-file-dialog nil)
- ;; Make yes-or-no-p less verbose (and not use windows)
- (setq use-dialog-box nil
- use-short-answers t)
- ;; Disable startup screen
- (setq inhibit-startup-screen t
- server-client-instructions nil)
- ;; show column numbers
- (column-number-mode 1)
- ;; Disable the menu and tool bars
- (menu-bar-mode -1)
- (tool-bar-mode -1)
- ;; No scroll bars
- (scroll-bar-mode -1)
- ;; Visual line mode
- (global-visual-line-mode 1)
- ;; Make some commands easier to enter multiple times
- (repeat-mode 1)
- ;; Easier buffer navigation
- (keymap-global-set "C-c <" #'previous-buffer)
- (keymap-global-set "C-c >" #'next-buffer)
- (keymap-global-set "C-c k" #'previous-buffer)
- (keymap-global-set "C-c j" #'next-buffer)
- ;; Set fonts
- (add-to-list 'default-frame-alist '(font . "FiraCode Nerd Font Mono-12"))
- (add-hook 'server-after-make-frame-hook
- (lambda ()
- (set-fontset-font t 'japanese-jisx0208 "IPAGothic")))
- ;; Enable color in compilation buffers
- (add-hook 'compilation-filter-hook 'ansi-color-compilation-filter)
- ;; Some settings for programming
- (setq-default indent-tabs-mode nil
- tab-width 4
- fill-column 80
- comment-multi-line t
- comment-empty-lines 'eol)
- (add-to-list 'auto-mode-alist '("\\.[cC][nN][fF]\\'" . conf-mode))
- (keymap-set emacs-lisp-mode-map "C-c C-r" #'eval-region)
- (defun my/-fix-emacs-lisp-mode-system-files ()
- (when (string-prefix-p lisp-directory buffer-file-name)
- ;; system Emacs files use tab characters and look weird without this.
- (setq-local tab-width 8)))
- (add-hook 'emacs-lisp-mode-hook #'my/-fix-emacs-lisp-mode-system-files)
- ;; Tree sitter download locations
- (setq treesit-language-source-alist
- '((c "https://github.com/tree-sitter/tree-sitter-c")
- (cpp "https://github.com/tree-sitter/tree-sitter-cpp")
- (java "https://github.com/tree-sitter/tree-sitter-java")
- (python "https://github.com/tree-sitter/tree-sitter-python")
- (rust "https://github.com/tree-sitter/tree-sitter-rust")
- (json "https://github.com/tree-sitter/tree-sitter-json")
- (yaml "https://github.com/ikatyang/tree-sitter-yaml")
- (css "https://github.com/tree-sitter/tree-sitter-css")
- (go "https://github.com/tree-sitter/tree-sitter-go")
- (gomod "https://github.com/camdencheek/tree-sitter-go-mod")
- (javascript "https://github.com/tree-sitter/tree-sitter-javascript")
- (bash "https://github.com/tree-sitter/tree-sitter-bash")
- (cmake "https://github.com/uyha/tree-sitter-cmake")
- (blueprint "https://github.com/huanie/tree-sitter-blueprint")
- (kdl "https://github.com/tree-sitter-grammars/tree-sitter-kdl")))
- ;; Tree sitter major mode conversions
- (setq major-mode-remap-alist
- '((c-mode . c-ts-mode)
- (c++-mode . c++-ts-mode)
- (c-or-c++-mode . c-or-c++-ts-mode)
- (python-mode . python-ts-mode)
- (java-mode . java-ts-mode)
- (rust-mode . rust-ts-mode)
- (json-mode . json-ts-mode)
- (yaml-mode . yaml-ts-mode)
- (css-mode . css-ts-mode)
- (js-mode . js-ts-mode)
- (cmake-mode . cmake-ts-mode)))
- (defun my/treesit-compile-all (force)
- "Compile all the modules defined in `treesit-language-source-alist'.
- If FORCE, recompile all modules, even ones that are already compiled.
- Interactively, force the recompile if called with a prefix."
- (interactive "P")
- (let ((did-build nil))
- (dolist (lang treesit-language-source-alist)
- (when (or force (not (treesit-language-available-p (car lang))))
- (treesit-install-language-grammar (car lang))
- (setq did-build t)))
- (unless did-build
- (message "All defined parsers installed!")))))
- (use-package midnight
- :ensure nil
- :config
- (add-to-list 'clean-buffer-list-kill-never-buffer-names
- "*mu4e-main*")
- (add-to-list 'clean-buffer-list-kill-never-buffer-names
- "*Async-native-compile-log*")
- (add-to-list 'clean-buffer-list-kill-never-buffer-names
- "*dashboard*")
- (add-to-list 'clean-buffer-list-kill-never-buffer-names
- "*elfeed-search*")
- (midnight-mode 1))
- (defvar my/kill-some-buffers-exclude-names
- '("*mu4e-main*" "*Async-native-compile-log*" "*dashboard*" "*elfeed-search*"
- "*Messages*" "*scratch*")
- "List of literal buffer names that `my/kill-some-buffers' should not kill.")
- (defun my/kill-some-buffers-excluded-buffer-p (buffer)
- "Return non-nil if BUFFER should be excluded from `my/kill-some-buffers'."
- (cl-find (buffer-name buffer) my/kill-some-buffers-exclude-names
- :test 'equal))
- (defun my/buffer-visible-p (buffer)
- "Return non-nil if BUFFER is visible.
- BUFFER can be a string or a buffer."
- (cond
- ((stringp buffer)
- (not (string-prefix-p " " buffer)))
- ((bufferp buffer)
- (and (stringp (buffer-name buffer))
- (my/buffer-visible-p (buffer-name buffer))))
- (t
- (signal 'wrong-type-argument `((or bufferp stringp) ,buffer)))))
- (defvar my/kill-some-buffers-default-pred 'my/buffer-visible-p
- "Default predicate for `my/kill-some-buffers'.")
- (defun my/kill-some-buffers-prompt-for (buffer)
- "Generate a prompt for BUFFER."
- (let* ((process (get-buffer-process buffer))
- (process-p (and (process-live-p process)
- (not (process-query-on-exit-flag process))))
- (modified-p (and (buffer-file-name buffer)
- (buffer-modified-p buffer))))
- (format "Buffer \"%s\" %s. Kill? "
- (buffer-name buffer)
- (cond
- ((and process-p modified-p)
- "HAS BEEN EDITED AND HAS A LIVE PROCESS")
- (modified-p
- "HAS BEEN EDITED")
- (process-p
- "HAS A LIVE PROCESS")
- (t "is unmodified")))))
- (cl-defun my/kill-some-buffers (&optional auto-unmod pred)
- "Improved version of `kill-some-buffers'.
- Ask the user weather to kill each visible buffer whose name is not in
- `my/kill-some-buffers-exclude-names'.
- When AUTO-UNMOD is non-nil, as it is with a prefix argument, automatically kill
- unmodified buffers, and then ask about the rest.
- When PRED is non-nil, it is a function that will be run in each buffer (not just
- visible ones). If it returns t, that buffer will be considered for killing. If
- PRED is nil, the value of `my/kill-some-buffers-default-pred' is used."
- (interactive "P")
- ;; we already ask, no need to do it again
- (let ((kill-buffer-query-functions nil)
- (all-action (when auto-unmod 'unmod))
- (had-valid-buffer)
- (ask-again-buffers)
- (to-kill))
- (cl-flet ((ask-about (buffer allow-unmod)
- (unless all-action
- (read-answer
- (my/kill-some-buffers-prompt-for buffer)
- `(("yes" ?y "save and kill this buffer")
- ("no" ?n "skip this buffer")
- ("all" ?! "save and kill all remaining buffers")
- ("nosave" ?l "kill this buffer without saving")
- ,@(when allow-unmod
- '(("unmod" ?a
- "kill unmodified buffers, ask about the rest")))
- ("quit" ?q "exit")))))
- (act-on (ans buffer allow-unmod)
- (when (equal ans "all")
- (setq all-action 'all))
- (when (and allow-unmod
- (equal ans "unmod"))
- (setq all-action 'unmod))
- (cond
- ((and (eq all-action 'unmod)
- (buffer-file-name buffer)
- (buffer-modified-p buffer))
- (push buffer ask-again-buffers))
- ((or (eq all-action 'all)
- (eq all-action 'unmod)
- (equal ans "yes"))
- (when (buffer-file-name buffer)
- (with-current-buffer buffer
- (save-buffer)))
- (push buffer to-kill))
- ((equal ans "nosave")
- (with-current-buffer buffer
- (set-buffer-modified-p nil))
- (push buffer to-kill))
- ;; Skip buffer
- ;; ((equal ans "no"))
- ((equal ans "quit")
- (cl-return-from my/kill-some-buffers)))))
- (dolist (buffer (buffer-list))
- (when (and (not (my/kill-some-buffers-excluded-buffer-p buffer))
- (funcall (or pred my/kill-some-buffers-default-pred) buffer))
- (setq had-valid-buffer t)
- (act-on (ask-about buffer t) buffer t)))
- (unless had-valid-buffer
- (message "Nothing to do..."))
- (setq all-action nil)
- (dolist (buffer ask-again-buffers)
- (act-on (ask-about buffer nil) buffer nil))
- ;; Do this last so that tty frames don't auto-close half way through
- (dolist (buffer to-kill)
- (kill-buffer buffer)))))
- (keymap-global-set "C-x K" 'my/kill-some-buffers)
- (use-package tab-bar
- :ensure nil
- :init
- (setq tab-bar-show 1
- tab-bar-tab-hints t
- icon-preference '(symbol text image emoji))
- (tab-bar-mode 1))
- ;; jinx (better flyspell)
- (use-package jinx
- :hook (emacs-startup . global-jinx-mode)
- :config
- (evil-define-key 'normal 'global
- "z=" #'jinx-correct))
- ;; recentf
- (use-package recentf
- :init
- (setq recentf-exclude `("^/tmp/.*"
- "^~/.mail/[^/]/Drafts/.*"
- ,(format "^%svar/elpa/.*" user-emacs-directory)
- ,(format "^%svar/elfeed/.*" user-emacs-directory)
- ,(format "^%svar/gnus/.*" user-emacs-directory)
- ,(format "^%svar/ellama-sessions/.*" user-emacs-directory)
- ,(format "^%setc/gnus/.*" user-emacs-directory)
- ,(format "^%svar/bookmark-default.el" user-emacs-directory)))
- :bind ("C-c r" . recentf)
- :config
- (recentf-mode 1))
- ;; bookmarks
- (use-package bookmark
- :ensure nil
- :bind ("C-c b" . my/bookmark-find-file)
- :config
- (defun my/bookmark-find-file (&optional name)
- "Run `find-file' in or on bookmark NAME.
- If NAME points to a directory, run `find-file' with `default-directory' in that
- directory. Otherwise, run `find-file' on that file."
- (interactive (list (bookmark-completing-read
- "Find file in" bookmark-current-bookmark)))
- (unless name
- (error "No bookmark specified"))
- (bookmark-maybe-historicize-string name)
- (when-let ((file (bookmark-get-filename name)))
- (if (file-directory-p file)
- (let ((default-directory (file-name-as-directory file)))
- (call-interactively 'find-file))
- (find-file file)))))
- ;; kitty keyboard protocol
- (use-package kkp
- :defer nil
- :config
- (global-kkp-mode 1)
- (defun my/-kkp-after-terminal-setup ()
- ;; Make tab and backtab work properly
- (define-key input-decode-map [(control ?i)] [tab])
- (define-key input-decode-map [(control ?I)] [backtab])
- (define-key input-decode-map [(control ?m)] [return]))
- (defun my/-kkp-after-terminal-teardown (term)
- (with-selected-frame (car (frames-on-display-list term))
- (define-key input-decode-map [(control ?i)] nil t)
- (define-key input-decode-map [(control ?I)] nil t)
- (define-key input-decode-map [(control ?m)] nil t)))
- (advice-add 'kkp--terminal-setup :after 'my/-kkp-after-terminal-setup)
- (advice-add 'kkp--terminal-teardown :after 'my/-kkp-after-terminal-teardown)
- (defun my/quoted-insert (arg)
- "Insert the next character using read-key, not read-char."
- (interactive "*p")
- ;; Source: https://github.com/benjaminor/kkp/issues/11
- (let ((char (read-key)))
- ;; Ensure char is treated as a character code for insertion
- (unless (characterp char)
- (user-error "%s is not a valid character"
- (key-description (vector char))))
- (when (numberp char)
- (while (> arg 0)
- (insert-and-inherit char)
- (setq arg (1- arg))))))
- (keymap-global-set "C-q" #'my/quoted-insert)
- (defun my/-kkp-fix-map-y-or-n-p (oldfun &rest args)
- "Fix `map-y-or-n-p' when used in a terminal with kkp enabled."
- (let ((status (kkp--terminal-has-active-kkp-p)))
- (condition-case err
- (progn
- (when status (kkp-disable-in-terminal))
- (apply oldfun args))
- (quit
- ;; We won't die in this case, so just re-enable kkp
- (when (and status (not (kkp--terminal-has-active-kkp-p)))
- (kkp-enable-in-terminal))
- (signal 'quit nil))
- (t
- (when (and status (not (kkp--terminal-has-active-kkp-p)))
- ;; this does async stuff that will make kitty send characters after
- ;; Emacs exits. We prevent that by not re-enabling if this frame (or
- ;; Emacs) is about to die
- (let ((will-die))
- (mapbacktrace
- (lambda (_evald func _args _flags)
- (when (or (eq func 'save-buffers-kill-emacs)
- (eq func 'server-save-buffers-kill-terminal))
- (setq will-die t))))
- (unless will-die
- (kkp-enable-in-terminal))))
- (when err
- (signal (car err) (cdr err)))))))
- (advice-add #'map-y-or-n-p :around
- #'my/-kkp-fix-map-y-or-n-p))
- ;; mozc
- (require 'mozc nil t)
- (setq default-input-method "japanese-mozc")
- ;; undo-tree
- (use-package undo-tree
- :defer nil
- :hook (undo-tree-visualizer-mode . my/-undo-tree-visualizer-mode-setup)
- :config
- (defun my/-undo-tree-visualizer-mode-setup ()
- (visual-line-mode -1)
- (setq truncate-lines t))
- (global-undo-tree-mode))
- ;; evil
- (use-package evil
- :init
- (setq evil-want-integration t
- evil-want-C-d-scroll nil
- evil-want-keybinding nil
- evil-undo-system 'undo-tree
- evil-search-module 'isearch
- evil-respect-visual-line-mode t)
- :config
- (evil-mode 1)
- (evil-define-key '(normal visual motion) proced-mode-map
- "u" #'proced-unmark)
- (evil-define-key '(normal visual motion) dired-mode-map
- "u" #'dired-unmark)
- (evil-define-key '(normal visual motion) profiler-report-mode-map
- (kbd "TAB") #'profiler-report-toggle-entry)
- (eldoc-add-command 'evil-insert
- 'evil-append
- 'evil-insert-line
- 'evil-append-line))
- (use-package evil-collection
- :after evil
- :diminish evil-collection-unimpaired-mode
- :config
- (evil-collection-init))
- (use-package evil-surround
- :after evil
- :config
- (evil-define-key 'operator evil-surround-mode-map
- "z" #'evil-surround-edit
- "Z" #'evil-Surround-edit)
- (evil-define-key 'visual evil-surround-mode-map
- "gz" #'evil-surround-region
- "gZ" #'evil-Surround-region)
- (global-evil-surround-mode 1))
- (use-package evil-terminal-cursor-changer
- :after evil
- :config
- (evil-terminal-cursor-changer-activate))
- (use-package evil-numbers
- :after evil
- :bind (("C-c =" . evil-numbers/inc-at-pt)
- ("C-c +" . evil-numbers/inc-at-pt)
- ("C-c -" . evil-numbers/dec-at-pt)
- ("C-c C-=" . evil-numbers/inc-at-pt-incremental)
- ("C-c C-+" . evil-numbers/inc-at-pt-incremental)
- ("C-c C--" . evil-numbers/dec-at-pt-incremental)))
- (use-package evil-cleverparens
- :hook ((prog-mode . my/-enable-evil-cleverparens)
- (evil-cleverparens-mode . paredit-mode))
- :bind (:map paredit-mode-map
- ("C-<return>" . paredit-RET)
- ("C-RET" . paredit-RET)
- :map evil-cleverparens-mode-map
- ("C-c o" . evil-cp-open-below-form))
- :custom
- (evil-cleverparens-use-s-and-S nil)
- :config
- (eldoc-add-command 'paredit-RET
- 'paredit-open-round
- 'paredit-open-angled
- 'paredit-open-bracket
- 'paredit-open-angled
- 'paredit-open-parenthesis
- 'delete-indentation
- 'evil-cp-insert
- 'evil-cp-append
- 'evil-cp-insert-at-beginning-of-form
- 'evil-cp-insert-at-end-of-form)
- (keymap-unset evil-cleverparens-mode-map "<normal-state> M-o" t)
- (defun my/-enable-evil-cleverparens ()
- (if (member major-mode '(lisp-mode emacs-lisp-mode
- lisp-interaction-mode))
- (evil-cleverparens-mode 1)
- (electric-pair-local-mode 1)))
- (cl-defun my/range-inside-thing-p (thing beg end &optional no-edge)
- "Return non-nil if BEG and END fall inside the bounds of THING.
- With NO-EDGE, return nil if beg or end fall on the edge of the range."
- (save-excursion
- ;; this fixes that fact that `thing-at-point-bounds-of-string-at-point'
- ;; errors if called at the end of the buffer
- (condition-case nil
- (let ((sb (progn (goto-char beg) (bounds-of-thing-at-point thing)))
- (eb (progn (goto-char end) (bounds-of-thing-at-point thing))))
- (and sb eb (equal sb eb)
- (or (not no-edge)
- (and (/= beg (car sb))
- (< beg (cdr sb))
- (/= end (car sb))
- (< end (cdr sb))))))
- ;; if the error happens, we aren't in a string
- (wrong-type-argument nil))))
- (defun my/-evil-cp-region-ok-p-no-string (oldfun beg end)
- (or
- (and (sp-point-in-comment beg)
- (sp-point-in-comment end))
- (and (sp-point-in-string beg)
- (sp-point-in-string end)
- (my/range-inside-thing-p 'string beg end t))
- (funcall oldfun beg end)))
- (defun my/column-num-at-pos (pos)
- "Return the column number at POS."
- (save-excursion
- (goto-char pos)
- (current-column)))
- (defun my/-evil-cp-block-ok-p-no-string (oldfun beg end)
- (when (> beg end) (cl-rotatef beg end))
- (or
- (save-excursion
- (goto-char beg)
- (let ((start-off (current-column))
- (end-off (my/column-num-at-pos end)))
- (cl-block nil
- (dotimes (_ (count-lines beg end) t)
- (let ((bol (pos-bol)))
- (unless (sp-region-ok-p (+ bol start-off)
- (+ bol end-off))
- (cl-return))
- (forward-line))))))
- (funcall oldfun beg end)))
- (advice-add 'sp-region-ok-p :around 'my/-evil-cp-region-ok-p-no-string)
- (advice-add 'evil-cp--balanced-block-p :around 'my/-evil-cp-block-ok-p-no-string))
- ;; better lisp editing
- (use-package adjust-parens
- :hook (prog-mode . adjust-parens-mode)
- :config
- (defun my/lisp-indent-adjust-parens ()
- "Like `lisp-indent-adjust-parens', but got to first char on line first.
- Also, this works even if the region is active (it indents every line in the
- region)."
- (interactive)
- (save-mark-and-excursion
- (let ((end (mark t))
- (line-count 1)
- (indent-cols))
- (when (and (region-active-p) end)
- (setq mark-active nil
- line-count (count-lines (point) end))
- (when (> (point) end)
- (let ((start (point)))
- (goto-char end)
- (setq end start))))
- ;; find the indentation column of each line
- (save-excursion
- (dotimes (_ line-count)
- (back-to-indentation)
- (push (- (point) (pos-bol)) indent-cols)
- (forward-line))
- (cl-callf nreverse indent-cols))
- (cl-loop repeat line-count
- for indent-col in indent-cols
- for bol = (pos-bol)
- do (back-to-indentation)
- ;; skip this line if the indentation has changed
- when (= (- (point) bol) indent-col) do
- (lisp-indent-adjust-parens)
- ;; if the indent failed, stop
- (when (= (- (point) bol) indent-col)
- (cl-return))
- do (forward-line)))))
- (defun my/lisp-dedent-adjust-parens ()
- "Like `lisp-dedent-adjust-parens', but got to first char on line first.
- Also, this works even if the region is active (it just jumps to the first line
- in the region and indents once)."
- (interactive)
- (save-mark-and-excursion
- (let ((end (mark t)))
- (when (and (region-active-p) end)
- (setq mark-active nil)
- (when (> (point) end)
- (goto-char end))))
- (back-to-indentation)
- (lisp-dedent-adjust-parens)))
- (eldoc-add-command 'my/lisp-indent-adjust-parens
- 'my/lisp-dedent-adjust-parens
- 'lisp-indent-adjust-parens
- 'lisp-dedent-adjust-parens)
- (evil-define-key '(normal visual) adjust-parens-mode-map
- (kbd "<tab>") #'my/lisp-indent-adjust-parens
- (kbd "<backtab>") #'my/lisp-dedent-adjust-parens))
- ;; for when the files are just too large
- (use-package vlf
- :demand t
- :config
- (require 'vlf-setup))
- ;; allow copy from terminal
- (use-package xclip
- :config
- (setq xclip-method 'wl-copy
- xclip-program (symbol-name xclip-method))
- (xclip-mode 1)
- (defun my/-xclip-detect-wl-paste-error (oldfun type)
- (if (eq xclip-method 'wl-copy)
- ;; Direct from `xclip-get-selection'
- (when (and (getenv "WAYLAND_DISPLAY")
- (memq type '(clipboard CLIPBOARD primary PRIMARY)))
- (let* ((exit-code 0)
- (output
- (with-output-to-string
- (setq exit-code
- (apply #'call-process (replace-regexp-in-string
- "\\(.*\\)copy" "\\1paste"
- xclip-program 'fixedcase)
- nil standard-output nil
- "-n" (if (memq type '(primary PRIMARY))
- '("-p")))))))
- (if (zerop exit-code)
- output
- "")))
- (funcall oldfun type)))
- (advice-add 'xclip-get-selection :around 'my/-xclip-detect-wl-paste-error))
- ;; which-key
- (use-package which-key
- :diminish which-key-mode
- :config
- (which-key-mode 1))
- ;; avy
- (use-package avy
- :bind (("C-c C-j" . avy-resume)
- ("M-s s" . evil-avy-goto-char-2)
- ("M-s S" . evil-avy-goto-line))
- :init
- (define-minor-mode my/evil-avy-mode
- "A minor mode for binding avy commands to s and S in evil's normal and
- visual states."
- :keymap (make-sparse-keymap))
- (evil-define-key '(normal visual operator motion) my/evil-avy-mode-map
- "s" #'evil-avy-goto-char-2
- "S" #'evil-avy-goto-line)
- (define-globalized-minor-mode my/evil-avy-global-mode my/evil-avy-mode
- (lambda () (my/evil-avy-mode 1))
- :predicate '((not magit-mode dired-mode
- proced-mode mu4e-main-mode
- mu4e-view-mode mu4e-headers-mode
- ibuffer-mode calc-mode calc-trail-mode
- gnus-group-mode) t))
- (my/evil-avy-global-mode 1)
- :config
- (avy-setup-default))
- ;; ace-window
- (use-package ace-window
- :diminish ace-window-mode
- :bind ("M-o" . ace-window)
- :init
- (setq aw-scope 'frame
- aw-minibuffer-flag t))
- ;; savehist
- (use-package savehist
- :config
- (savehist-mode 1))
- ;; vertico
- (use-package vertico
- :bind (:map vertico-map
- ("C-RET" . vertico-exit-input)
- ("C-<return>" . vertico-exit-input)
- ("C-S-k" . kill-line)
- ("C-k" . vertico-previous)
- ("C-j" . vertico-next)
- ("RET" . vertico-directory-enter)
- ("DEL" . vertico-directory-delete-char)
- ("M-DEL" . vertico-directory-delete-word))
- :hook (minibuffer-setup . cursor-intangible-mode)
- :init
- (defun my/crm-indicator (args)
- (cons (format "[CRM%s] %s"
- (replace-regexp-in-string
- "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
- crm-separator)
- (car args))
- (cdr args)))
- (advice-add #'completing-read-multiple :filter-args #'my/crm-indicator)
- (setq vertico-cycle t
- enable-recursive-minibuffers t
- ;; read-extended-command-predicate #'command-completion-default-include-p
- read-extended-command-predicate nil
- minibuffer-prompt-properties '(read-only t ;; noindent 3
- cursor-intangible t
- face minibuffer-prompt))
- (vertico-mode 1)
- ;; for jinx
- (require 'vertico-multiform)
- (add-to-list 'vertico-multiform-categories
- '(jinx grid (vertico-grid-annotate . 20)))
- (vertico-multiform-mode 1))
- ;; orderless
- (use-package orderless
- :autoload orderless-define-completion-style
- :hook (text-mode . my/-setup-text-mode-completion-styles)
- :init
- (defun my/-setup-text-mode-completion-styles ()
- (setq-local completion-styles '(basic)))
- (orderless-define-completion-style my/orderless-with-initialism
- (orderless-matching-styles '(orderless-initialism
- orderless-regexp)))
- (setq orderless-matching-styles '(orderless-regexp)
- completion-styles '(orderless basic)
- completion-category-defaults nil
- completion-category-overrides '((file
- (styles basic partial-completion))
- (command
- (styles my/orderless-with-initialism basic)))))
- ;; marginalia
- (use-package marginalia
- :bind (:map minibuffer-local-map
- ("M-a" . marginalia-cycle))
- :init
- (marginalia-mode 1))
- ;; embark
- (use-package embark
- :bind (("C-," . embark-act)
- ("C-;" . embark-dwim)
- :map help-map
- ("B" . embark-bindings)
- :map embark-symbol-map
- ("h" . helpful-symbol)
- :map embark-become-file+buffer-map
- ("b" . consult-buffer)
- ("B" . switch-to-buffer))
- :init
- (setq embark-quit-after-action nil
- embark-indicators '(embark-minimal-indicator
- embark-isearch-highlight-indicator
- embark-highlight-indicator))
- :config
- (defvar-keymap my/embark-string-map
- :doc "Keymap for Embark string actions."
- :parent embark-expression-map
- "R" 'repunctuate-sentences)
- (defun my/embark-target-string ()
- "Target the string at point."
- (if-let (((not (eobp))) ; prevent next line from causing errors
- (bounds (bounds-of-thing-at-point 'string)))
- (append (list 'string (buffer-substring-no-properties (car bounds)
- (cdr bounds)))
- bounds)))
- (add-to-list 'embark-around-action-hooks
- '(repunctuate-sentences embark--mark-target))
- (add-to-list 'embark-keymap-alist
- '(string my/embark-string-map))
- (add-to-list 'embark-target-finders 'my/embark-target-string)
- (add-to-list 'display-buffer-alist
- '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
- nil
- (window-parameters (mode-line-format . none))))
- (evil-define-key '(normal motion) org-mode-map
- (kbd "C-,") #'embark-act))
- ;; consult
- (use-package consult
- :bind (("C-s" . consult-line)
- ("C-x b" . consult-buffer)
- ("C-S-s" . consult-ripgrep)
- ("C-x C-S-f" . consult-fd)
- ("C-x c k" . consult-keep-lines)
- ("C-x c f" . consult-focus-lines)
- ("C-x c r" . consult-recent-file)
- ("C-x c b" . consult-bookmark)
- ("C-x c d" . consult-fd)
- ("C-x c g" . consult-ripgrep)
- ("C-x c y" . consult-yank-from-kill-ring)
- ("M-g i" . consult-imenu)
- ("M-g I" . consult-imenu-multi)
- ("M-g r" . consult-imenu-multi)
- :map help-map
- ("TAB". consult-info)
- ("C-m" . consult-man))
- :hook (minibuffer-setup . my/consult-setup-minibuffer-completion)
- :init
- (defun my/consult-setup-minibuffer-completion ()
- (setq-local completion-in-region-function #'consult-completion-in-region))
- (evil-declare-motion #'consult-line))
- (use-package consult-eglot
- :commands consult-eglot-symbols)
- ;; wgrep
- (use-package wgrep)
- ;; integration for embark and consult
- (use-package embark-consult
- :hook (embark-collect-mode . consult-preview-at-point-mode))
- ;; corfu (autocomplete)
- (use-package corfu
- :bind (("M-<tab>" . completion-at-point)
- :map corfu-map
- ("C-j" . corfu-next)
- ("C-k" . corfu-previous)
- ("M-SPC" . corfu-insert-separator)
- ("M-m" . my/corfu-move-to-minibuffer))
- :init
- (defun my/corfu-move-to-minibuffer ()
- (interactive)
- (when completion-in-region--data
- (let ((completion-extra-properties corfu--extra)
- (completion-cycle-threshold completion-cycling))
- (apply #'consult-completion-in-region completion-in-region--data))))
- (setq corfu-cycle t
- corfu-auto t
- corfu-on-exact-match nil
- corfu-popupinfo-delay '(1.0 . 0.5)
- completion-cycle-threshold nil
- global-corfu-minibuffer
- ;; only enable corfu in the minibuffer in graphical frames
- (lambda ()
- (and (display-graphic-p)
- (not (eq (current-local-map)
- read-passwd-map)))))
- (global-corfu-mode 1)
- (corfu-popupinfo-mode 1)
- :config
- (add-to-list 'corfu-continue-commands #'my/corfu-move-to-minibuffer)
- (defun my/help-buffer-exists-p ()
- "Return if the buffer that `help-buffer' would, or nil if it doesn't exist."
- (or (and help-xref-following (derived-mode-p 'help-mode))
- (get-buffer "*Help*")))
- (defun my/-corfu-popupinfo-close-help-buffer (oldfun &rest args)
- (if (derived-mode-p 'emacs-lisp-mode)
- (let ((help-buf (my/help-buffer-exists-p)))
- (prog1
- (apply oldfun args)
- (when-let (((not help-buf))
- (buf (help-buffer)))
- ;; Ensure that, even if `help-buffer' returns nil in the future, we
- ;; don't kill the current buffer
- (kill-buffer buf))))
- (apply oldfun args)))
- (advice-add 'corfu-popupinfo--get-documentation :around
- 'my/-corfu-popupinfo-close-help-buffer))
- (use-package corfu-terminal
- :init
- (corfu-terminal-mode 1)
- :config
- (require 'corfu-terminal-popupinfo)
- (corfu-terminal-popupinfo-mode 1))
- (use-package dabbrev
- :ensure nil
- :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))
- ;; cape (a bunch of capfs!)
- (use-package cape
- :bind (("C-c p" . cape-dabbrev)
- ([remap dabbrev-expand] . cape-dabbrev)
- ("C-c P" . cape-line)
- ("C-c f" . cape-file))
- :hook (text-mode . my/-cape-setup-text-mode)
- :init
- (defun my/-cape-setup-text-mode ()
- ;; Only run this if we are not in `TeX-mode'
- (unless (bound-and-true-p TeX-mode-p)
- (setq-local completion-at-point-functions
- (append completion-at-point-functions (list 'cape-dict
- 'cape-dabbrev))
- corfu-auto nil))))
- ;; xref
- (use-package xref
- :init
- (evil-define-key '(normal motion) 'global
- "gr" #'xref-find-references)
- (setq xref-show-xrefs-function #'consult-xref
- xref-show-definitions-function #'consult-xref))
- ;; popup.el
- (use-package popup)
- ;; posframe
- (use-package posframe
- :init
- (defun my/posframe-tip (name msg)
- "Like `popup-tip', but with a posframe.
- NAME should be the buffer name to pass to `posframe-show'. MSG is the message to
- display."
- (unwind-protect
- (progn
- (posframe-show name
- :string msg
- :position (point)
- :max-width 80
- :border-width 2
- :border-color "white")
- (clear-this-command-keys)
- (push (read-event) unread-command-events)
- (posframe-hide name))
- (posframe-hide name))))
- (defun my/floating-tooltip (name msg)
- "If `display-graphic-p', call `my/posframe-tip', otherwise `popup-tip'.
- MSG is the message to show in the popup. NAME is the name of the buffer to pass
- to `posframe-show' if the display is graphical."
- (if (display-graphic-p)
- (my/posframe-tip name msg)
- (popup-tip msg)))
- ;; flymake
- (use-package flymake
- :config
- (require 'consult-flymake))
- ;; flycheck
- (use-package flycheck
- :hook ((sh-mode emacs-lisp-mode) . flycheck-mode)
- :custom
- (flycheck-indication-mode 'left-margin)
- :init
- (setq flycheck-display-errors-function nil))
- (use-package consult-flycheck)
- (defun my/sly-notes-at-point (&optional pos buffer)
- "Return the sly notes at POS in BUFFER.
- If BUFFER is nil, the current buffer is used."
- (with-current-buffer (or buffer (current-buffer))
- (unless pos
- (setq pos (point)))
- (cl-loop for overlay in (overlays-at pos)
- for note = (overlay-get overlay 'sly-note)
- when note
- collect note)))
- (defun my/diagnostic-at-point ()
- "Show the diagnostics under point."
- (interactive)
- (let ((message))
- (when-let (((bound-and-true-p flymake-mode))
- (diag (get-char-property (point) 'flymake-diagnostic)))
- (cl-callf nconc message (string-split (flymake--diag-text diag) "\n" t)))
- (when (bound-and-true-p flycheck-mode)
- (cl-callf nconc message
- (mapcar 'flycheck-error-message (flycheck-overlay-errors-at (point)))))
- ;; sly (lazy-loaded)
- (when (featurep 'sly)
- (cl-callf nconc message (mapcar (lambda (note)
- (plist-get note :message))
- (my/sly-notes-at-point))))
- ;; jinx
- (when-let (((bound-and-true-p jinx-mode))
- (jinx-msg (jinx--get-overlays (point) (1+ (point)))))
- (push "misspelled word" message))
- (when message
- (my/floating-tooltip " *my-diagnostic-posframe*"
- (mapconcat (lambda (msg)
- (concat "•" msg))
- message "\n")))))
- (defconst my/consult-flymake-flycheck-narrow
- '((?e . "Error")
- (?w . "Warning")
- (?i . "Info")
- (?n . "Info")))
- (defun my/-consult-replace-flymake-error-level (candidates)
- "Return CANDIDATES with the flymake error level note replaced with info."
- (cl-loop for cand in candidates
- collect
- (cl-loop
- with start = nil
- for i below (length cand)
- for props = (text-properties-at i cand)
- for face = (plist-get props 'face)
- when (eq face 'compilation-info) do
- (setq start (or start i))
- else when start do
- (setf (substring cand start i)
- (propertize (string-pad "info" (- i start))
- 'face (flycheck-error-level-error-list-face
- 'info)))
- (cl-return cand)
- finally return cand)))
- (defun my/consult-flymake-flycheck-candidates (&optional project)
- "Return combined candidate list for flymake and flycheck.
- With PROJECT, return the candiadeets for that project."
- (let ((had-errors))
- (prog1
- (seq-uniq
- (append
- (when-let (((bound-and-true-p flymake-mode))
- (diags (if project (flymake--project-diagnostics
- project)
- (flymake-diagnostics))))
- (setq had-errors t)
- (my/-consult-replace-flymake-error-level
- (consult-flymake--candidates diags)))
- (when (boundp 'flycheck-mode)
- (if project
- (cl-loop for buf in (project-buffers project)
- append
- (with-current-buffer buf
- (when (and flycheck-mode flycheck-current-errors)
- (setq had-errors t)
- (consult-flycheck--candidates))))
- (when (and flycheck-mode flycheck-current-errors)
- (setq had-errors t)
- (consult-flycheck--candidates))))))
- (unless had-errors
- (user-error "No errors (Flymake: %s | Flycheck: %s)"
- (cond
- ((not (bound-and-true-p flymake-mode))
- "not running")
- ((seq-difference (flymake-running-backends)
- (flymake-reporting-backends))
- "running")
- (t "finished"))
- (if (boundp 'flycheck-last-status-change)
- flycheck-last-status-change
- "not running"))))))
- (defun my/consult-flymake-flycheck (&optional project)
- "Jump to flymake or flycheck error.
- With PROJECT, give diagnostics for all buffers in the current project."
- (interactive "P")
- (consult--read
- (consult--with-increased-gc
- (my/consult-flymake-flycheck-candidates
- (and project (project-current))))
- :prompt "Error: "
- :category 'flymake-flycheck-error
- :history t
- :require-match t
- :sort nil
- :narrow (consult--type-narrow my/consult-flymake-flycheck-narrow)
- :group (consult--type-group my/consult-flymake-flycheck-narrow)
- :lookup #'consult--lookup-candidate
- :state (consult--jump-state)))
- (with-eval-after-load 'flymake
- (keymap-set flymake-mode-map "C-c e" 'my/diagnostic-at-point)
- (keymap-set flymake-mode-map "C-c E" 'my/consult-flymake-flycheck))
- (with-eval-after-load 'flycheck
- (keymap-set flycheck-mode-map "C-c e" 'my/diagnostic-at-point)
- (keymap-set flycheck-mode-map "C-c E" 'my/consult-flymake-flycheck))
- (with-eval-after-load 'jinx
- (keymap-set jinx-mode-map "C-c e" 'my/diagnostic-at-point))
- ;; eldoc
- (use-package eldoc
- :diminish eldoc-mode
- :init
- (setq-default eldoc-echo-area-use-multiline-p nil))
- ;; eglot
- (use-package eglot
- :demand t
- :pin gnu ;; try to force Elpa version to fix warnings
- :hook ((eglot-managed-mode . my/-eglot-setup))
- :init
- ;; (defun my/eglot-in-text-mode-only ()
- ;; (when (eq major-mode 'text-mode)
- ;; (eglot-ensure)))
- (defvar my/-eglot-documentation-buffer nil
- "Buffer for showing documentation for `my/eglot-documentation-at-point'.")
- (defun my/eglot-documentation-at-point ()
- "Show documentation for a symbol at point."
- (interactive)
- (if-let (server (eglot-current-server))
- (progn
- (if-let* (((not (buffer-live-p my/-eglot-documentation-buffer)))
- (name (generate-new-buffer-name "*eglot documentation*")))
- (setq my/-eglot-documentation-buffer (generate-new-buffer name)))
- (eglot-hover-eldoc-function
- (lambda (info _ _)
- (if-let (((not (seq-empty-p info)))
- (buff (current-buffer)))
- (with-current-buffer my/-eglot-documentation-buffer
- (read-only-mode -1)
- (erase-buffer)
- (insert info)
- (goto-char (point-min))
- (special-mode)
- (read-only-mode 1)
- (when (not (get-buffer-window my/-eglot-documentation-buffer nil))
- (switch-to-buffer-other-window my/-eglot-documentation-buffer t)
- (switch-to-buffer-other-window buff t)))))))))
- (defun my/-eglot-cleanup-doc-buffer (_server &optional _interactive _timeout
- preserve-buffers)
- (when (and (not preserve-buffers)
- (buffer-live-p my/-eglot-documentation-buffer)
- (cl-every (lambda (buffer)
- (with-current-buffer buffer
- (let ((server (eglot-current-server)))
- (or (not (eglot-lsp-server-p server))
- (eglot--shutdown-requested server)))))
- (buffer-list)))
- (kill-buffer my/-eglot-documentation-buffer)))
- (advice-add 'eglot-shutdown :after 'my/-eglot-cleanup-doc-buffer)
- (defun my/-eglot-setup ()
- "Setup eldoc variables for `eglot-managed-mode-hook'."
- (setq-local evil-lookup-func #'my/eglot-documentation-at-point)
- (evil-define-key '(normal motion) 'local
- "K" #'evil-lookup
- "gR" #'eglot-rename
- "gA" #'eglot-code-actions
- "gs" #'consult-eglot-symbols)
- (eglot-inlay-hints-mode -1))
- (setq eglot-autoshutdown t)
- :config
- (add-to-list 'eglot-server-programs
- (cons '(c-mode c-ts-mode c++-mode c++-ts-mode objc-mode)
- '("clangd" "--all-scopes-completion" "--background-index"
- "--clang-tidy" "--completion-style=detailed"
- "--header-insertion=never" "--pch-storage=memory"
- "--function-arg-placeholders"))))
- ;; LTeX (languagetool)
- (require 'ltex-eglot)
- ;; gud
- (use-package gud
- :demand t
- :ensure nil
- :after (project evil)
- :bind (:map project-prefix-map
- ("U" . my/project-gdb))
- :config
- (setq gdb-debuginfod-enable-setting t)
- (defvar my/project-gdb-command nil
- "Command to use in `my/project-gdb'.")
- (put 'my/project-gdb-command 'safe-local-variable (lambda (val)
- (stringp val)))
- (defun my/project-gdb (project command-line)
- "Run gdb in the project root"
- (interactive (let* ((project (project-current t))
- (default-directory (project-root project)))
- (list project (gud-query-cmdline 'gdb))))
- (let ((default-directory (project-root project)))
- (gdb command-line)))
- (evil-set-initial-state 'gdb-locals-mode 'motion)
- (evil-collection-inhibit-insert-state 'gdb-locals-mode-map)
- (evil-define-key '(normal motion visual) gdb-locals-mode-map
- (kbd "TAB") (keymap-lookup gdb-locals-mode-map "TAB")
- (kbd "RET") #'gdb-edit-locals-value
- (kbd "<mouse-1>") #'gdb-edit-locals-value
- "q" #'kill-current-buffer)
- (evil-set-initial-state 'gdb-registers-mode 'motion)
- (evil-collection-inhibit-insert-state 'gdb-registers-mode-map)
- (evil-define-key '(normal motion visual) gdb-registers-mode-map
- (kbd "TAB") (keymap-lookup gdb-registers-mode-map "TAB")
- (kbd "RET") #'gdb-edit-register-value
- (kbd "<mouse-1>") #'gdb-edit-register-value
- "q" #'kill-current-buffer
- (kbd "C-c f") #'gdb-registers-toggle-filter
- (kbd "C-c F") (lambda ()
- "Customize the filter for the registers buffer."
- (interactive)
- (customize-option-other-window
- 'gdb-registers-filter-pattern-list)))
- (evil-set-initial-state 'gdb-frames-mode 'motion)
- (evil-collection-inhibit-insert-state 'gdb-frames-mode-map)
- (evil-define-key '(normal motion visual) gdb-frames-mode-map
- "q" #'kill-current-buffer
- (kbd "RET") #'gdb-select-frame)
- (evil-set-initial-state 'gdb-breakpoints-mode 'motion)
- (evil-collection-inhibit-insert-state 'gdb-breakpoints-mode-map)
- (evil-define-key '(normal motion visual) gdb-breakpoints-mode-map
- (kbd "TAB") (keymap-lookup gdb-breakpoints-mode-map "TAB")
- "q" #'gdb-delete-frame-or-window
- "D" #'gdb-delete-breakpoint
- (kbd "RET") #'gdb-goto-breakpoint
- (kbd "<mouse-1>") #'gdb-goto-breakpoint
- (kbd "SPC") #'gdb-toggle-breakpoint)
- (evil-set-initial-state 'gdb-threads-mode 'motion)
- (evil-collection-inhibit-insert-state 'gdb-threads-mode-map)
- (evil-define-key '(normal motion visual) gdb-threads-mode-map
- (kbd "TAB") (keymap-lookup gdb-threads-mode-map "TAB")
- "q" #'gdb-delete-frame-or-window
- "D" #'gdb-frame-disassembly-for-thread
- (kbd "C-c f") #'gdb-display-stack-for-thread
- (kbd "C-c i") #'gdb-interrupt-thread
- (kbd "C-c l") #'gdb-display-locals-for-thread
- (kbd "C-c r") #'gdb-display-registers-for-thread
- (kbd "C-c c") #'gdb-continue-thread
- (kbd "C-c d") #'gdb-display-disassembly-for-thread
- (kbd "C-c s") #'gdb-step-thread
- (kbd "C-c F") #'gdb-frame-stack-for-thread
- (kbd "C-c L") #'gdb-frame-locals-for-thread
- (kbd "C-c R") #'gdb-frame-registers-for-thread
- (kbd "RET") #'gdb-select-thread
- (kbd "<mouse-2>") #'gdb-select-thread))
- ;; dape
- (use-package dape
- :hook ((after-init . dape-breakpoint-load)
- (kill-emacs . dape-breakpoint-save)
- (dape-start . save-some-buffers)
- (dape-display-source . pulse-momentary-highlight-one-line))
- :bind (:map dape-info-parent-mode-map
- ("<tab>" . dape--info-buffer-tab))
- :init
- (setopt dape-default-breakpoints-file (no-littering-expand-var-file-name
- "dape-breakpoints"))
- :config
- (setopt dape-buffer-window-arrangement 'right)
- (dape-breakpoint-global-mode 1))
- ;; dumb-jump
- (use-package dumb-jump
- :init
- (add-hook 'xref-backend-functions #'dumb-jump-xref-activate))
- ;; yasnippet
- (use-package yasnippet
- :demand t
- :bind ("C-c s" . yas-expand)
- :config
- (yas-global-mode 1))
- ;; project.el
- (use-package project
- :bind (("C-c v" . my/project-eshell-or-default)
- ([remap project-compile] . my/project-compile-or-default)
- :map project-prefix-map
- ("s" . my/project-eshell)
- ("u" . my/project-run))
- :init
- (defvar eshell-buffer-name)
- (defun my/project-eshell (prompt &optional arg)
- "Switch to or create an eshell buffer in the current projects root."
- (interactive (list t current-prefix-arg))
- (if-let ((proj (project-current prompt))
- (default-directory (project-root proj))
- (eshell-buffer-name
- (concat "*eshell for project " default-directory "*")))
- (eshell arg)))
- (defun my/project-eshell-or-default (&optional arg)
- "Open an eshell for the current project, otherwise, open a normal eshell."
- (interactive "P")
- (unless (my/project-eshell nil arg)
- (eshell arg)))
- (defun my/project-compile-or-default ()
- "If in a project, run `project-compile', otherwise run `compile'."
- (interactive)
- (if (project-current)
- (call-interactively 'project-compile)
- (call-interactively 'compile)))
- (defvar my/project-run-command nil
- "Command to run with `my/project-run'.")
- (put 'my/project-run-command 'safe-local-variable (lambda (val)
- (stringp val)))
- (defvar my/project-run-dir nil
- "Directory to run project in with `my/project-run'.")
- (put 'my/project-run-dir 'safe-local-variable (lambda (val)
- (stringp val)))
- (defvar my/-project-run-history '()
- "Commands previously run with `my/project-run'")
- (defvar my/project-root-marker ".project-root"
- "Marker file to look for in non-vc backed projects.")
- (defun my/project-get-root-dir ()
- "Get the root dir for the current project"
- (let* ((proj (project-current nil))
- (default-directory (if proj
- (project-root proj)
- default-directory)))
- (if my/project-run-dir
- (expand-file-name my/project-run-dir)
- default-directory)))
- (defun my/project-run (command comint)
- "Like `project-compile', but for running a project.
- COMMAND and COMINT are like `compile'."
- (interactive
- (list
- (let ((default-directory (my/project-get-root-dir)))
- (read-shell-command "Run Command: "
- (or (car my/-project-run-history)
- my/project-run-command)
- (if (and my/project-run-command
- (equal my/project-run-command
- (car-safe my/-project-run-history)))
- '(my/-project-run-history . 1)
- 'my/-project-run-history)))
- (consp current-prefix-arg)))
- (let* ((default-directory (my/project-get-root-dir))
- (compilation-buffer-name-function (lambda (_)
- (progn "*run project*")))
- (compilation-directory default-directory)
- (compile-history nil)
- (compile-command nil))
- (compile command comint)
- (when (not my/project-run-command)
- (setq my/project-run-command command))))
- :config
- (defun my/project-try-dotfile (dir)
- (if-let (root (locate-dominating-file dir my/project-root-marker))
- (list 'vc nil root)))
- (add-hook 'project-find-functions #'my/project-try-dotfile))
- ;; nxml
- (use-package nxml-mode
- :ensure nil
- :hook (nxml-mode . my/-nxml-setup)
- :init
- (defun my/-nxml-setup ()
- "Setup `nxml-mode'."
- (sgml-electric-tag-pair-mode 1)
- (setq-local completion-at-point-functions
- '(rng-completion-at-point cape-file)))
- (add-to-list 'auto-mode-alist
- `(,(concat
- (regexp-opt '("gschema" "gresource" "ui")) "\\'")
- . nxml-mode)))
- ;; Bibtex (built in)
- (require 'bibtex)
- (defun my/bibtex-in-entry-p (&optional exclude-braces)
- "Return t is point is inside a BibTeX entry.
- When EXCLUDE-BRACES is non-nil, don't count the first and last brace of the
- entry as in the entry. That is, if the point is on the first { or last } of the
- entry, return nil."
- (save-excursion
- (when (and exclude-braces (eq ?\} (char-after)))
- (forward-char))
- ;; go to top level and check if the character at point is {
- (let ((start-pos (point))
- (last-valid (point)))
- (condition-case nil
- (while t
- (backward-up-list 1 t t)
- (setq last-valid (point)))
- (error
- (and
- (eq ?\{ (char-after last-valid))
- (or (not exclude-braces)
- (not (= start-pos last-valid)))))))))
- (defvar my/bibtex-indent-width 4
- "Width to indent for `my/bibtex-calculate-indentation'.")
- (defun my/bibtex-calculate-indentation ()
- "Calculate the column to indent to on the current line."
- (save-excursion
- (back-to-indentation)
- (if (my/bibtex-in-entry-p t)
- my/bibtex-indent-width
- 0)))
- (defun my/bibtex-empty-line-p ()
- "Return t if the current line is only blank characters."
- (save-excursion
- (beginning-of-line)
- (looking-at (rx (* blank) eol))))
- (defun my/bibtex-indent-line ()
- "Indent the current line."
- (interactive)
- (save-excursion
- (beginning-of-line)
- (when (looking-at (rx (+ blank)))
- (delete-region (point) (match-end 0)))
- (indent-to (my/bibtex-calculate-indentation)))
- (when (looking-at (rx (+ blank) eol))
- (end-of-line)))
- (defun my/bibtex-indent-or-find-text ()
- "Either indent the current line or jump to the current fields text.
- If the current line is only whitespace call `my/bibtex-calculate-indentation',
- otherwise, call `bibtex-find-text'."
- (interactive)
- (if (my/bibtex-empty-line-p)
- (my/bibtex-indent-line)
- (bibtex-find-text)))
- (defun my/bibtex-indent-or-find-text-and-insert ()
- "Like `my/bibtex-indent-or-find-text', but enter insert mode after."
- (interactive)
- (my/bibtex-indent-or-find-text)
- (if (my/bibtex-empty-line-p)
- (evil-append 1)
- (evil-insert 1)))
- (defun my/-bibtex-setup-indent ()
- "Set up `bibtex-mode' indentation stuff."
- (setq-local indent-line-function 'my/bibtex-indent-line
- electric-indent-chars '(?\n ?\{ ?\} ?,)))
- (defun my/-bibtex-fix-fill-prefix ()
- "`bivtex-mode' has a bad habbit of messing up `fill-prefix'."
- (when (eq major-mode 'bibtex-mode)
- (setq-local fill-prefix nil)))
- (advice-add 'bibtex-mode :after 'my/-bibtex-fix-fill-prefix)
- (add-hook 'bibtex-mode-hook 'my/-bibtex-setup-indent)
- (keymap-set bibtex-mode-map "RET" 'newline-and-indent)
- (keymap-set bibtex-mode-map "TAB" 'my/bibtex-indent-or-find-text)
- (evil-define-key 'normal bibtex-mode-map
- (kbd "TAB") 'my/bibtex-indent-or-find-text-and-insert)
- ;; Latex help (from elisp file)
- (require 'latex-help)
- ;; AUCTeX
- (use-package auctex
- :hook ((LaTeX-mode . turn-on-reftex)
- (LaTeX-mode . LaTeX-math-mode)
- (LaTeX-mode . my/-setup-LaTeX-mode)
- (LaTeX-mode . flycheck-mode))
- :bind (:map TeX-mode-map
- ("C-c ?" . latex-help))
- :init
- (add-to-list 'major-mode-remap-alist '(plain-tex-mode . plain-TeX-mode))
- (add-to-list 'major-mode-remap-alist '(latex-mode . LaTeX-mode))
- (add-to-list 'major-mode-remap-alist '(ams-tex-mode . AmSTeX-mode))
- (add-to-list 'major-mode-remap-alist '(context-mode . ConTeXt-mode))
- (add-to-list 'major-mode-remap-alist '(texinfo-mode . Texinfo-mode))
- (add-to-list 'major-mode-remap-alist '(doctex-mode . docTeX-mode))
- (add-to-list 'auto-mode-alist '("/\\.latexmkrc\\'" . perl-mode))
- (add-to-list 'auto-mode-alist '("\\.[tT]e[xX]\\'" . LaTeX-mode))
- :config
- (defun my/-auctex-texdoc-setup-env (oldfun &rest args)
- (let ((process-environment process-environment)
- (emacs-cmd (concat "emacsclient" (and (not (display-graphic-p)) " -nw"))))
- (setenv "PDFVIEWER_texdoc" "evince")
- (setenv "MDVIEWER_texdoc" emacs-cmd)
- (setenv "PAGER_texdoc" emacs-cmd)
- (apply oldfun args)))
- (advice-add 'TeX-documentation-texdoc :around 'my/-auctex-texdoc-setup-env)
- (defun my/-setup-LaTeX-mode ()
- (setq evil-lookup-func 'latex-help-at-point))
- (setq TeX-auto-save t
- TeX-parse-self t
- reftex-plug-into-AUCTeX t)
- (evil-define-operator my/evil-LaTeX-fill (beg end)
- "Like `evil-fill', but using auctex."
- ;; The code here came straight from `evil-fill'
- :move-point nil
- :type line
- (save-excursion
- (ignore-errors (LaTeX-fill-region beg end))))
- (evil-define-operator my/evil-LaTeX-fill-and-move (beg end)
- "Like `evil-fill-and-move', but using auctex."
- ;; The code here came straight from `evil-fill-and-move'
- :move-point nil
- :type line
- (let ((marker (make-marker)))
- (move-marker marker (1- end))
- (ignore-errors
- (LaTeX-fill-region beg end)
- (goto-char marker)
- (evil-first-non-blank))))
- (evil-define-key 'normal TeX-mode-map
- "gq" 'my/evil-LaTeX-fill-and-move
- "gw" 'my/evil-LaTeX-fill)
- (setq-default TeX-master nil)
- (require 'tex)
- (TeX-global-PDF-mode 1))
- ;; blueprint
- (use-package blueprint-ts-mode
- :hook (blueprint-ts-mode . eglot-ensure)
- :after eglot)
- ;; python-ts-mode
- (use-package python-ts-mode
- :ensure nil
- :hook (python-ts-mode . eglot-ensure))
- ;; java-ts-mode
- (use-package java-ts-mode
- :hook (java-ts-mode . eglot-ensure))
- ;; c-ts-mode
- (use-package c-ts-mode
- :after evil
- :hook ((c-ts-mode c++-ts-mode) . eglot-ensure)
- :init
- (setq-default c-ts-mode-indent-offset 4)
- :config
- (evil-define-key 'normal 'c-ts-mode-map
- "go" #'ff-find-other-file
- "gO" #'ff-find-other-file-other-window)
- (evil-define-key 'normal 'c++-ts-mode-map
- "go" #'ff-find-other-file
- "gO" #'ff-find-other-file-other-window)
- (evil-define-key 'normal 'objc-mode-map
- "go" #'ff-find-other-file
- "gO" #'ff-find-other-file-other-window))
- ;; php-mode
- (use-package php-mode
- :hook (php-mode . eglot-ensure))
- ;; web-mode
- (use-package web-mode
- :hook (web-mode . eglot-ensure)
- :init
- (add-to-list 'eglot-server-programs
- '(web-mode . ("vscode-html-language-server" "--stdio"))))
- ;; Polymode
- (use-package polymode
- :config
- (define-hostmode my/poly-web-hostmode
- :mode 'web-mode)
- (define-innermode my/poly-php-innermode
- :mode 'php-mode
- :head-matcher "\<\?php"
- :tail-matcher "\?\>"
- :head-mode 'body
- :tail-mode 'body)
- (define-polymode my/poly-web-mode
- :hostmode 'my/poly-web-hostmode
- :innermodes '(my/poly-php-innermode))
- (add-to-list 'auto-mode-alist '("\\.php\\|\\.phtml\\'" . my/poly-web-mode)))
- ;; shell-mode
- (use-package sh-script
- :ensure nil
- :hook (sh-mode . my/-setup-sh-mode)
- :init
- (defun my/-setup-sh-mode ()
- (add-to-list 'completion-at-point-functions #'cape-file)))
- ;; go mode
- (use-package go-mode
- :defer nil
- :hook (go-mode . eglot-ensure))
- (use-package go-ts-mode
- :ensure nil
- :hook (go-ts-mode . eglot-ensure))
- ;; rust
- (use-package rust-mode)
- (use-package rust-ts-mode
- :ensure nil
- :hook (rust-ts-mode . eglot-ensure))
- ;; zig
- (use-package zig-mode
- :hook (zig-mode . eglot-ensure))
- ;; lua
- (use-package lua-mode
- :hook (lua-mode . eglot-ensure))
- ;; markdown
- (use-package markdown-mode
- :hook (markdown-mode . auto-fill-mode))
- ;; groovy
- (use-package groovy-mode)
- ;; cmake
- (require 'cmake-mode)
- (with-eval-after-load 'cmake-mode
- (defun my/setup-cmake-ts-mode ()
- "Setup `cmake-ts-mode' buffers."
- (setq-local indent-line-function #'cmake-indent))
- (add-hook 'cmake-ts-mode-hook #'my/setup-cmake-ts-mode))
- ;; kdl
- (require 'kdl-ts-mode)
- ;; json
- (use-package json-ts-mode
- :hook (json-ts-mode . eglot-ensure))
- (use-package json-mode)
- ;; csv
- (use-package csv-mode)
- ;; firejail
- (require 'firejail-mode)
- ;; yaml
- (use-package yaml-ts-mode
- :hook ((yaml-ts-mode . eglot-ensure)
- (yaml-ts-mode . my/-setup-yaml-ts-mode))
- :init
- (defun my/-setup-yaml-ts-mode ()
- (setq indent-line-function #'yaml-indent-line)))
- (use-package yaml-mode)
- ;; yuck (config language for eww)
- (use-package yuck-mode)
- ;; Some Elisp indentation stuff
- ;; Source: https://github.com/magit/emacsql
- ;; emacsql.el line 394
- (defun my/lisp-inside-plist-p ()
- "Return t if point is inside a plist."
- (save-excursion
- (let ((start (point)))
- (beginning-of-defun)
- (when-let ((sexp (nth 1 (parse-partial-sexp (point) start))))
- (goto-char sexp)
- (looking-at (rx "(" (* (syntax whitespace)) ":"))))))
- (defun my/-calculate-indent-fix-plists (oldfun &rest args)
- "This function is meant to advise `calculate-lisp-indent'.
- It calls OLDFUN with ARGS in such an environment as to prevent the default
- indentation of plists."
- (if (and (eq major-mode 'emacs-lisp-mode)
- (save-excursion
- (beginning-of-line)
- (my/lisp-inside-plist-p)))
- (let ((lisp-indent-offset 1))
- (apply oldfun args))
- (apply oldfun args)))
- (advice-add 'calculate-lisp-indent :around
- 'my/-calculate-indent-fix-plists)
- (defvar my/max-lisp-noindent-comment-search-lines 30
- "Max lines to search for the noindent comment.")
- (defun my/-calculate-lisp-indent-noindent-comment (oldfun &rest args)
- "This function is meant to advise `calculate-lisp-indent'.
- It calls OLDFUN with ARGS, unless the line ends with the comment
- ; noindent [LINES]
- In this case, it just returns the current amount of indentation. LINES is the
- number of lines that this comment affects. This is limited by
- `my/max-lisp-noindent-comment-search-lines'.
- This only works if its on the first or second form in a block. I think this is
- because the indentation code only checks those and then assumes the same
- indentation for every following line in the same block. This is probably OK as
- I can't imagine too many instances where you need to randomly change the indent
- midway through a block, and in those cases you can just stick this on the first
- line in the block and manually deal with indentation."
- (if (and (save-excursion
- (end-of-line)
- (re-search-backward
- (rx (+ ";") (syntax whitespace) "noindent"
- (? (syntax whitespace) (group (+ num)))
- line-end)
- (pos-bol (- my/max-lisp-noindent-comment-search-lines))
- t))
- (save-excursion
- ;; if we are on a blank line, move forward a line
- (when (zerop (length (buffer-substring-no-properties
- (pos-bol) (pos-eol))))
- (beginning-of-line 2))
- (<= (count-lines (match-beginning 0) (pos-eol))
- (if-let ((match (match-string 1)))
- (string-to-number match)
- 1))))
- (save-excursion
- (beginning-of-line)
- (looking-at (rx (* blank)))
- (length (match-string 0)))
- (apply oldfun args)))
- (advice-add 'calculate-lisp-indent :around
- 'my/-calculate-lisp-indent-noindent-comment)
- ;; sly
- (use-package sly
- ;; :hook (lisp-mode . my/-lisp-mode-autoconnect-sly)
- :bind (:map sly-mode-map
- ("C-c e" . my/diagnostic-at-point))
- :autoload sly-connected-p
- :init
- (defun my/-lisp-mode-autoconnect-sly ()
- (unless (sly-connected-p)
- (sly)))
- (setq inferior-lisp-program "/usr/bin/sbcl")
- (defun my/-sly-fix-special-buffers ()
- (when (string-match-p (rx bos "*" (* any) "*" eos) (buffer-name))
- (setq-local show-trailing-whitespace nil)))
- (add-hook 'lisp-mode-hook 'my/-sly-fix-special-buffers)
- :config
- (sly-symbol-completion-mode -1))
- ;; pdf-tools
- (use-package pdf-tools
- :hook (pdf-view-mode . my/setup-pdf-view-mode)
- :init
- (setq pdf-misc-print-program-executable "lp")
- (defun my/setup-pdf-view-mode ()
- (display-line-numbers-mode -1)
- (evil-define-key '(motion normal visual) 'local
- (kbd "C-s") #'isearch-forward
- (kbd "C-r") #'isearch-backward)
- (setq-local cursor-type nil))
- (pdf-tools-install))
- ;; doc view
- (use-package doc-view
- :ensure nil
- :hook (doc-view-mode . my/-setup-doc-view-mode)
- :init
- (defun my/-setup-doc-view-mode ()
- (display-line-numbers-mode -1)
- (evil-define-key '(motion normal visual) 'local
- (kbd "C-s") #'isearch-forward
- (kbd "C-r") #'isearch-backward)))
- ;; calc
- (use-package calc
- :ensure nil
- :bind (("C-c m" . quick-calc)
- :map calc-mode-map
- ("M-<tab>" . calc-roll-up)
- ("M-TAB" . calc-roll-up))
- :hook ((calc-mode calc-trail-mode) . my/setup-calc-calc-trail-mode)
- :init
- (defun my/setup-calc-calc-trail-mode ()
- (setq-local doom-modeline-percent-position '()
- truncate-partial-width-windows nil)
- (visual-line-mode -1)
- (display-line-numbers-mode -1)
- (toggle-truncate-lines 1))
- :config
- (evil-define-key '(normal visual motion) calc-edit-mode-map
- (kbd "RET") 'calc-edit-return
- (kbd "<return>") 'calc-edit-return)
- (defun my/-calc-float-mode-string ()
- (cl-destructuring-bind (mode prec) calc-float-format
- (concat
- (upcase-initials (symbol-name mode))
- (unless (zerop prec)
- (concat ": " (number-to-string prec))))))
- (doom-modeline-def-segment calc
- "Display calculator icons and info."
- (concat
- (doom-modeline-spc)
- (when-let ((icon (doom-modeline-icon 'faicon "nf-fa-calculator" "🖩" "")))
- (concat
- (doom-modeline-display-icon icon)
- (doom-modeline-vspc)))
- (doom-modeline--buffer-simple-name)
- (when (eq major-mode 'calc-mode)
- (concat
- (doom-modeline-spc)
- (number-to-string calc-internal-prec)
- (doom-modeline-spc)
- (upcase-initials (symbol-name calc-angle-mode))
- (doom-modeline-spc)
- (my/-calc-float-mode-string)
- (when calc-prefer-frac
- (concat
- (doom-modeline-spc)
- "Frac"))
- (cond
- (calc-algebraic-mode
- (concat
- (doom-modeline-spc)
- "Alg"))
- (calc-incomplete-algebraic-mode
- (concat
- (doom-modeline-spc)
- "IAlg"))))))))
- ;; sage (for when calc is not enough)
- (use-package sage-shell-mode
- :demand
- :bind ("C-c g" . my/run-sage)
- :hook (sage-shell-mode . my/-setup-sage-shell-mode)
- :init
- (defun my/-setup-sage-shell-mode ()
- (setq-local comint-dynamic-complete-functions
- '(comint-c-a-p-replace-by-expanded-history)))
- :config
- (defun my/run-sage (p)
- "Like `sage-shell:run-sage', but does not ask anything without a prefix
- argument."
- (interactive "P")
- (let ((sage-shell:ask-command-options p))
- (funcall-interactively #'sage-shell:run-sage
- (sage-shell:read-command)))))
- ;; fricas (because I like calculators)
- (add-to-list 'load-path "/usr/lib/fricas/emacs/")
- (use-package fricas
- :ensure nil
- :custom
- (fricas-run-command "fricas -nosman")
- :init
- ;; Fix `fricas-mode' messing up `completion-at-point-functions'
- (advice-add #'fricas-mode :around
- #'(lambda (oldfun &rest r)
- (let ((temp-capfs))
- (let ((completion-at-point-functions '(t)))
- (apply oldfun r)
- (setq temp-capfs completion-at-point-functions))
- (setq-local completion-at-point-functions temp-capfs)))
- '((name . "my/-fricas-fix-capfs")))
- :config
- (face-spec-set 'fricas-type-time '((t (:foreground unspecified
- :background unspecified
- :inherit font-lock-type-face))))
- (face-spec-set 'fricas-message '((t (:foreground unspecified
- :background unspecified
- :inherit error))))
- (face-spec-set 'fricas-undefined '((t (:foreground unspecified
- :background unspecified
- :inherit nerd-icons-lblue))))
- (face-spec-set 'fricas-algebra '((t (:foreground unspecified
- :background unspecified
- :weight bold
- :inherit fricas-prompt))))
- (face-spec-set 'fricas-TeX '((t (:foreground "black"
- :background "white"
- :inherit fricas-prompt)))))
- ;; gnuplot (mostly for org-plot)
- (use-package gnuplot)
- ;; eat
- (use-package eat
- :bind (("C-c V" . my/project-eat-or-default)
- :map eat-mode-map
- ("M-o" . ace-window)
- :map eat-semi-char-mode-map
- ("M-o" . ace-window)
- :map eat-eshell-emacs-mode-map
- ("M-o" . ace-window)
- :map eat-eshell-semi-char-mode-map
- ("M-o" . ace-window))
- :config
- (defvar my/project-eat-hash-table (make-hash-table :test 'equal)
- "Hash table that maps project root dirs to eat buffers.")
- (defun my/project-eat (prompt)
- "Switch to or create a eat buffer in the current projects root."
- (interactive (list t))
- (if-let ((proj (project-current prompt))
- (default-directory (project-root proj)))
- (if-let ((eat-buff (gethash default-directory
- my/project-eat-hash-table))
- ((buffer-live-p eat-buff)))
- (switch-to-buffer eat-buff)
- (let ((eat-buffer-name (concat "*eat for project " default-directory
- "*"))
- (eat-term-name (if (file-remote-p default-directory)
- "xterm-256color"
- eat-term-name)))
- (puthash default-directory
- (eat)
- my/project-eat-hash-table)))))
- (defun my/project-eat-or-default ()
- "Open an eat for the current project, otherwise, open a normal eat."
- (interactive)
- (unless (my/project-eat nil)
- (if-let ((eat-buff (gethash nil my/project-eat-hash-table))
- ((buffer-live-p eat-buff)))
- (switch-to-buffer eat-buff)
- (puthash nil (let ((eat-term-name (if (file-remote-p default-directory)
- "xterm-256color"
- eat-term-name)))
- (eat))
- my/project-eat-hash-table)))))
- ;; eshell stuff
- (use-package eshell
- :ensure nil
- :defer nil
- :hook ((eshell-load . eat-eshell-visual-command-mode)
- (eshell-load . eat-eshell-mode)
- (eshell-mode . my/-eshell-mode-setup))
- :bind (:map eshell-mode-map
- ("TAB" . completion-at-point)
- ("<tab>" . completion-at-point))
- :init
- (defun my/-eshell-mode-setup ()
- "Setup function run from `eshell-mode-hook'"
- (setq-local corfu-auto nil))
- (setq-default eshell-command-aliases-list
- '(("clear" "clear t")
- ("e" "find-file $1")
- ("n" "find-file $1")
- ("emacs" "find-file $1")
- ("nvim" "find-file $1")
- ("ls" "eza --git -F $*")
- ("la" "ls -a $*")
- ("l" "ls -l $*")
- ("ll" "la -l $*")
- ("gt" "git status $*")
- ("gp" "git push $*")
- ("gu" "git pull $*")
- ("gf" "git fetch $*")
- ("ga" "git add $*")
- ("gcm" "git commit -m ${string-join $* \" \"}")
- ("ldg" "ledger -f \"$HOME/docs/finance/finances.ledger\" $*")
- ("tp" "trash-put $*")
- ("trr" "trash-restore $*")
- ("tre" "trash-empty $*")
- ("tre" "trash-empty $*")
- ("trm" "trash-rm $*")
- ("rm" "echo 'rm: I''m unsafe! Don''t use me.'; false")
- ("\\rm" "eshell/rm")))
- (defvar my/eshell-bm-auto-ls t
- "Weather or not to run ls after `eshell/bm'")
- (defun eshell/bm (&optional name)
- "Change to directory of bookmark NAME.
- If no name is given, list all bookmarks instead."
- (if name
- (progn
- (eshell/cd (bookmark-get-filename name))
- (when my/eshell-bm-auto-ls
- (eshell/ls)))
- (eshell-print (string-join (bookmark-all-names) " ")))))
- (use-package esh-help
- :hook (eshell-mode . my/-setup-eshell-help-func)
- :init
- (defun my/-setup-eshell-help-func ()
- (eldoc-mode 1)
- (setq-local evil-lookup-func #'esh-help-run-help))
- (setup-esh-help-eldoc))
- (use-package eshell-syntax-highlighting
- :init
- (eshell-syntax-highlighting-global-mode 1))
- (use-package eshell-starship
- :ensure nil
- :demand t
- :hook (eshell-prompt-mode . eshell-starship-prompt-mode))
- ;; proced
- (use-package proced
- :bind ("C-x j" . proced)
- :init
- (evil-define-key '(motion visual normal) proced-mode-map
- "u" 'proced-unmark)
- (setq proced-auto-update-flag t
- proced-auto-update-interval 1)
- (defun my/-setup-proced-mode ()
- (visual-line-mode -1)
- (setq-local truncate-lines t))
- (add-hook 'proced-mode-hook 'my/-setup-proced-mode))
- ;; dired
- (use-package dired
- :ensure nil
- :init
- (setq-default dired-kill-when-opening-new-dired-buffer t)
- (setq delete-by-moving-to-trash t
- dired-recursive-copies 'always
- dired-recursive-deletes 'always
- dired-dwim-target t
- dired-create-destination-dirs 'ask
- dired-create-destination-dirs-on-trailing-dirsep t
- dired-isearch-filenames 'dwim
- dired-do-revert-buffer (lambda (dir)
- (not (file-remote-p dir)))
- dired-clean-up-buffers-too t
- dired-clean-confirm-killing-deleted-buffers t)
- (evil-define-key '(normal visual motion) dired-mode-map
- "u" #'dired-unmark
- "U" #'dired-unmark-all-marks))
- ;; ibuffer
- (use-package ibuffer
- :bind ("C-x C-b" . ibuffer))
- ;; magit
- (use-package magit
- :init
- (evil-define-key '(normal visual motion) magit-mode-map
- "s" #'magit-stage-file
- "S" #'magit-stage-modified))
- ;; org-mode
- (use-package org
- :pin gnu
- :bind (("C-c c" . org-capture)
- ("C-c a" . org-agenda)
- ("C-c l" . org-store-link)
- :map org-mode-map
- ("C-c t" . org-table-create))
- :hook (org-mode . org-table-header-line-mode)
- :init
- (font-lock-add-keywords 'org-mode
- `((,(rx bol (* " ") (group "-") " ")
- (0 (prog1 nil
- (compose-region (match-beginning 1)
- (match-end 1) "•"))))))
- (setq org-directory "~/org"
- org-agenda-files '("~/org/")
- org-log-into-drawer t
- org-log-done 'time
- org-log-redeadline 'time
- org-log-reschedule 'time
- org-preview-latex-default-process 'dvisvgm
- org-highlight-latex-and-related '(native entities)
- org-startup-with-inline-images t
- org-adapt-indentation t
- org-hide-leading-stars t
- org-html-with-latex 'dvisvgm
- org-preview-latex-process-alist
- '((dvisvgm
- :image-input-type "dvi"
- :image-output-type "svg"
- :image-size-adjust (1.7 . 1.5)
- :latex-compiler ("pdflatex -interaction nonstopmode -output-format=dvi -output-directory=%o %f")
- :image-converter ("dvisvgm %o%b.dvi --no-fonts --exact-bbox --scale=%S --output=%O"))))
- (defun my/-org-allow-in-derived-mode (oldfun &rest r)
- "Allow OLDFUN to run, even if `major-mode' is only derived from `org-mode'.
- R is rest of the arguments to OLDFUN."
- (let ((major-mode (if (derived-mode-p 'org-mode)
- 'org-mode
- major-mode)))
- (apply oldfun r)))
- (advice-add 'org-element-at-point :around 'my/-org-allow-in-derived-mode)
- (advice-add 'org-table-header-line-mode :around 'my/-org-allow-in-derived-mode))
- (use-package evil-org
- :after org
- :hook (org-mode . evil-org-mode)
- :init
- (require 'evil-org-agenda)
- (evil-org-agenda-set-keys))
- ;; ledger
- (use-package ledger-mode)
- (use-package flycheck-ledger
- :hook (ledger-mode . flycheck-mode))
- ;; khard contacts
- (require 'khard)
- ;; This is also in khard (see above), it's just also here so that if I remove
- ;; that file ever, other things will not break.
- (defun my/message-in-header-p (name &optional testfn)
- "If in field NAME, return the start of the header, otherwise, return nil.
- The name is compared with the field name using TESTFN (defaults to `equal')."
- (save-excursion
- (when (and (message-point-in-header-p)
- (message-beginning-of-header t))
- (beginning-of-line)
- (when (and (looking-at (rx bol (group (+? any)) ":" (? " ")))
- (funcall (or testfn 'equal) (match-string 1) name))
- (match-end 0)))))
- ;; mu4e
- (use-package mu4e
- :ensure nil
- :defer nil
- :hook ((mu4e-index-updated . my/-mu4e-enable-index-messages)
- (mu4e-main-mode . my/-mu4e-setup-main-mode)
- (mu4e-view-mode . my/-mu4e-setup-view-mode)
- (mu4e-compose-mode . my/-mu4e-setup-compose-mode))
- :bind (("C-x C-m" . mu4e)
- :map message-mode-map
- ("C-c k" . khard-insert-email-contact)
- :map mu4e-headers-mode-map
- ([remap mu4e-headers-mark-for-trash] .
- my/mu4e-headers-mark-for-trash)
- :map mu4e-view-mode-map
- ([remap mu4e-view-mark-for-trash] .
- my/mu4e-view-mark-for-trash))
- :init
- (require 'mu4e)
- (evil-define-key '(normal motion) mu4e-main-mode-map "q" #'bury-buffer)
- (evil-define-key '(normal motion) mu4e-view-mode-map "gy" #'mu4e-view-save-url)
- (defun my/-mu4e-setup-view-mode ()
- (setq-local global-hl-line-mode nil))
- (defun my/-mu4e-setup-main-mode ()
- (setq-local default-directory "~/"))
- (defun my/-mu4e-enable-index-messages ()
- (setq mu4e-hide-index-messages nil))
- (defun my/mu4e-update-mail-and-index-silent ()
- "Run `mu4e-update-mail-and-index' without any messages in the background."
- (setq mu4e-hide-index-messages t)
- (mu4e-update-mail-and-index t))
- (defun my/mu4e-headers-mark-for-trash ()
- "Move the message a point to the trash without marking it was deleted
- (trashed)."
- (interactive)
- (when (mu4e-thread-message-folded-p)
- (mu4e-warn "Cannot mark folded messages"))
- (mu4e-mark-at-point 'move mu4e-trash-folder)
- (when mu4e-headers-advance-after-mark
- (mu4e-headers-next)))
- (defun my/mu4e-view-mark-for-trash ()
- "Like `my/mu4e-headers-mark-for-trash', but for `mu4e-view-mode'."
- (interactive)
- (mu4e--view-in-headers-context
- (my/mu4e-headers-mark-for-trash)))
- (defun my/-mu4e-enable-autocomplete-in-header ()
- ;; corfu auto must be t (not the integer returned by
- ;; `my/message-in-header-p'
- (setq-local corfu-auto (and (not (window-minibuffer-p))
- (my/message-in-header-p "To")
- t)))
- (defun my/-mu4e-setup-compose-mode ()
- (add-hook 'post-command-hook 'my/-mu4e-enable-autocomplete-in-header
- nil t)
- (add-to-list
- (make-local-variable 'completion-at-point-functions)
- (cape-capf-super #'mu4e-complete-contact #'khard-message-mode-capf)))
- (defun my/-mu4e-fix-cycle-threshold ()
- (setq-local completion-cycle-threshold nil))
- (advice-add 'mu4e--compose-setup-completion :after
- 'my/-mu4e-fix-cycle-threshold)
- (defvar my/mu4e-interesting-mail-query
- (concat "flag:unread AND NOT flag:trashed AND NOT "
- "maildir:/protonmail/Trash AND NOT maildir:/protonmail/Spam")
- "Flag for mail which will appear as \"unread\" and will be notified.")
- (setq message-kill-buffer-on-exit t
- message-confirm-send t
- message-send-mail-function 'sendmail-send-it
- mu4e-change-filenames-when-moving t
- mu4e-context-policy 'pick-first
- mu4e-attachment-dir "~/downloads/"
- mu4e-last-update-buffer " *mu4e-last-update*"
- mu4e-index-update-error-warning nil
- mu4e-get-mail-command "mbsync protonmail"
- mu4e-completing-read-function #'completing-read-default
- mu4e-compose-context-policy 'ask-if-none
- mu4e-contexts
- (list (make-mu4e-context
- :name "Personal"
- :match-func (lambda (msg)
- (when msg
- (string-match-p "^/protonmail/"
- (mu4e-message-field msg
- :maildir))))
- :vars `((user-mail-address . ,(my/get-private 'mu4e-email))
- (user-full-name . ,(my/get-private 'mu4e-name))
- (message-signature . nil)
- (mu4e-refile-folder . "/protonmail/Archive")
- (mu4e-sent-folder . "/protonmail/Sent")
- (mu4e-drafts-folder . "/protonmail/Drafts")
- (mu4e-trash-folder . "/protonmail/Trash")
- (mu4e-bookmarks
- . ((:name "Inbox"
- :query "maildir:/protonmail/Inbox"
- :key ?i)
- (:name "Unread"
- :query ,my/mu4e-interesting-mail-query
- :key ?u))))))))
- (use-package mu4e-alert
- :after mu4e
- :hook (after-init . mu4e-alert-enable-notifications)
- :init
- (setq mu4e-alert-set-window-urgency nil
- mu4e-alert-interesting-mail-query my/mu4e-interesting-mail-query)
- :config
- (mu4e-alert-set-default-style 'libnotify))
- (mu4e t)
- (mu4e-context-switch nil "Personal")
- ;; mu4e compose HTML messages
- (use-package org-mime)
- (require 'org-mu4e-compose)
- (setq mail-user-agent 'org-mu4e-user-agent
- org-mime-org-html-with-latex-default 'dvisvgm
- org-mime-export-options '(:with-latex dvisvgm :with-footnotes t))
- (evil-define-key '(normal visual) org-mu4e-compose-mode-map
- "G" #'mu4e-compose-goto-bottom
- "gg" #'mu4e-compose-goto-top)
- (evil-define-key 'normal org-mu4e-compose-mode-map
- "ZZ" #'message-send-and-exit
- "ZD" #'message-dont-send
- "ZQ" #'message-kill-buffer
- "ZF" #'mml-attach-file)
- (evil-define-key 'normal mu4e-view-mode-map
- "R" 'org-mu4e-compose-reply
- "cr" 'org-mu4e-compose-reply)
- (evil-define-key 'normal mu4e-headers-mode-map
- "R" 'org-mu4e-compose-reply
- "cr" 'org-mu4e-compose-reply)
- (defun my/-setup-org-mu4e-compose-mode ()
- "Setup up stuff in `org-mu4e-compose' buffers."
- (setq-local ltex-eglot-variable-save-method 'file)
- ;; this should come last so it can pick up the above
- ;; (eglot-ensure)
- )
- (add-hook 'org-mu4e-compose-mode-hook #'my/-setup-org-mu4e-compose-mode)
- ;; elfeed
- (use-package elfeed
- :bind (("C-c d" . elfeed))
- :custom
- (elfeed-feeds
- '(("https://archlinux.org/feeds/news/" linux arch)
- ("https://9to5linux.com/feed/atom" linux news)))
- :config
- (setq elfeed-log-buffer-name " *elfeed-log*")
- (evil-define-key '(normal motion) elfeed-search-mode-map
- "r" #'elfeed-search-fetch)
- (elfeed-db-load))
- ;; helpful
- (use-package helpful
- :hook ((emacs-lisp-mode . my/-helpful-setup-emacs-lisp-mode)
- (helpful-mode . my/-setup-helpful-mode))
- :bind (:map help-map
- ("f" . helpful-callable)
- ("v" . helpful-variable)
- ("k" . helpful-key)
- ("o" . helpful-symbol)
- ("x" . helpful-command)
- ("F" . helpful-function)
- :map helpful-mode-map
- ("<mouse-8>" . my/helpful-history-back)
- ("<mouse-9>" . my/helpful-history-forward)
- ("<normal-state><" . my/helpful-history-back)
- ("<normal-state>>" . my/helpful-history-forward))
- :init
- (defun my/-helpful-setup-emacs-lisp-mode ()
- (setq-local evil-lookup-func #'helpful-at-point))
- (defun my/-setup-helpful-mode ()
- (setq-local evil-lookup-func #'helpful-at-point
- tab-width 8))
- (defvar my/helpful-symbol-history-size 50
- "Max size of `my/helpful-symbol-history'.")
- (defvar my/helpful-symbol-history '()
- "History of helpful symbols.")
- (defvar my/-helpful-inhibit-history nil
- "If non-nil, don't add symbols to `my/helpful-symbol-history'.")
- (defvar my/-helpful-last-entry nil
- "Last entry looked up with helpful.")
- (defun my/helpful-history-back (count)
- "Go back COUNT symbols in `my/helpful-symbol-history'. If called
- interactively, COUNT defaults to 1."
- (interactive "p")
- (my/helpful-history-forward (- count)))
- (defun my/helpful-history-forward (count)
- "Move COUNT symbols in `my/helpful-symbol-history'. If COUNT is negative,
- move back. If COUNT is larger than the history, go to the newest entry. Go to
- the oldest entry if -COUNT is larger than the history."
- (interactive "p")
- (when helpful--sym
- (let* ((hist-len (length my/helpful-symbol-history))
- (current-pos (seq-position my/helpful-symbol-history
- (cons helpful--sym
- helpful--callable-p)
- 'equal))
- (new-pos (- current-pos count)))
- (cond
- ;; if already at the newest element, signal an error
- ((and (> count 0) (= current-pos 0))
- (message "%s" "No newer symbol!"))
- ;; if already at the oldest element, signal an error
- ((and (< count 0) (= (1+ current-pos) hist-len))
- (message "%s" "No older symbol!"))
- (t
- (let ((my/-helpful-inhibit-history t)
- (entry (cond
- ((<= new-pos 0)
- (seq-first my/helpful-symbol-history))
- ((>= new-pos hist-len)
- (car (last my/helpful-symbol-history)))
- (t
- (nth new-pos my/helpful-symbol-history)))))
- (if (cdr entry)
- (helpful-callable (car entry))
- (helpful-variable (car entry)))))))))
- (defun my/-helpful-switch-buffer-function (helpful-buf)
- "Like `pop-to-buffer', but kill previous helpful buffers and save the new
- buffers `helpful--sym' to `my/helpful-symbol-history'."
- (cl-loop with window = nil
- for buf in (buffer-list)
- when (and
- (not (eq buf helpful-buf))
- (eq (buffer-local-value 'major-mode buf) 'helpful-mode))
- do
- (when-let (cur-window (get-buffer-window buf nil))
- (setq window cur-window))
- (kill-buffer buf)
- finally
- (let ((entry (cons (buffer-local-value 'helpful--sym helpful-buf)
- (buffer-local-value 'helpful--callable-p
- helpful-buf))))
- (unless my/-helpful-inhibit-history
- (when-let (from-current-hist
- (member my/-helpful-last-entry
- my/helpful-symbol-history))
- (setq my/helpful-symbol-history from-current-hist))
- (cl-pushnew entry my/helpful-symbol-history :test 'equal)
- (setq my/helpful-symbol-history
- (seq-take my/helpful-symbol-history
- my/helpful-symbol-history-size)))
- (setq my/-helpful-last-entry entry))
- (if window
- (window--display-buffer helpful-buf window 'reuse)
- (pop-to-buffer helpful-buf))))
- (setq helpful-switch-buffer-function 'my/-helpful-switch-buffer-function
- helpful-max-buffers 2))
- (defun my/greyify-color (color percent &optional frame)
- "Make COLOR closer to black by PERCENT on FRAME.
- Color can be any color which can be passed to `color-values'."
- (cl-destructuring-bind (&optional r g b)
- (color-name-to-rgb color frame)
- (when (and r g b)
- (let ((scale (- 1.0 (/ percent 100.0))))
- (color-rgb-to-hex (* r scale)
- (* g scale)
- (* b scale))))))
- ;; rainbow-delimiters
- (use-package rainbow-delimiters
- :hook (prog-mode . rainbow-delimiters-mode)
- :config
- ;; generate dark version of the rainbow delimiters faces
- (defun my/-rainbow-delimiters-recalc-dark-faces (&optional frame)
- (unless frame (setq frame (selected-frame)))
- (dotimes (i 9)
- (when-let ((old-face (intern-soft
- (format "rainbow-delimiters-depth-%d-face"
- (1+ i))))
- (new-face
- (intern
- (format "my/rainbow-delimiters-depth-%d-dark-face"
- (1+ i))))
- (old-color (face-attribute old-face :foreground frame))
- (new-color (my/greyify-color old-color 50 frame)))
- (set-face-attribute new-face frame :foreground new-color))))
- (add-hook 'after-make-frame-functions
- #'my/-rainbow-delimiters-recalc-dark-faces)
- (add-hook 'server-after-make-frame-hook
- #'my/-rainbow-delimiters-recalc-dark-faces)
- (defun my/rainbow-delimiters-parinfer-pick-face (depth match loc)
- "Version of `rainbow-delimiters-default-pick-face' that colors closing
- parenthesis darker than opening ones. This function defers to
- `rainbow-delimiters-default-pick-face' and just changes the output if it returns
- one of the normal rainbow-delimiters-depth-N-face faces."
- (save-match-data
- (let* ((base-face (rainbow-delimiters-default-pick-face depth match loc))
- (base-name (symbol-name base-face)))
- (if (and evil-cleverparens-mode
- (eq ?\) (char-syntax
- (elt (buffer-substring-no-properties loc (1+ loc)) 0)))
- (string-match (rx string-start "rainbow-delimiters-depth-"
- (group (+ num))
- "-face" string-end)
- base-name))
- (or (intern-soft (format "my/rainbow-delimiters-depth-%s-dark-face"
- (match-string 1 base-name)))
- base-face)
- base-face))))
- (setopt rainbow-delimiters-pick-face-function
- 'my/rainbow-delimiters-parinfer-pick-face))
- ;; auto-highlight-symbol
- (use-package auto-highlight-symbol
- :hook (lisp-data-mode . auto-highlight-symbol-mode)
- :init
- (setq ahs-face 'bold
- ahs-face-unfocused 'bold
- ahs-definition-face 'bold
- ahs-definition-face-unfocused 'bold
- ahs-plugin-default-face 'bold
- ahs-plugin-default-face-unfocused 'bold))
- ;; Theme (doom-themes)
- (use-package doom-themes
- :config
- (load-theme 'doom-molokai t)
- (doom-themes-org-config))
- ;; solaire-mode
- (use-package solaire-mode
- :config
- (solaire-global-mode 1))
- ;; Highlight todos
- (use-package hl-todo
- :config
- (global-hl-todo-mode 1))
- (use-package magit-todos
- :after (hl-todo magit)
- :config
- (magit-todos-mode 1))
- ;; icons
- (use-package nerd-icons)
- (use-package nerd-icons-completion
- :config
- (nerd-icons-completion-mode))
- (use-package nerd-icons-dired
- :hook (dired-mode . nerd-icons-dired-mode))
- (use-package kind-icon
- :after corfu
- :init
- (setq kind-icon-default-face 'corfu-default
- kind-icon-default-style
- '(:padding -1 :stroke 0 :margin 0 :radius 0 :height 0.5 :scale 1))
- :config
- (add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter))
- ;; modeline (doom-modeline)
- (use-package doom-modeline
- :init
- (setq doom-modeline-support-imenu t)
- (doom-modeline-mode 1))
- ;; dashboard.el
- (use-package dashboard
- :config
- (dashboard-setup-startup-hook)
- (setq initial-buffer-choice (lambda () (get-buffer-create "*dashboard*"))
- dashboard-force-refresh t
- dashboard-display-icons-p t
- dashboard-icon-type 'nerd-icons
- dashboard-set-file-icons t
- dashboard-projects-backend 'project-el
- dashboard-items '((recents . 5)
- (projects . 5)
- (bookmarks . 5))))
- ;; page break lines
- (use-package page-break-lines
- :config
- (global-page-break-lines-mode 1)
- (add-to-list 'page-break-lines-modes 'prog-mode)
- (add-to-list 'page-break-lines-modes 'text-mode)
- (add-to-list 'page-break-lines-modes 'helpful-mode))
- ;; fun!
- (use-package mines)
- ;;; init.el ends here
|