;;; init.el --- my emacs configuration -*- lexical-binding: t; -*- ;; Todo: ;; - Look at completion-preview-mode ;; - Look at grep-use-headings ;; - Look at elpa-openwith ;; (profiler-start 'cpu+mem) (add-to-list 'load-path (expand-file-name (concat user-emacs-directory "site-lisp"))) (add-to-list 'load-path (expand-file-name "~/Documents/Projects/2024-10-08 Ctrlj")) (add-to-list 'load-path (expand-file-name "~/Documents/Projects/2024-09-17 Tubthumping theme")) (add-to-list 'exec-path "/home/noa/.config/Scripts") (use-package use-package :custom (use-package-compute-statistics t)) ;; Give me stats on garbage collection and startup time (setopt garbage-collection-messages t) (add-hook 'emacs-startup-hook #'(lambda () (message (format "Initialised in %s seconds with %s garbage collections." (emacs-init-time) gcs-done)))) ;; Use the gcmh to collect garbage when i'm not using emacs (use-package gcmh :disabled t :ensure t :custom (gcmh-mode t)) ;;; Modern keybindings ;; A lot of people say that you get used to emacs keybindings over time, and this is true. But i find it hard to maintain two sets of keybindings in my head: those for emacs, and those for everything else. So i think that it's best to make emacs use the same bindings as everything else. For now, we do that with wakib mode. (use-package wakib-keys :disabled t :ensure t :custom (wakib-keys t) :hook ((after-change-major-mode . wakib-update-major-mode-map) (menu-bar-update . wakib-update-minor-mode-maps)) :bind (:map isearch-mode-map ("C-f" . isearch-repeat-forward) ("C-S-f" . isearch-repeat-backward) ("M-;" . isearch-repeat-forward) ("M-:" . isearch-repeat-backward) ("C-v" . isearch-yank-kill) ("M-d" . isearch-delete-char))) ;; It is often useful to be able to run a command while i am already in the process of running a command in the minibuffer. This is rarely two extended commands; usually it is completion. (use-package mb-depth :custom (minibuffer-depth-indicate-mode t)) ;; This is my emacs theme. It's a monochrome theme which, unlike most monochrome themes, really does have only two colours. I define a few faces, and set every other face as one of them. There are a few things i want to do with it before i make it properly public: make the colours configurable and able to update on the fly, and in general iron out some of the janky parts. A few things defined it are quite specific to this configuration, like the way i define the borders for the tab and header bars, and there is no mode line configuration because i don't use it. (use-package tubthumping-theme :config (load-theme 'tubthumping t)) ;;; Fonts ;; Using a proportional font is the right way to do things, but emacs is very old and comes from a time before the innovation of legibility. As a result, there are some things that require a monospaced font, so i set one here. (custom-set-faces '(default ((t (:family "Noto Serif" :height 120)))) '(variable-pitch ((t (:family "Noto Serif" :height 120)))) '(fixed-pitch ((t (:family "Noto Sans Mono" :height 120))))) ;; Use simplified not korean hanzi (when (display-graphic-p) (dolist (charset '(han cjk-misc)) (set-fontset-font t charset (font-spec :family "Noto Serif CJK SC")))) ;; Prioritise fsd and noto emoji over coloured variants (when (display-graphic-p) (set-fontset-font t 'emoji (font-spec :family "FSD Emoji") nil 'prepend) (set-fontset-font t 'emoji (font-spec :family "Noto Emoji") nil 'append)) ;; While we're here, let's set up emoji input. (use-package emoji :bind ("C-." . emoji-search)) ;; Update the calendar. We want weeks to start on a monday, the first day of the week. Holidays should be highlighted, and the date format should put the year first. (use-package calendar :defer t :custom (calendar-week-start-day 1) (calendar-date-style 'iso) :config ;; Ensure the calendar always displays at the bottom of the screen, rather than wrapping weirdly and looking bad when it shows up in a side window. (add-to-list 'display-buffer-alist '("\\*Calendar\\*" (display-buffer-in-side-window) (side . bottom)))) ;; This is my own version of fixed-pitch, which has some changes to it. No hooks are added by default. Updating the whitelist automatically applies the hooks. And there is no functionality for changing the cursor type. (use-package fixed-pitch :custom (fixed-pitch-whitelist-hooks '(calendar-mode-hook dired-mode-hook ibuffer-mode-hook magit-mode-hook profiler-report-mode-hook jabber-roster-mode-hook mu4e-headers-mode-hook proced-mode-hook rmail-summary-mode-hook ebib-index-mode-hook which-key-init-buffer-hook ebib-entry-mode-hook))) (use-package transient :defer t :custom ;; Ensure that transients look nice with a variable pitch font. (transient-align-variable-pitch t)) ;; Squeeze text into a more legible sliver. (use-package visual-fill-column :ensure t :custom (visual-fill-column-enable-sensible-window-split t) (visual-fill-column-fringes-outside-margins nil) ; Keep fringes on the inside so relevant icons are in the right place (visual-fill-column-center-text t) :hook ((text-mode . visual-line-fill-column-mode) (eww-after-render . visual-line-fill-column-mode)) ) ;; (advice-add 'text-scale-adjust :after #'visual-fill-column-adjust) ;; Doesn't indent nicely with proportional fonts ;; (use-package adaptive-wrap :ensure t) ;; (add-hook 'visual-fill-column-mode-hook #'visual-wrap-prefix-mode) ;; At the moment, explicitly disabling the menu bar and tool bar does nothing, because i already set there to be no lines displayed for the tool and menu bars in my early-init.el file. (setopt menu-bar-mode nil tool-bar-mode nil) ;; Make tooltip information appear consistently in the echo area (setopt tooltip-mode nil) ;; (Almost) immediately show which chords in a key sequence i have already pressed. (setopt echo-keystrokes 0.1) (use-package paren :custom (show-paren-mode t) (show-paren-when-point-in-periphery t) ; Highlight nearby paren if only whitespace separates paren from point (show-paren-when-point-inside-paren t) ; Highlight paren if point is inside, not just on ) ;; Syntax highlighting (setopt global-font-lock-mode t) (setopt font-lock-maximum-decoration nil) ;;; Further options (setopt inhibit-startup-screen t mouse-drag-and-drop-region nil mouse-yank-at-point t ;; deleting should be an explicit action delete-selection-mode nil) ;; Shift click to select region with the mouse (https://christiantietze.de/posts/2022/07/shift-click-in-emacs-to-select/) (global-set-key (kbd "S-") #'mouse-set-mark) ;; Doesn't work great with a proportional font but could still be useful. (global-set-key (kbd "C-S-") #'mouse-drag-region-rectangle) ;; Nicer tables (use-package valign :after markdown-mode :ensure t :hook ((markdown-mode . valign-mode)) :custom (valign-fancy-bar t) (valign-max-table-size 0)) ;; Markdown (use-package markdown-mode :ensure t :mode ("\\.\\(?:md\\|markdown\\|mkd\\|mdown\\|mkdn\\|mdwn\\)\\'" . markdown-mode) :custom (markdown-disable-tooltip-prompt t) ; When inserting a link, only prompt for url and link text (markdown-enable-html nil) ; I don't believe markdown should have html (markdown-hide-urls t) ; Make inline urls look a bit neater (markdown-url-compose-char ?~) ;; :hook ((markdown-mode . noa/set-buffer-name-to-markdown-title)) ) ;; Use abbrev as a simple autocorrect mode. M-x list-abbrevs for stats. ;; Check ~/.config/emacs/abbrev_defs to update any mistakes (use-package abbrev :hook (text-mode . abbrev-mode)) ;; A nicer package for spellchecking (use-package jinx :ensure t :hook (text-mode . jinx-mode) :bind ([remap ispell-word] . jinx-correct) ;; replaces ispell-word ("C-M-$" . jinx-languages) :config (put 'jinx-overlay 'mouse-face '(jinx-misspelled highlight)) ;; Use standard mouse face for jinx overlays (add-to-list 'jinx-exclude-regexps '(t "\\cc")) ;; Don't check chinese characters ) ;; Automatically creates an abbrev for words i correct, so i don't make the same mistake twice (defun jinx--add-to-abbrev (overlay word) "Add abbreviation to `global-abbrev-table'. The misspelled word is taken from OVERLAY. WORD is the corrected word." (let ((abbrev (buffer-substring-no-properties (overlay-start overlay) (overlay-end overlay)))) (message "Abbrev: %s -> %s" abbrev word) (define-abbrev global-abbrev-table abbrev word))) (advice-add 'jinx--correct-replace :before #'jinx--add-to-abbrev) (use-package help :defer t :custom (help-window-select t) ;; Make it easier to close help windows ;; When opening source files from a help window, use the same window (help-window-keep-selected t)) ;; Despite the name, eww is a delight to use for text-heavy websites. (use-package browse-url :defer t :custom (browse-url-browser-function 'eww-browse-url) (browse-url-secondary-browser-function 'browse-url-default-browser)) ;; I've had no use for cookies in eww (use-package url-cookie :defer t :custom (url-cookie-trusted-urls '()) (url-cookie-untrusted-urls '(".*"))) (use-package shr :defer t :custom (shr-cookie-policy nil) (shr-use-colors nil) ;; I like the colours i already have set (shr-max-width nil) ;; Don't insert hard linebreaks to wrap paragraphs (shr-bullet " • ") (shr-discard-aria-hidden t)) (use-package eww :defer t :custom ;; Better buffer naming for eww buffers. See the help for a function which gives the page title and the url. (eww-auto-rename-buffer 'title)) ;; Goto address mode makes urls and email address in a buffer clickable. I want these clickable links to look like links, because that's what they are. The two mouse face variables are what face is used on hover, which at the moment i ignore. It might also be worth setting them to 'highlight. (use-package goto-addr :custom (global-goto-address-mode nil) (goto-address-mail-face 'link) (goto-address-mail-mouse-face 'highlight) (goto-address-url-face 'link) (goto-address-url-mouse-face 'highlight)) (use-package eldoc :custom (global-eldoc-mode t)) ;; Use a bar cursor and blink it and don't stop blinking it. (setopt cursor-type 'bar blink-cursor-mode t blink-cursor-interval 0.7) ;; I have quite a bit of storage and also make bad decisions regularly ;; People who have used computers in the last forty years or so will likely be familiar with this innovation. (setopt delete-by-moving-to-trash t) (use-package dired :defer t :custom (dired-recursive-deletes 'always) ;; Don't ask me things (dired-recursive-copies 'always) ;; Don't ask me things (dired-dwim-target t) ;; Synergy between two dired windows ;; -l is required by dired ;; -a to also show dotfiles ;; -v to sort numebrs properly ;; -F to visually distinguish different types of file ;; -h for human readable file sizes ;; I won't explain the meaning of the long flag. (dired-listing-switches "-alvFh --group-directories-first") ;; By default, don't show dired details :hook (dired-mode . dired-hide-details-mode)) ;; Show the recursive size of directories (use-package dired-du :disabled t :ensure t :after dired :custom (dired-du-size-format t) :hook (dired-mode . dired-du-mode)) ;; Some tramp settings. (setopt remote-file-name-inhibit-locks t) (use-package tramp :defer t :custom (tramp-inline-compress-start-size 1000) (tramp-verbose 3)) ;; (add-to-list 'tramp-remote-path 'tramp-own-remote-path) ;; I only use git, and this apparently speeds up tramp. (use-package vc-hooks :after vc :custom (vc-handled-backends '(Git))) ;; (setopt vc-handled-backends '(Git RCS CVS SVN SCCS SRC Bzr Hg)) ;; It seems that tramp can also be made faster with these .ssh/config settings. ;; Host * ;; ControlMaster auto ;; ControlPath ~/.ssh/master-%h:%p ;; ControlPersist 10m ;; ForwardAgent yes ;; ServerAliveInterval 60 ;; Don't override display actions when i manually initiate a buffer switch. (setopt switch-to-buffer-obey-display-actions t) ;; History (setopt history-length 250 kill-ring-max 25) (setopt savehist-file "~/.config/emacs/savehist") (setopt savehist-additional-variables '(kill-ring command-history set-variable-value-history custom-variable-history query-replace-history read-expression-history minibuffer-history read-char-history face-name-history bookmark-history file-name-history)) (setopt savehist-mode t) (setopt window-divider-mode t) (setopt window-divider-default-right-width 1) (setopt window-divider-default-bottom-width 1) (setopt window-divider-default-places t) ;; Taken from configuration for the vertico stack: ;; Add prompt indicator to `completing-read-multiple'. ;; We display [CRM], e.g., [CRM,] if the separator is a comma. (defun 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 #'crm-indicator) ;; Do not allow the cursor in the minibuffer prompt (setopt minibuffer-prompt-properties '(read-only t cursor-intangible t face minibuffer-prompt)) (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) ;; Support opening new minibuffers from inside existing minibuffers. (setopt enable-recursive-minibuffers t) ;; Whether to drop into the debugger on any error. This seems cool, but in practice is a bit annoying. (setopt debug-on-error nil) ;; Hide commands in M-x which do not work in the current mode. (setopt read-extended-command-predicate 'command-completion-default-include-p) (setopt recentf-max-menu-items 25 recentf-save-file "~/.config/emacs/recentf" recentf-mode t bookmark-default-file "~/.config/emacs/bookmarks") ;; My brain is not ready for advanced emacs undo (setopt undo-no-redo t) (global-unset-key (kbd "C-z")) (global-set-key (kbd "C-z") 'undo) (global-set-key (kbd "C-S-z") 'undo-redo) ;; Saving ;; Backups are pointless in long emacs sessions, but autosaves are useful. (setopt remote-file-name-inhibit-auto-save t) (setopt remote-file-name-inhibit-auto-save-visited t) (setopt backup-directory-alist '(("." . "~/.config/emacs/backups/")) make-backup-files nil backup-by-copying t create-lockfiles nil auto-save-mode t auto-save-interval 6 ;; every six keystrokes auto-save-timeout 5 ;; every 5 seconds auto-save-default t auto-save-no-message t save-silently t version-control t ;; this will auto save to the current file auto-save-visited-mode t) (add-hook 'focus-out-hook (lambda () (interactive) (save-some-buffers t))) (add-hook 'mouse-leave-buffer-hook (lambda () (interactive) (save-some-buffers t))) ;; Unfill commands (defun unfill-paragraph () "Takes a multi-line paragraph and makes it into a single line of text." (interactive) (let ((fill-column (point-max))) (fill-paragraph nil))) (global-set-key (kbd "M-Q") #'unfill-paragraph) ;; C-l from top to bottom (setopt recenter-positions '(top middle bottom)) ;; Always give me a line of text when i'm near the edges of the screen (setopt scroll-margin 1) ;; This doesn't work well sometimes for some reason, so i've disabled it for now. ;; (setopt pixel-scroll-precision-mode t ;; pixel-scroll-precision-use-momentum t) ;; Remember my position in files (setopt save-place-mode t) ;; Use single character abbreviations to answer prompts. (setopt read-answer-short t) (setopt use-short-answers t) ;; Disable disabled commands (setq disabled-command-function nil) ;; Don't save changes in the customize interface (setopt custom-file (make-temp-file "custom")) ;; Scroll along with text in compilation mode, and stop scrolling at the first error. (setopt compilation-scroll-output 'first-error) ;; Don't advertise gnu on startup (setq inhibit-startup-echo-area-message "noa") ;; #userfreedom ;; Better buffer naming (setopt uniquify-after-kill-buffer-p t uniquify-buffer-name-style 'forward uniquify-ignore-buffers-re "^\\*" uniquify-separator "/") ;; Emacs server ;; (unless (server-running-p) (server-start))) ;; This puts some help in the minibuffer when we leave the point on some interactive text. (setopt help-at-pt-display-when-idle 'never) ;; Better support for long lines. (setopt global-so-long-mode t) ;; This will stop us being prompted before killing a buffer with a running process: (setopt kill-buffer-query-functions (remq 'process-kill-buffer-query-function kill-buffer-query-functions)) ;; Automatically revert buffers when they change on disk. This doesn't apply to tramp. (setopt global-auto-revert-mode t) (setopt global-auto-revert-non-file-buffers t) ;; This behaviour changes how we visit symlinks. (setopt find-file-visit-truename t) (setopt vc-follow-symlinks 'ask) ;; Clicking around ;; Allow for slightly sloppier clicking. (setopt mouse-prefer-closest-glyph t) (use-package consult :ensure t :bind (([remap switch-to-buffer] . consult-buffer) ([remap yank-pop] . consult-yank-pop) ([remap goto-line] . consult-goto-line) ([remap imenu] . consult-imenu) ([remap info] . consult-info) ([remap repeat-complex-command] . consult-complex-command) ([remap bookmark-jump] . consult-bookmark)) :custom ;; Use consult for completion at point (completion-in-region-function 'consult-completion-in-region)) ;; Annotations for completing-read ;; (package-ensure 'marginalia) (use-package marginalia :ensure t :defer t :custom (marginalia-mode t) (marginalia-max-relative-age most-positive-fixnum) ;; Always show the relative age of file ) ;; Minibuffer candidate completion ;; Display completion candidates vertically (use-package vertico :ensure t :custom (vertico-mode t) (vertico-count 12) ;; Use about half the screen to show candidates (vertico-group-format #("%s " 0 3 (face vertico-group-title))) ;; Don't put a vertical line across group titles (vertico-cycle t)) ;; Interact with vertico with the mouse. (use-package vertico-mouse :after vertico :custom (vertico-mouse-mode t)) ;; More comfortable directory navigation (use-package vertico-directory :after vertico :bind (:map vertico-map ("RET" . vertico-directory-enter) ("" . vertico-directory-delete-char) ("C-" . vertico-directory-delete-word)) ;; If i type ~/ etc in a find-file prompt, get rid of the preceding directory names for a cleaner look. :hook (rfn-eshadow-update-overlay . vertico-directory-tidy)) ;; Some settings for nicer completion with the default emacs completion buffer. I don't use this, because i use vertico. ;; (setopt completion-auto-help 'lazy ;; completion-auto-select 'second-tab ;; completion-show-help nil ;; completions-sort nil ;; completions-header-format nil) ;; Completion styles ;; When given a prompt to select from a list of candidates, there are quite a lot of things we can tweak to improve the experience. ;; I don't actually know if these make any difference when i've specified a different completion style. (setopt read-buffer-completion-ignore-case t) (setopt read-file-name-completion-ignore-case t) (setopt completion-ignore-case t) ;; Basic matches candidates with the same text before the point, and the text after the point as a substring. ;; Orderless takes any number of space separated components and displays candidates that much every component in any order. (use-package orderless :ensure t :custom (completion-styles '(orderless basic)) (completion-category-overrides '((file (styles basic partial-completion))))) ;; Make leading whitespace a uniform width, so indentation still works with proportional fonts (require 'elastic-indent) (add-hook 'prog-mode-hook #'elastic-indent-mode) ;; Change the width of tab characters within lines to make subsequent lines form a table-like layout. (require 'elastic-table) (add-hook 'prog-mode-hook #'elastic-table-mode) ;; Use tab for completion if the region is already indented (setopt tab-always-indent 'complete) ;; Indenting lisp with tabs is horrible. H/t acdw (defvar space-indent-modes '(emacs-lisp-mode lisp-interaction-mode lisp-mode scheme-mode python-mode) "Modes to indent with spaces, not tabs.") (add-hook 'prog-mode-hook (defun indent-tabs-mode-maybe () (setq indent-tabs-mode (if (apply #'derived-mode-p space-indent-modes) nil t)))) ;; Make sentence navigation commands work for people who are wrong (setopt sentence-end-double-space nil) ;; If i write a script, i will always run chmod +x after saving it. This command means i don't have to do that. (add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p) ;; We are on a unix system, so it makes sense to end files in the unix system way. I'm surprised this isn't the default. (setopt require-final-newline t) ;; Zap up to char (global-set-key (kbd "M-z") 'zap-up-to-char) ;; Insert date and time at point ;; Sometimes it's useful to be able to add a timestamp. I use this for notes. Use the same binding as notepad.exe. (defun noa/insert-date-time () (interactive) (insert (format-time-string "<%Y-%m-%d>"))) (global-set-key (kbd "") 'noa/insert-date-time) ;; Improve incremental search (use-package isearch :bind (:map isearch-mode-map ("" . noa/isearch-done-goto-start) ; always put point at the beginning of the match ("C-g" . isearch-cancel) ; always quit on C-g ("C-o" . isearch-occur)) :init (defun noa/isearch-done-goto-start (&optional nopush edit) "End isearch at the start of the match." (interactive) (funcall #'isearch-done nopush edit) (when isearch-forward (goto-char isearch-other-end))) :custom (isearch-lax-whitespace t) (isearch-lazy-count t) (isearch-allow-motion t) (isearch-repeat-on-direction-change t) (isearch-wrap-pause 'no)) ;; I don't like the fact that isearch doesn't respect the minibuffer (use-package isearch-mb :ensure t :custom (isearch-mb-mode t)) (use-package visual-regexp :ensure t) ;; Make window management commands easier to press (global-set-key (kbd "M-o") 'other-window) (global-set-key (kbd "M-1") 'delete-other-windows) (global-set-key (kbd "M-2") 'split-window-below) (global-set-key (kbd "M-3") 'split-window-right) (global-set-key (kbd "M-0") 'delete-window) (global-set-key (kbd "C-x k") 'kill-current-buffer) ;; Window management ;; My computer has a small screen, so i find that it's more beneficial for me to split the frame into columns, so i get more context. However, splitting in this way only gives me a (window-width) of 61, so emacs will always split into vertically stacked windows. By setting this to 80, the first split should always be vertical. (setopt split-width-threshold 80) ;; Full text search of every file in my home directory. (defun noa/consult-rg-home () (interactive) (consult-ripgrep "~/")) (global-set-key (kbd "M-") #'noa/consult-rg-home) (setopt shell-file-name "/bin/sh") (defun snarf-song (url) (interactive "sYoutube url:") (async-shell-command (concat "yt-dlp -x --audio-format=mp3 -o " (shell-quote-argument "~/media/music/%(title)s [%(id)s].%(ext)s") " " (shell-quote-argument url)))) ;;; Other (setopt confirm-kill-emacs 'y-or-n-p) (global-set-key (kbd "C-=") #'calc) ;;; Email ;; I keep coming back to rmail, despite its many, many warts. (use-package rmail :custom (rmail-primary-inbox-list (directory-files "~/Documents/Library/Mail/inbox" t "^[^\.]")) (rmail-file-name "~/Documents/Library/Mail/rmail.mbox") (rmail-user-mail-address-regexp (rx "noa@noa.pub")) (rmail-mime-prefer-html nil) (rmail-mime-attachment-dirs-alist '(("" "~/media"))) (rmail-displayed-headers (rx bol (or "To" "Cc" "From" "Date" "Subject") ":")) (rmail-secondary-file-directory "~/Documents/Library/Mail/archive/") (rmail-secondary-file-regexp "\\.mbox\\'") (rmail-delete-after-output t) (rmail-default-file "~/Documents/Library/Mail/archive/") (mail-dont-reply-to-names rmail-user-mail-address-regexp) (rmail-display-summary nil) (rmail-redisplay-redisplay-summary t) (rmail-summary-line-count-flag nil) (rmail-summary-window-size 12) :hook ((rmail-show-message . visual-line-fill-column-mode))) (use-package message :defer t :init (defun noa/message-default-headers () (format "Fcc: ~/Documents/Library/Mail/outbox/%s.mbox" (format-time-string "%Y-%m"))) :custom (message-default-headers #'noa/message-default-headers) (message-fill-column nil) ;; Don't enable auto-fill (user-full-name "noa") (user-mail-address "noa@noa.pub") (message-signature t) (message-signature-file "~/.config/signature") (message-send-mail-function 'message-send-mail-with-sendmail) (sendmail-program (executable-find "msmtpq")) (message-sendmail-extra-arguments '("--read-envelope-from")) (message-sendmail-envelope-from 'header) (message-kill-buffer-on-exit t) (message-sendmail-f-is-evil t) (message-forward-as-mime t) (message-interactive t) (message-auto-save-directory "~/Documents/Library/Mail/drafts")) ;; Environment variables (setenv "PAGER" "cat") (setenv "TERM" "dumb") (setenv "NO_COLOR") (setenv "GPG_AGENT_INFO" nil) ;; Dictionary ;; Emacs has built in support for interfacing with dictd. With dictd and some dictionaries installed on debian, this works fine out of the box. ;; Unfortunately, dictionaries in this format tend to be hard wrapped and there isn't a lot of coverage outside of english (setopt dictionary-search-interface nil) ;; Dictionary tooltip mode lets me hover over a word to view the definition. (setopt dictionary-tooltip-mode t) ;; Unsorted ;; Just a few settings i haven't put into another category yet. (setopt save-interprogram-paste-before-kill t mouse-yank-at-point t require-final-newline t load-prefer-newer t ediff-window-setup-function 'ediff-setup-windows-plain) ;;; Bibliography management (use-package ebib :ensure t :defer t :custom (ebib-bibtex-dialect 'biblatex) (ebib-index-columns '(("Author/Editor" 40 t) ("Year" 6 t) ("Title" 50 t) ("Entry Key" 40 t))) ;; Put notes in my markdown notes directory. I still need to find a way to make ebib-notes-name-transform-function return the appropriate date-based filename format. (ebib-notes-storage 'one-file-per-note) (ebib-notes-directory "~/Documents/Notes/References") (ebib-notes-show-note-method 'all) (ebib-notes-file-extension "md") (ebib-notes-template "# %T\n\n%%?") ) ;; https://juanjose.garciaripoll.com/blog/managing-bibliographies-from-emacs/index.html (defun noa/yank-buffer-file-name () (interactive) (when (buffer-file-name) (kill-new (file-name-nondirectory (buffer-file-name))))) (use-package ctrlj :init (global-unset-key (kbd "C-j")) :bind* (("" . ctrlj/open-note) ("C-j C-j" . ctrlj/open-note) ("C-j C-n" . ctrlj/new-note) ("C-j C-l" . ctrlj/insert-link-to-note) ("C-j C-d" . ctrlj/open-todays-diary) ("C-j C-a" . ctrlj/view-agenda) ("C-j C-o" . ctrlj/jump-to-other-related-note))) (defun noa/consult-rg-notes () (interactive) (consult-ripgrep "~/Documents/Notes")) (global-set-key (kbd "C-j C-s") #'noa/consult-rg-notes) (defun noa/agenda () "List agenda." (interactive) (async-shell-command "~/.config/Scripts/agenda" "*agenda*")) ;; so i can search for synonyms without using the internet (use-package wordnut :if (executable-find "wordnet") :ensure t :defer t) ;; Experiment with embark (use-package embark :ensure t :bind (("C-" . embark-act) ("M-" . embark-dwim) ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings' :init ;; Optionally replace the key help with a completing-read interface (setq prefix-help-command #'embark-prefix-help-command)) (use-package embark-consult :disabled t :ensure t :hook (embark-collect-mode . consult-preview-at-point-mode)) (use-package which-key :ensure t :custom (which-key-mode t)) (use-package windmove :disabled t :bind* (("M-b" . windmove-left) ("M-f" . windmove-right) ("M-p" . windmove-up) ("M-n" . windmove-down))) ;; for whatever reason, window-combination-resize doesn't work with this (global-set-key (kbd "C-x 3") #'split-root-window-right) (setopt window-min-height 1 window-combination-resize t window-resize-pixelwise t frame-resize-pixelwise t) (use-package pdf-tools :ensure t) (use-package webjump :custom (webjump-sites '(("Instagram direct messages" . "https://www.instagram.com/direct/") ("Lute" . "http://localhost:5000/") ("SJTU Canvas" . "https://oc.sjtu.edu.cn/") ("Zdic" . [simple-query "www.zdic.net" "https://www.zdic.net/search/?sclb=tm&q=" ""]) ("Marginalia search" . [simple-query "search.marginalia.nu" "https://search.marginalia.nu/search?query=" ""]) ("Langcorrect" . "https://www.langcorrect.com/journals/") ("Emacs Wiki" . [simple-query "www.emacswiki.org" "www.emacswiki.org/cgi-bin/wiki/" #1=""]) ("DuckDuckGo" . [simple-query "duckduckgo.com" "duckduckgo.com/lite?q=" #1#]) ("Wikipedia" . [simple-query "wikipedia.org" "wikipedia.org/wiki/" #1#])))) (use-package hyperspace :ensure t :bind ("C-c s" . hyperspace) :custom (hyperspace-actions '(("z" . "https://www.zdic.net/search/?sclb=tm&q=%s") ("ddg" . "https://duckduckgo.com/lite?q=%s") ("dis" . "https://duckduckgo.com/?q=%s&iax=images&ia=images") ("gg" . "https://www.google.com/search?q=%s") ("ggm" . "https://www.google.com/maps/search/%s") ("gis" . "https://www.google.com/search?tbm=isch&q=%s") ("osm" . "https://www.openstreetmap.org/search?query=%s") ("az" . "https://www.amazon.com/s?k=%s") ("eb" . "https://www.ebay.com/sch/i.html?_nkw=%s") ("alix" . "https://www.aliexpress.com/wholesale?SearchText=%s") ("wp" . "https://en.wikipedia.org/w/index.php?search=%s&title=Special:Search&go=Go") ("pg" . "https://www.gutenberg.org/ebooks/search/?query=%s") ("bc" . "https://bandcamp.com/search?q=%s") ("dgs" . "https://www.discogs.com/search/?q=%s&type=all") ("imdb" . "https://www.imdb.com/find?q=%s&s=all") ("iv" . "https://invidio.us/search?q=%s") ("yt" . "https://www.youtube.com/results?search_query=%s") ("dp" . "https://packages.debian.org/%s") ("ac" . apropos-command) ("af" lambda (query) (apropos-command query t)) ("av" . apropos-variable) ("bb" . bbdb-search-name) ("el" apply-partially #'hyperspace-action->info "(elisp)Top")))) (setopt view-read-only t) ;; Common lisp development (use-package sly :if (executable-find "sbcl") :ensure t :commands 'sly :custom ((inferior-lisp-program (executable-find "sbcl")) (common-lisp-hyperspec-root "file:///usr/share/doc/hyperspec/")) :mode ((rx (or ".lisp" ".cl") eos) . common-lisp-mode)) ;; (profiler-stop)