863 lines
29 KiB
EmacsLisp
863 lines
29 KiB
EmacsLisp
;; -*- lexical-binding: t; -*-
|
|
|
|
(menu-bar-mode 0)
|
|
(tool-bar-mode 0)
|
|
(scroll-bar-mode 0)
|
|
(column-number-mode 1)
|
|
|
|
;; Word wrapping
|
|
(global-visual-line-mode 1)
|
|
(setq-default visual-line-fringe-indicators '(left-curly-arrow right-curly-arrow))
|
|
|
|
;; Set custom tab width here
|
|
(defvar custom-tab-width 8)
|
|
|
|
;; Disable bell/messages sound on windows
|
|
(when (eq window-system 'w32)
|
|
(set-message-beep 'silent))
|
|
|
|
;; Temporary file config
|
|
(setq backup-directory-alist
|
|
`((".*" . ,temporary-file-directory)))
|
|
(setq auto-save-file-name-transforms
|
|
`((".*" ,temporary-file-directory t)))
|
|
|
|
;; Fixes to stop weird window geometry issues
|
|
(setq frame-inhibit-implied-resize t)
|
|
(setq frame-resize-pixelwise t)
|
|
|
|
;; Paren matching
|
|
(setq show-paren-context-when-offscreen 'overlay)
|
|
(show-paren-mode 1)
|
|
|
|
;; Ensure that tabs are default over spaces
|
|
(setq-default tab-width custom-tab-width)
|
|
(setq tab-width custom-tab-width)
|
|
(setq-default indent-tabs-mode 't)
|
|
(setq indent-tabs-mode 't)
|
|
(advice-add 'indent-to :around
|
|
(lambda (orig-fun column &rest args)
|
|
(when (eq indent-tabs-mode 'only)
|
|
(setq column (* tab-width (round column tab-width))))
|
|
(apply orig-fun column args)))
|
|
(defvaralias 'c-basic-offset 'tab-width)
|
|
(electric-indent-mode 0)
|
|
|
|
;; Hide all minor modes from the modeline
|
|
(setq mode-line-modes
|
|
(mapcar (lambda (elem)
|
|
(pcase elem
|
|
(`(:propertize (,_ minor-mode-alist . ,_) . ,_) "")
|
|
(t elem)))
|
|
mode-line-modes))
|
|
|
|
;; Clipboard config
|
|
(setopt select-active-regions nil)
|
|
(setq select-enable-clipboard t) ; Syncs Emacs 'kill' with system clipboard
|
|
(setq select-enable-primary t) ; Syncs with the primary selection (middle-click)
|
|
(setq save-interprogram-paste-before-kill t) ; Save existing clipboard to kill ring before overwriting
|
|
(setopt interprogram-cut-function #'gui-select-text)
|
|
|
|
;; Midnight Mode
|
|
; Automatically clean up old unused buffers
|
|
(midnight-mode 1)
|
|
|
|
;; Font configuration
|
|
; Global font
|
|
(set-frame-font "MesloLGL Nerd Font 20")
|
|
|
|
; Buffer fonts
|
|
(defun set-buffer-local-font ()
|
|
"Set font for normal buffers."
|
|
(face-remap-add-relative 'default :height 260))
|
|
(add-hook 'prog-mode-hook #'set-buffer-local-font)
|
|
(add-hook 'text-mode-hook #'set-buffer-local-font)
|
|
|
|
; Emacsclient new frame fonts
|
|
(setq default-frame-alist '((font . "MesloLGL Nerd Font 20")))
|
|
|
|
;; Emacsclient Configuration
|
|
(defun client-config ()
|
|
"Ran on new emacslient frame creations."
|
|
(scroll-bar-mode 0))
|
|
(add-hook 'after-make-frame-functions #'(lambda (frame)
|
|
(select-frame frame)
|
|
(client-config)))
|
|
|
|
;; Ensure TAB key ACTUALLY works like a TAB key
|
|
(defun my/complete-or-tab ()
|
|
"Complete at point or insert a tab if no characters before point."
|
|
(interactive)
|
|
(if (and (char-before) (not (member (char-before) '(?\s ?\t ?\n)))) ; Check for whitespace, tabs or newline
|
|
(completion-at-point) ; If yes, do completion at point
|
|
(insert-tab))) ; If no, insert a tab character
|
|
(global-set-key (kbd "TAB") 'my/complete-or-tab)
|
|
(define-key global-map [remap backward-delete-char-untabify] 'backward-delete-char)
|
|
|
|
;; Track recently opened files
|
|
(recentf-mode 1)
|
|
|
|
;; Stop weird C-9 keybindings causing conflicts on typo
|
|
(define-key global-map [remap digit-argument] "")
|
|
|
|
;; Optimisation
|
|
; GCMH
|
|
;Enforce a sneaky Garbage Collection strategy to minimize GC interference with user activity.
|
|
;During normal use a high GC threshold is set.
|
|
;When idling GC is triggered and a low threshold is set.
|
|
;This greatly improves performance/startup time of emacs.
|
|
(use-package gcmh
|
|
:ensure t
|
|
:init
|
|
(gcmh-mode 1)
|
|
|
|
;; Ensure garbage collector does not run TOO frequently which causes random freezes
|
|
(defun gcmh-mode-optimisation-setup-hook ()
|
|
(setq gc-cons-threshold most-positive-fixnum))
|
|
|
|
(defun gcmh-mode-optimisation-exit-hook ()
|
|
(setq gc-cons-threshold 800000))
|
|
|
|
(add-hook 'minibuffer-setup-hook 'gcmh-mode-optimisation-setup-hook)
|
|
(add-hook 'minibuffer-exit-hook 'gcmh-mode-optimisation-exit-hook))
|
|
|
|
; Fontification
|
|
(jit-lock-mode 1)
|
|
(jit-lock-debug-mode 1)
|
|
(setq jit-lock-stealth-time 1.25)
|
|
(setq jit-lock-stealth-nice 0.5) ;; Seconds between font locking.
|
|
(setq jit-lock-chunk-size 4096)
|
|
|
|
(setq jit-lock-defer-time 0)
|
|
(with-eval-after-load 'evil
|
|
(add-hook 'evil-insert-state-entry-hook
|
|
(lambda ()
|
|
(setq jit-lock-defer-time 0.25)) nil t)
|
|
(add-hook 'evil-insert-state-exit-hook
|
|
(lambda ()
|
|
(setq jit-lock-defer-time 0)) nil t))
|
|
|
|
|
|
;; TRAMP
|
|
;TRAMP edit files over SSH configuration
|
|
(use-package tramp
|
|
:ensure t
|
|
:config
|
|
;; To speed up connections
|
|
(setq tramp-verbose 0
|
|
tramp-chunksize 2000
|
|
tramp-use-ssh-controlmaster-options nil
|
|
tramp-default-method "ssh"
|
|
tramp-verbose 1
|
|
tramp-default-remote-shell "/bin/sh"
|
|
tramp-connection-local-default-shell-variables
|
|
'((shell-file-name . "/bin/bash")
|
|
(shell-command-switch . "-c")))
|
|
|
|
(add-to-list 'tramp-remote-path 'tramp-own-remote-path)
|
|
(when (eq window-system 'w32)
|
|
(setq tramp-default-method "plink")))
|
|
|
|
; Tramp RPC - Alternate backend promising more speed
|
|
(use-package tramp-rpc
|
|
:ensure (:host github :repo "ArthurHeymans/emacs-tramp-rpc")
|
|
:after tramp
|
|
:config
|
|
(setq tramp-rpc-deploy-local-cache-directory
|
|
"~/.cache/emacs/tramp-rpc-binaries"))
|
|
|
|
|
|
;; Org Mode Config
|
|
; Agenda
|
|
(defun org-agenda-toggle-day-view ()
|
|
"Toggle between daily and weekly view in org agenda."
|
|
(interactive)
|
|
(if (eq org-agenda-current-span 'day)
|
|
(org-agenda-week-view)
|
|
(org-agenda-day-view)))
|
|
;For Org-Agenda, you can set a location of your Org Agenda file here. Set Agenda Directory:
|
|
(use-package org
|
|
;:ensure (:wait t)
|
|
:ensure nil
|
|
:demand t
|
|
:after evil
|
|
:hook
|
|
(org-agenda-mode . (lambda() (org-agenda-entry-text-mode 1)))
|
|
:bind
|
|
(:map org-agenda-mode-map
|
|
("C-j" . evil-next-line)
|
|
("C-k" . evil-previous-line)
|
|
("d" . org-agenda-toggle-day-view)
|
|
:map evil-normal-state-map
|
|
("U" . undo-redo))
|
|
:config
|
|
(setq org-agenda-files '("~/Nextcloud/Agenda"))
|
|
;This is will integrate the Calendar/Diary into Org-Agenda, so you can get access to dates on public holidays etc. Set diary to true:
|
|
(setq org-agenda-include-diary t)
|
|
;Ensure done date/closed timestamps are logged
|
|
(setq org-log-done 'time)
|
|
;Ensure state changes are logged into logbook
|
|
(setq org-log-into-drawer "LOGBOOK")
|
|
|
|
;Ensure agenda still shows DONE items
|
|
(setq org-agenda-skip-scheduled-if-done nil)
|
|
(setq agenda-skip-deadline-if-done nil)
|
|
|
|
;Fold settings
|
|
;Org Mode historically used overlays to hide text, but newer versions moved toward text properties for better performance in large files. This change occasionally causes "stuck" visibility where sub-headers remain hidden until the parent is fully cycled.
|
|
(setq org-fold-core-style 'overlays)
|
|
(setq org-startup-folded t)
|
|
(setq org-hide-emphasis-markers nil))
|
|
|
|
; For Org Pomodoro notification sound
|
|
(use-package sound-wav
|
|
:ensure t)
|
|
|
|
; Org Pomodoro
|
|
(use-package org-pomodoro
|
|
:ensure t
|
|
:after org
|
|
:defer t
|
|
:config
|
|
(setq org-pomodoro-manual-break t)
|
|
(setq org-pomodoro-keep-killed-pomodoro-time t)
|
|
(setq org-pomodoro-play-sounds t)
|
|
(setq org-pomodoro-ticking-sound-p nil)
|
|
(setq org-pomodoro-audio-player "mpv"))
|
|
|
|
(defun sound-alert (alert)
|
|
"Play a sound notification and show message ALERT."
|
|
(sound-wav-play (expand-file-name (concat user-emacs-directory "elpaca/builds/org-pomodoro/resources/bell.wav")))
|
|
(message alert))
|
|
|
|
; Org timer custom alert
|
|
(defun org-timer-sound-alert ()
|
|
"Sound notification on org timer finish."
|
|
(sound-alert "Timer done!"))
|
|
(add-hook 'org-timer-done-hook 'org-timer-sound-alert)
|
|
(use-package alert
|
|
:ensure t
|
|
:config
|
|
(alert-define-style 'custom-org-alert-notification
|
|
:title "Custom Notification"
|
|
:notifier
|
|
(lambda (info)
|
|
; 'info' is a plist containing :title, :message, :severity, etc.
|
|
(notifications-notify
|
|
:title "Emacs Alert"
|
|
:body (plist-get info :message))
|
|
(sound-alert (concat "ORG ALERT: "
|
|
;(plist-get info :title)
|
|
(plist-get info :message)))))
|
|
(setq alert-default-style 'custom-org-alert-notification))
|
|
|
|
; System notifications of org agenda items
|
|
(use-package org-wild-notifier
|
|
:ensure t
|
|
:after org
|
|
:config
|
|
;; Notifications fire N minutes before an event
|
|
(setq org-wild-notifier-alert-time '(1 10 30))
|
|
;; Notification title and icon
|
|
(setq org-wild-notifier-notification-title "Org Reminder")
|
|
;(setq org-wild-notifier-notification-icon "/path/to/icon.png")
|
|
;; Remind about day-wide events at 10am and 8pm
|
|
(setq org-wild-notifier-day-wide-alert-times '("10:00" "20:00"))
|
|
|
|
;; Alert severity: 'high, 'medium, or 'low
|
|
(setq org-wild-notifier--alert-severity 'high)
|
|
|
|
;; Pass additional arguments to alert
|
|
(setq org-wild-notifier-extra-alert-plist '(:persistent t))
|
|
(org-wild-notifier-mode))
|
|
|
|
; Upcoming agenda items in modeline
|
|
(use-package org-upcoming-modeline
|
|
:ensure t
|
|
:after org ; if you don't want it to start until org has been loaded
|
|
:config
|
|
(org-upcoming-modeline-mode))
|
|
|
|
; Org Mode Journalling
|
|
(use-package org-journal
|
|
:ensure t
|
|
:after org
|
|
:config
|
|
(setq org-journal-dir "~/Nextcloud/Journal/")
|
|
(setq org-journal-file-type 'daily)
|
|
(setq org-journal-file-format "%Y%m%d.org"))
|
|
|
|
;; Org Latex Preview Scale
|
|
; Automatically toggle Org mode LaTeX fragment previews as the cursor enters and exits them
|
|
(use-package org-fragtog
|
|
:ensure t
|
|
:after org
|
|
:config
|
|
(add-hook 'org-mode-hook 'org-latex-preview)
|
|
(add-hook 'org-mode-hook 'org-fragtog-mode)
|
|
(setq org-format-latex-options (plist-put org-format-latex-options :scale 3.0)))
|
|
|
|
|
|
;; Emacs minibuffer configurations.
|
|
(use-package emacs
|
|
:ensure nil
|
|
:custom
|
|
(tab-always-indent 'complete)
|
|
|
|
;; Enable context menu. `vertico-multiform-mode' adds a menu in the minibuffer
|
|
;; to switch display modes.
|
|
(context-menu-mode t)
|
|
;; Support opening new minibuffers from inside existing minibuffers.
|
|
(enable-recursive-minibuffers t)
|
|
;; Hide commands in M-x which do not work in the current mode. Vertico
|
|
;; commands are hidden in normal buffers. This setting is useful beyond
|
|
;; Vertico.
|
|
(read-extended-command-predicate #'command-completion-default-include-p)
|
|
;; Do not allow the cursor in the minibuffer prompt
|
|
(minibuffer-prompt-properties
|
|
'(read-only t cursor-intangible t face minibuffer-prompt)))
|
|
|
|
|
|
;; Doom Theme
|
|
(use-package doom-themes
|
|
:ensure t
|
|
:config
|
|
;; Global settings (defaults)
|
|
(setq
|
|
doom-themes-enable-bold t ; if nil, bold is universally disabled
|
|
doom-themes-enable-italic t) ; if nil, italics is universally disabled
|
|
|
|
(load-theme 'doom-gruvbox-light t))
|
|
|
|
|
|
;; Autocompletion configuration
|
|
;(use-package ido-vertical-mode
|
|
; :ensure t
|
|
; :config (ido-vertical-mode 1))
|
|
|
|
;; Enable Vertico.
|
|
(use-package vertico
|
|
:ensure t
|
|
;;:custom
|
|
;; (vertico-scroll-margin 0) ;; Different scroll margin
|
|
;; (vertico-count 20) ;; Show more candidates
|
|
;; (vertico-resize t) ;; Grow and shrink the Vertico minibuffer
|
|
;; (vertico-cycle t) ;; Enable cycling for `vertico-next/previous'
|
|
:config
|
|
(define-key vertico-map (kbd "C-k") 'vertico-previous)
|
|
(define-key vertico-map (kbd "C-j") 'vertico-next)
|
|
:init
|
|
(vertico-mode))
|
|
|
|
|
|
;; Fuzzy matching for completion frameworks like Vertico
|
|
(use-package orderless
|
|
:ensure t
|
|
:custom
|
|
(completion-styles '(orderless flex basic))
|
|
(completion-category-overrides '((file (styles partial-completion))))
|
|
(completion-pcm-leading-wildcard t)) ;; Emacs 31: partial-completion behaves like substring
|
|
|
|
|
|
;; Enhanced commands that Vertico can make use of
|
|
(use-package consult
|
|
:ensure t
|
|
:config
|
|
(define-key global-map [remap isearch-forward] 'consult-ripgrep)
|
|
(define-key global-map [remap switch-to-buffer] 'consult-buffer)
|
|
(define-key global-map [remap list-buffers] 'consult-buffer)
|
|
(define-key global-map [remap set-fill-column] 'consult-fd)
|
|
(define-key global-map [remap org-agenda-filter] 'consult-line)
|
|
(define-key global-map [remap eshell-previous-matching-input] 'consult-history))
|
|
|
|
|
|
;; Persist history over Emacs restarts. Vertico sorts by history position.
|
|
(use-package savehist
|
|
:ensure nil
|
|
:init
|
|
(savehist-mode))
|
|
|
|
|
|
;; Corfu Autocomplete in buffer
|
|
(use-package corfu
|
|
:ensure t
|
|
:hook
|
|
(prog-mode . corfu-mode)
|
|
(html-ts-mode . corfu-mode)
|
|
(css-ts-mode . corfu-mode)
|
|
;; (shell-mode . corfu-mode)
|
|
;; (eshell-mode . corfu-mode))
|
|
:config
|
|
(setq
|
|
auto nil
|
|
corfu-preselect 'first))
|
|
|
|
;;(global-corfu-mode)
|
|
|
|
|
|
;; Evil Config
|
|
; Vim Bindings
|
|
(use-package evil
|
|
:ensure t
|
|
:bind (("<escape>" . keyboard-escape-quit))
|
|
:init
|
|
(setq evil-want-keybinding nil)
|
|
(evil-mode 1)
|
|
:config
|
|
(define-key evil-insert-state-map (kbd "C-g") 'evil-force-normal-state)
|
|
(define-key evil-motion-state-map [remap evil-search-forward] 'consult-line))
|
|
|
|
; Evil Collection, configs evil bindings for more packages
|
|
(use-package evil-collection
|
|
:after evil
|
|
:ensure t
|
|
:config
|
|
(evil-collection-init))
|
|
|
|
|
|
;; Eshell config
|
|
; Like zoxide
|
|
(use-package eshell-z
|
|
:ensure t
|
|
:after tramp
|
|
:config
|
|
(add-hook 'eshell-mode-hook
|
|
(defun my-eshell-mode-hook ()
|
|
(require 'eshell-z))))
|
|
|
|
; Bash completion commands in eshell
|
|
(use-package bash-completion
|
|
:ensure t
|
|
:init
|
|
(autoload 'bash-completion-dynamic-complete
|
|
"bash-completion"
|
|
"BASH completion hook")
|
|
(add-hook 'shell-dynamic-complete-functions
|
|
'bash-completion-dynamic-complete)
|
|
(add-hook 'eshell-mode-hook
|
|
(lambda ()
|
|
(add-hook 'completion-at-point-functions
|
|
'bash-completion-capf-nonexclusive nil t))))
|
|
|
|
; Import bash aliases to eshell
|
|
(defun eshell-load-bash-aliases ()
|
|
"Read Bash aliases and add them to the list of eshell aliases."
|
|
;; Bash needs to be run - temporarily - interactively
|
|
;; in order to get the list of aliases.
|
|
(with-temp-buffer
|
|
(call-process "bash" nil '(t nil) nil "-ci" "alias")
|
|
(goto-char (point-min))
|
|
|
|
; Bash aliases to exclude
|
|
(flush-lines "^alias magit\\|^alias oc\\|^alias z\\|^alias zi\\|^alias cd\\|^alias cdi\\|^alias sudo")
|
|
|
|
(while (re-search-forward "alias \\(.+\\)='\\(.+\\)'$" nil t)
|
|
(add-to-list 'eshell-command-aliases-list (list (match-string 1) (match-string 2))))))
|
|
|
|
;; We only want Bash aliases to be loaded when Eshell loads its own aliases,
|
|
;; rather than every time `eshell-mode' is enabled.
|
|
(add-hook 'eshell-first-time-mode-hook 'eshell-load-bash-aliases t)
|
|
|
|
; Eat is a terminal emulator that can integrate nicely with eshell, allows us to run full ncurses applications inside eshell.
|
|
(use-package eat
|
|
:ensure t
|
|
:init
|
|
;; For `eat-eshell-mode'.
|
|
(add-hook 'eshell-load-hook #'eat-eshell-mode)
|
|
|
|
;; For `eat-eshell-visual-command-mode'.
|
|
(add-hook 'eshell-load-hook #'eat-eshell-visual-command-mode))
|
|
|
|
; New create new eshell instance
|
|
(defun eshell/new ()
|
|
(interactive)
|
|
(eshell t))
|
|
|
|
;; Sudo edit command to escalate priv if need be
|
|
(use-package sudo-edit
|
|
:ensure t
|
|
:config
|
|
(add-hook 'before-save-hook 'sudo-before-save-hook))
|
|
|
|
(setq tramp-auto-save-directory "~/.emacs.d/tramp-autosave")
|
|
|
|
;; Magit
|
|
(use-package transient
|
|
:ensure t)
|
|
(use-package magit
|
|
:ensure t
|
|
:after transient)
|
|
|
|
;; Auth Source Pass - Use pass for authentication with mail
|
|
(use-package auth-source-pass
|
|
:ensure nil
|
|
:init
|
|
(auth-source-pass-enable))
|
|
|
|
;; Mu4e Mail Config
|
|
(when (executable-find "mu")
|
|
(use-package mu4e
|
|
:ensure nil
|
|
:after (auth-source-pass consult)
|
|
:config
|
|
(define-key global-map [remap mu4e-search-narrow] 'consult-line)
|
|
|
|
(setq mu4e-mu-binary (executable-find "mu"))
|
|
|
|
;; This is set to 't' to avoid mail syncing issues when using mbsync
|
|
(setq mu4e-change-filenames-when-moving t)
|
|
|
|
;; Refresh mail using isync every 10 minutes
|
|
;(setq mu4e-update-interval (* 10 60))
|
|
(setq mu4e-get-mail-command "mbsync -a")
|
|
(setq mu4e-maildir "~/Mail")
|
|
|
|
;; Sending mail function
|
|
(setq message-send-mail-function 'smtpmail-send-it)
|
|
|
|
;; Make sure plain text mails flow correctly for recipients
|
|
(setq mu4e-compose-format-flowed t)
|
|
|
|
;; Use completing read AKA vertico
|
|
(setq mu4e-completing-read-function #'completing-read)
|
|
|
|
;; Immediately send SMTP with credentials
|
|
(setq smtpmail-servers-requiring-authorization "*")
|
|
|
|
(setq mu4e-contexts
|
|
(list
|
|
;; Work account
|
|
(make-mu4e-context
|
|
:name "A CSpark Work"
|
|
:match-func
|
|
(lambda (msg)
|
|
(when msg
|
|
(string-prefix-p "/work-cspark" (mu4e-message-field msg :maildir))))
|
|
:vars '((user-mail-address . "work@cspark.dev")
|
|
(user-full-name . "Curt Spark (Work)")
|
|
(smtpmail-smtp-server . "mail.cspark.dev")
|
|
(smtpmail-smtp-user . "work@cspark.dev")
|
|
(smtpmail-smtp-service . 587)
|
|
(smtpmail-stream-type . starttls)
|
|
(mu4e-compose-signature . "- Curt")
|
|
(mu4e-inbox-folder . "/work-cspark/Inbox")
|
|
(mu4e-drafts-folder . "/work-cspark/Drafts")
|
|
(mu4e-sent-folder . "/work-cspark/Sent Mail")
|
|
(mu4e-trash-folder . "/work-cspark/Trash")))
|
|
|
|
;; Services account
|
|
(make-mu4e-context
|
|
:name "B CSpark Services"
|
|
:match-func
|
|
(lambda (msg)
|
|
(when msg
|
|
(string-prefix-p "/services-cspark" (mu4e-message-field msg :maildir))))
|
|
:vars '((user-mail-address . "services@cspark.dev")
|
|
(user-full-name . "Curt Spark (services)")
|
|
(smtpmail-smtp-server . "mail.cspark.dev")
|
|
(smtpmail-smtp-user . "services@cspark.dev")
|
|
(smtpmail-smtp-service . 587)
|
|
(smtpmail-stream-type . starttls)
|
|
(mu4e-compose-signature . "- Curt")
|
|
(mu4e-inbox-folder . "/services-cspark/Inbox")
|
|
(mu4e-drafts-folder . "/services-cspark/Drafts")
|
|
(mu4e-sent-folder . "/services-cspark/Sent Mail")
|
|
(mu4e-trash-folder . "/services-cspark/Trash")))
|
|
|
|
;; Personal account
|
|
(make-mu4e-context
|
|
:name "C CSpark Personal"
|
|
:match-func
|
|
(lambda (msg)
|
|
(when msg
|
|
(string-prefix-p "/personal-cspark" (mu4e-message-field msg :maildir))))
|
|
:vars '((user-mail-address . "personal@cspark.dev")
|
|
(user-full-name . "Curt Spark (personal)")
|
|
(smtpmail-smtp-server . "mail.cspark.dev")
|
|
(smtpmail-smtp-user . "personal@cspark.dev")
|
|
(smtpmail-smtp-service . 587)
|
|
(smtpmail-stream-type . starttls)
|
|
(mu4e-compose-signature . "- Curt")
|
|
(mu4e-inbox-folder . "/personal-cspark/Inbox")
|
|
(mu4e-drafts-folder . "/personal-cspark/Drafts")
|
|
(mu4e-sent-folder . "/personal-cspark/Sent Mail")
|
|
(mu4e-trash-folder . "/personal-cspark/Trash")))
|
|
|
|
;; Alerts account
|
|
(make-mu4e-context
|
|
:name "D CSpark Alerts"
|
|
:match-func
|
|
(lambda (msg)
|
|
(when msg
|
|
(string-prefix-p "/alerts-cspark" (mu4e-message-field msg :maildir))))
|
|
:vars '((user-mail-address . "alerts@cspark.dev")
|
|
(user-full-name . "Curt Spark (alerts)")
|
|
(smtpmail-smtp-server . "mail.cspark.dev")
|
|
(smtpmail-smtp-user . "alerts@cspark.dev")
|
|
(smtpmail-smtp-service . 587)
|
|
(smtpmail-stream-type . starttls)
|
|
(mu4e-compose-signature . "- Curt")
|
|
(mu4e-inbox-folder . "/alerts-cspark/Inbox")
|
|
(mu4e-drafts-folder . "/alerts-cspark/Drafts")
|
|
(mu4e-sent-folder . "/alerts-cspark/Sent Mail")
|
|
(mu4e-trash-folder . "/alerts-cspark/Trash")))
|
|
|
|
;; Tuxtank Services account
|
|
(make-mu4e-context
|
|
:name "E Tuxtank Services"
|
|
:match-func
|
|
(lambda (msg)
|
|
(when msg
|
|
(string-prefix-p "/personal-tuxtank" (mu4e-message-field msg :maildir))))
|
|
:vars '((user-mail-address . "personal@tuxtank.dev")
|
|
(user-full-name . "Tuxtank (personal)")
|
|
(smtpmail-smtp-server . "mail.tuxtank.dev")
|
|
(smtpmail-smtp-user . "personal@tuxtank.dev")
|
|
(smtpmail-smtp-service . 587)
|
|
(smtpmail-stream-type . starttls)
|
|
(mu4e-compose-signature . "- Tuxtank")
|
|
(mu4e-inbox-folder . "/personal-tuxtank/Inbox")
|
|
(mu4e-drafts-folder . "/personal-tuxtank/Drafts")
|
|
(mu4e-sent-folder . "/personal-tuxtank/Sent Mail")
|
|
(mu4e-trash-folder . "/personal-tuxtank/Trash")))
|
|
|
|
;; Tuxtank Alerts account
|
|
(make-mu4e-context
|
|
:name "F Tuxtank Alerts"
|
|
:match-func
|
|
(lambda (msg)
|
|
(when msg
|
|
(string-prefix-p "/alerts-tuxtank" (mu4e-message-field msg :maildir))))
|
|
:vars '((user-mail-address . "alerts@tuxtank.dev")
|
|
(user-full-name . "Tuxtank (alerts)")
|
|
(smtpmail-smtp-server . "mail.tuxtank.dev")
|
|
(smtpmail-smtp-user . "alerts@tuxtank.dev")
|
|
(smtpmail-smtp-service . 587)
|
|
(smtpmail-stream-type . starttls)
|
|
(mu4e-compose-signature . "- Tuxtank")
|
|
(mu4e-inbox-folder . "/alerts-tuxtank/Inbox")
|
|
(mu4e-drafts-folder . "/alerts-tuxtank/Drafts")
|
|
(mu4e-sent-folder . "/alerts-tuxtank/Sent Mail")
|
|
(mu4e-trash-folder . "/alerts-tuxtank/Trash")))))))
|
|
|
|
|
|
;(setq mu4e-maildir-shortcuts
|
|
; '(("/Gmail/Inbox" . ?i)
|
|
; ("/Gmail/[Gmail]/Sent Mail" . ?s)
|
|
; ("/Gmail/[Gmail]/Trash" . ?t)
|
|
; ("/Gmail/[Gmail]/Drafts" . ?d)
|
|
; ("/Gmail/[Gmail]/All Mail" . ?a)))
|
|
|
|
|
|
|
|
;; Emacs everywhere - Use emacs for any text input
|
|
(use-package emacs-everywhere
|
|
:ensure t)
|
|
|
|
;; Parinfer mode - We will use conventional 2 spaces instead of tabs for lisp
|
|
(use-package parinfer-rust-mode
|
|
:ensure (:host github :repo "justinbarclay/parinfer-rust-mode")
|
|
:hook
|
|
((emacs-lisp-mode . (lambda()
|
|
(setq-local tab-width 2)
|
|
(indent-tabs-mode -1)
|
|
(parinfer-rust-mode)))
|
|
(common-lisp-mode . (lambda()
|
|
(setq-local tab-width 2)
|
|
(indent-tabs-mode -1)
|
|
(parinfer-rust-mode)))))
|
|
|
|
;; Rainbow delimiters
|
|
(use-package rainbow-delimiters
|
|
:ensure t
|
|
:hook
|
|
(prog-mode . rainbow-delimiters-mode))
|
|
|
|
;; Treesit Config
|
|
(use-package treesit
|
|
:ensure nil
|
|
:commands (treesit-install-language-grammar nf/treesit-install-all-languages)
|
|
:init
|
|
(setq treesit-language-source-alist
|
|
'((bash . ("https://github.com/tree-sitter/tree-sitter-bash"))
|
|
(c . ("https://github.com/tree-sitter/tree-sitter-c"))
|
|
(cpp . ("https://github.com/tree-sitter/tree-sitter-cpp"))
|
|
(css . ("https://github.com/tree-sitter/tree-sitter-css"))
|
|
(cmake . ("https://github.com/uyha/tree-sitter-cmake"))
|
|
(go . ("https://github.com/tree-sitter/tree-sitter-go"))
|
|
(html . ("https://github.com/tree-sitter/tree-sitter-html"))
|
|
(javascript . ("https://github.com/tree-sitter/tree-sitter-javascript"))
|
|
(json . ("https://github.com/tree-sitter/tree-sitter-json"))
|
|
(julia . ("https://github.com/tree-sitter/tree-sitter-julia"))
|
|
(lua . ("https://github.com/Azganoth/tree-sitter-lua"))
|
|
(make . ("https://github.com/alemuller/tree-sitter-make"))
|
|
(ocaml . ("https://github.com/tree-sitter/tree-sitter-ocaml" "master" "ocaml/src"))
|
|
(python . ("https://github.com/tree-sitter/tree-sitter-python"))
|
|
(php . ("https://github.com/tree-sitter/tree-sitter-php"))
|
|
(typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src"))
|
|
(tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src"))
|
|
(ruby . ("https://github.com/tree-sitter/tree-sitter-ruby"))
|
|
(rust . ("https://github.com/tree-sitter/tree-sitter-rust"))
|
|
(sql . ("https://github.com/m-novikov/tree-sitter-sql"))
|
|
(toml . ("https://github.com/tree-sitter/tree-sitter-toml"))
|
|
(zig . ("https://github.com/GrayJack/tree-sitter-zig"))))
|
|
|
|
:config ;; Credit to https://github.com/Nathan-Furnal/dotemacs/blob/df9b845563a84a927ff762e172334cf772253a44/init.el#L1154
|
|
(defun nf/treesit-install-all-languages ()
|
|
"Install all languages specified by `treesit-language-source-alist'."
|
|
(interactive)
|
|
(let ((languages (mapcar 'car treesit-language-source-alist)))
|
|
(dolist (lang languages)
|
|
(treesit-install-language-grammar lang)
|
|
(message "`%s' parser was installed." lang)
|
|
(sit-for 0.75)))))
|
|
|
|
(setq treesit-font-lock-level 4)
|
|
; Remap basic modes to treesit equivalent
|
|
(use-package bash-ts-mode
|
|
:ensure nil
|
|
:mode "\\.sh\\'")
|
|
(use-package c-ts-mode
|
|
:ensure nil
|
|
:mode "\\.c\\'")
|
|
(use-package rust-ts-mode
|
|
:ensure nil
|
|
:mode "\\.rs\\'")
|
|
(use-package swift-ts-mode
|
|
:ensure t
|
|
:mode "\\.swift\\'")
|
|
(use-package nix-ts-mode
|
|
:ensure nil
|
|
:mode "\\.nix\\'")
|
|
(use-package html-ts-mode
|
|
:ensure nil
|
|
:mode "\\.html\\'")
|
|
(use-package css-ts-mode
|
|
:ensure nil
|
|
:mode "\\.css\\'")
|
|
(use-package js-ts-mode
|
|
:ensure nil
|
|
:mode "\\.js\\'")
|
|
(use-package typescript-ts-mode
|
|
:ensure nil
|
|
:mode "\\.ts\\'")
|
|
(use-package tsx-ts-mode
|
|
:ensure nil
|
|
:mode "\\.tsx\\'")
|
|
;(use-package emacs-lisp-ts-mode
|
|
; :ensure t)
|
|
; Remap base modes to their treesitter counterpart
|
|
(setq major-mode-remap-alist
|
|
'(
|
|
;(emacs-lisp-mode . emacs-lisp-ts-mode)
|
|
|
|
(c-mode . c-ts-mode)
|
|
(rust-mode . rust-ts-mode)
|
|
(rustic-mode . rust-ts-mode)
|
|
(python-mode . python-ts-mode)
|
|
(html-mode . html-ts-mode)
|
|
(css-mode . css-ts-mode)
|
|
(js-mode . js-ts-mode)
|
|
(javascript-mode . js-ts-mode)))
|
|
|
|
|
|
|
|
;; Programming treesit style config
|
|
; Enforcing tabs as programming style
|
|
(add-hook 'prog-mode-hook
|
|
(lambda ()
|
|
(setq-local tab-width custom-tab-width)
|
|
(setq-local indent-tabs-mode 't)))
|
|
(add-hook 'nix-ts-mode-hook
|
|
(lambda ()
|
|
(setq-local nix-ts-mode-indent-offset custom-tab-width)))
|
|
(add-hook 'c-ts-mode-hook
|
|
(lambda ()
|
|
(setq-local c-ts-mode-indent-style 'linux)
|
|
(setq-local c-ts-mode-indent-offset custom-tab-width)
|
|
(c-ts-mode-toggle-comment-style -1)))
|
|
(add-hook 'rust-ts-mode-hook
|
|
(lambda ()
|
|
(setq-local rust-ts-mode-indent-offset custom-tab-width)))
|
|
|
|
;; Flymake Configuration
|
|
(use-package flymake
|
|
:ensure nil
|
|
:hook
|
|
(prog-mode . flymake-mode)
|
|
(emacs-lisp-mode . flymake-mode))
|
|
|
|
; Flyover for nice in buffer flymake error/warning messages.
|
|
(use-package flyover
|
|
:ensure t
|
|
:hook
|
|
(flymake-mode . flyover-mode)
|
|
:custom
|
|
;; Checker settings
|
|
(flyover-checkers '(flymake))
|
|
|
|
;; Display mode (controls cursor-based visibility)
|
|
(flyover-display-mode 'show-only-on-same-line)
|
|
|
|
;; Completion integration
|
|
(flyover-hide-during-completion t))
|
|
|
|
|
|
;; LSP Configuration
|
|
(use-package eglot
|
|
:hook
|
|
(((
|
|
bash-ts-mode
|
|
c-ts-mode
|
|
rust-ts-mode
|
|
swift-ts-mode
|
|
nix-ts-mode
|
|
html-ts-mode
|
|
css-ts-mode
|
|
js-ts-mode
|
|
typescript-ts-mode
|
|
tsx-ts-mode)
|
|
. eglot-ensure))
|
|
:custom
|
|
(eglot-ignored-server-capabilities '(:documentOnTypeFormattingProvider)))
|
|
|
|
|
|
;; HTML Emmet Snippets
|
|
(use-package emmet-mode
|
|
:ensure t
|
|
:hook
|
|
(typescript-ts-mode . emmet-mode)
|
|
(tsx-ts-mode . emmet-mode)
|
|
(html-ts-mode . emmet-mode)
|
|
(css-ts-mode . emmet-mode)
|
|
:config
|
|
(setq emmet-indentation custom-tab-width))
|
|
|
|
|
|
;; JS Prettier Mode
|
|
(use-package prettier-js
|
|
:ensure t
|
|
:hook
|
|
(js-ts-mode . prettier-js-mode)
|
|
(typescript-ts-mode . prettier-js-mode)
|
|
(tsx-ts-mode . prettier-js-mode)
|
|
:config
|
|
(setq prettier-js-use-modules-bin t))
|
|
|
|
|
|
(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.
|
|
'(auth-source-save-behavior nil)
|
|
'(package-selected-packages nil)
|
|
'(smtpmail-smtp-server "smtp.cspark.dev")
|
|
'(smtpmail-smtp-service 25))
|
|
(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.
|
|
|