chore(tazjin/emacs): Move //tools/emacs to //users/tazjin/emacs
Change-Id: I9dfbd0bb1fd3e215bb91c5734fb0934ee3faeae6
This commit is contained in:
parent
9448a2262b
commit
0b0e8c2da7
15 changed files with 2 additions and 2 deletions
11
tools/emacs/.gitignore
vendored
11
tools/emacs/.gitignore
vendored
|
|
@ -1,11 +0,0 @@
|
|||
.smex-items
|
||||
*token*
|
||||
auto-save-list/
|
||||
clones/
|
||||
elpa/
|
||||
irc.el
|
||||
local.el
|
||||
other/
|
||||
scripts/
|
||||
themes/
|
||||
*.elc
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
tools/emacs
|
||||
===========
|
||||
|
||||
This sub-folder builds my Emacs configuration, supplying packages from
|
||||
Nix and configuration from this folder.
|
||||
|
||||
I use Emacs for many things (including as my desktop environment).
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
;; Font size
|
||||
(define-key global-map (kbd "C-=") 'increase-default-text-scale) ;; '=' because there lies '+'
|
||||
(define-key global-map (kbd "C--") 'decrease-default-text-scale)
|
||||
(define-key global-map (kbd "C-x C-0") 'set-default-text-scale)
|
||||
|
||||
;; What does <tab> do? Well, it depends ...
|
||||
(define-key prog-mode-map (kbd "<tab>") #'company-indent-or-complete-common)
|
||||
|
||||
;; imenu instead of insert-file
|
||||
(global-set-key (kbd "C-x i") 'imenu)
|
||||
|
||||
;; Window switching. (C-x o goes to the next window)
|
||||
(windmove-default-keybindings) ;; Shift+direction
|
||||
|
||||
;; Start eshell or switch to it if it's active.
|
||||
(global-set-key (kbd "C-x m") 'eshell)
|
||||
|
||||
;; Start a new eshell even if one is active.
|
||||
(global-set-key (kbd "C-x C-p") 'ivy-browse-repositories)
|
||||
(global-set-key (kbd "M-g M-g") 'goto-line-with-feedback)
|
||||
|
||||
;; Miscellaneous editing commands
|
||||
(global-set-key (kbd "C-c w") 'whitespace-cleanup)
|
||||
(global-set-key (kbd "C-c a") 'align-regexp)
|
||||
(global-set-key (kbd "C-c m") 'mc/mark-dwim)
|
||||
|
||||
;; Browse URLs (very useful for Gitlab's SSH output!)
|
||||
(global-set-key (kbd "C-c b p") 'browse-url-at-point)
|
||||
(global-set-key (kbd "C-c b b") 'browse-url)
|
||||
|
||||
;; C-x REALLY QUIT (idea by @magnars)
|
||||
(global-set-key (kbd "C-x r q") 'save-buffers-kill-terminal)
|
||||
(global-set-key (kbd "C-x C-c") 'ignore)
|
||||
|
||||
;; Open Fefes Blog
|
||||
(global-set-key (kbd "C-c C-f") 'fefes-blog)
|
||||
|
||||
;; Open a file in project:
|
||||
(global-set-key (kbd "C-c f") 'project-find-file)
|
||||
|
||||
;; Insert TODO comments
|
||||
(global-set-key (kbd "C-c t") 'insert-todo-comment)
|
||||
|
||||
;; Add subthread collapsing to notmuch-show.
|
||||
;;
|
||||
;; C-, closes a thread, C-. opens a thread. This mirrors stepping
|
||||
;; in/out of definitions.
|
||||
(define-key notmuch-show-mode-map (kbd "C-,") 'notmuch-show-open-or-close-subthread)
|
||||
(define-key notmuch-show-mode-map (kbd "C-.")
|
||||
(lambda ()
|
||||
(interactive)
|
||||
(notmuch-show-open-or-close-subthread t))) ;; open
|
||||
|
||||
(provide 'bindings)
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
(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.
|
||||
'(ac-auto-show-menu 0.8)
|
||||
'(ac-delay 0.2)
|
||||
'(avy-background t)
|
||||
'(cargo-process--custom-path-to-bin "env CARGO_INCREMENTAL=1 cargo")
|
||||
'(cargo-process--enable-rust-backtrace 1)
|
||||
'(company-auto-complete (quote (quote company-explicit-action-p)))
|
||||
'(company-idle-delay 0.5)
|
||||
'(custom-enabled-themes (quote (gruber-darker)))
|
||||
'(custom-safe-themes
|
||||
(quote
|
||||
("d61fc0e6409f0c2a22e97162d7d151dee9e192a90fa623f8d6a071dbf49229c6" "3c83b3676d796422704082049fc38b6966bcad960f896669dfc21a7a37a748fa" "89336ca71dae5068c165d932418a368a394848c3b8881b2f96807405d8c6b5b6" default)))
|
||||
'(display-time-default-load-average nil)
|
||||
'(display-time-interval 30)
|
||||
'(elnode-send-file-program "/run/current-system/sw/bin/cat")
|
||||
'(frame-brackground-mode (quote dark))
|
||||
'(global-auto-complete-mode t)
|
||||
'(kubernetes-commands-display-buffer-function (quote display-buffer))
|
||||
'(lsp-gopls-server-path "/home/tazjin/go/bin/gopls")
|
||||
'(magit-log-show-gpg-status t)
|
||||
'(ns-alternate-modifier (quote none))
|
||||
'(ns-command-modifier (quote control))
|
||||
'(ns-right-command-modifier (quote meta))
|
||||
'(require-final-newline (quote visit-save))
|
||||
'(tls-program (quote ("gnutls-cli --x509cafile %t -p %p %h"))))
|
||||
(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.
|
||||
'(default ((t (:foreground "#e4e4ef" :background "#181818"))))
|
||||
'(rainbow-delimiters-depth-1-face ((t (:foreground "#2aa198"))))
|
||||
'(rainbow-delimiters-depth-2-face ((t (:foreground "#b58900"))))
|
||||
'(rainbow-delimiters-depth-3-face ((t (:foreground "#268bd2"))))
|
||||
'(rainbow-delimiters-depth-4-face ((t (:foreground "#dc322f"))))
|
||||
'(rainbow-delimiters-depth-5-face ((t (:foreground "#859900"))))
|
||||
'(rainbow-delimiters-depth-6-face ((t (:foreground "#268bd2"))))
|
||||
'(rainbow-delimiters-depth-7-face ((t (:foreground "#cb4b16"))))
|
||||
'(rainbow-delimiters-depth-8-face ((t (:foreground "#d33682"))))
|
||||
'(rainbow-delimiters-depth-9-face ((t (:foreground "#839496"))))
|
||||
'(term-color-black ((t (:background "#282828" :foreground "#282828"))))
|
||||
'(term-color-blue ((t (:background "#96a6c8" :foreground "#96a6c8"))))
|
||||
'(term-color-cyan ((t (:background "#1fad83" :foreground "#1fad83"))))
|
||||
'(term-color-green ((t (:background "#73c936" :foreground "#73c936"))))
|
||||
'(term-color-magenta ((t (:background "#9e95c7" :foreground "#9e95c7"))))
|
||||
'(term-color-red ((t (:background "#f43841" :foreground "#f43841"))))
|
||||
'(term-color-white ((t (:background "#f5f5f5" :foreground "#f5f5f5"))))
|
||||
'(term-color-yellow ((t (:background "#ffdd33" :foreground "#ffdd33")))))
|
||||
|
|
@ -1,249 +0,0 @@
|
|||
;; -*- lexical-binding: t; -*-
|
||||
;;
|
||||
;; Configure desktop environment settings, including both
|
||||
;; window-management (EXWM) as well as additional system-wide
|
||||
;; commands.
|
||||
|
||||
(require 's)
|
||||
(require 'f)
|
||||
(require 'dash)
|
||||
(require 'exwm)
|
||||
(require 'exwm-config)
|
||||
(require 'exwm-randr)
|
||||
(require 'exwm-systemtray)
|
||||
|
||||
(defun pactl (cmd)
|
||||
(shell-command (concat "pactl " cmd))
|
||||
(message "Volume command: %s" cmd))
|
||||
|
||||
(defun volume-mute () (interactive) (pactl "set-sink-mute @DEFAULT_SINK@ toggle"))
|
||||
(defun volume-up () (interactive) (pactl "set-sink-volume @DEFAULT_SINK@ +5%"))
|
||||
(defun volume-down () (interactive) (pactl "set-sink-volume @DEFAULT_SINK@ -5%"))
|
||||
|
||||
(defun brightness-up ()
|
||||
(interactive)
|
||||
(shell-command "xbacklight -inc 5")
|
||||
(message "Brightness increased"))
|
||||
|
||||
(defun brightness-down ()
|
||||
(interactive)
|
||||
(shell-command "xbacklight -dec 5")
|
||||
(message "Brightness decreased"))
|
||||
|
||||
(defun lock-screen ()
|
||||
(interactive)
|
||||
;; A sudoers configuration is in place that lets me execute this
|
||||
;; particular command without having to enter a password.
|
||||
;;
|
||||
;; The reason for things being set up this way is that I want
|
||||
;; xsecurelock.service to be started as a system-wide service that
|
||||
;; is tied to suspend.target.
|
||||
(shell-command "/usr/bin/sudo /usr/bin/systemctl start xsecurelock.service"))
|
||||
|
||||
(defun set-xkb-layout (layout)
|
||||
"Set the current X keyboard layout."
|
||||
|
||||
(shell-command (format "setxkbmap %s" layout))
|
||||
(message "Set X11 keyboard layout to '%s'" layout))
|
||||
|
||||
(defun create-window-name ()
|
||||
"Construct window names to be used for EXWM buffers by
|
||||
inspecting the window's X11 class and title.
|
||||
|
||||
A lot of commonly used applications either create titles that
|
||||
are too long by default, or in the case of web
|
||||
applications (such as Cider) end up being constructed in
|
||||
awkward ways.
|
||||
|
||||
To avoid this issue, some rewrite rules are applied for more
|
||||
human-accessible titles."
|
||||
|
||||
(pcase (list (or exwm-class-name "unknown") (or exwm-title "unknown"))
|
||||
;; In Cider windows, rename the class and keep the workspace/file
|
||||
;; as the title.
|
||||
(`("Google-chrome" ,(and (pred (lambda (title) (s-ends-with? " - Cider" title))) title))
|
||||
(format "Cider<%s>" (s-chop-suffix " - Cider" title)))
|
||||
|
||||
;; Attempt to detect IRCCloud windows via their title, which is a
|
||||
;; combination of the channel name and network.
|
||||
;;
|
||||
;; This is what would often be referred to as a "hack". The regexp
|
||||
;; will not work if a network connection buffer is selected in
|
||||
;; IRCCloud, but since the title contains no other indication that
|
||||
;; we're dealing with an IRCCloud window
|
||||
(`("Google-chrome"
|
||||
,(and (pred (lambda (title)
|
||||
(s-matches? "^[\*\+]\s#[a-zA-Z0-9/\-]+\s\|\s[a-zA-Z\.]+$" title)))
|
||||
title))
|
||||
(format "IRCCloud<%s>" title))
|
||||
|
||||
;; For other Chrome windows, make the title shorter.
|
||||
(`("Google-chrome" ,title)
|
||||
(format "Chrome<%s>" (s-truncate 42 (s-chop-suffix " - Google Chrome" title))))
|
||||
|
||||
;; Gnome-terminal -> Term
|
||||
(`("Gnome-terminal" ,title)
|
||||
;; fish-shell buffers contain some unnecessary whitespace and
|
||||
;; such before the current working directory. This can be
|
||||
;; stripped since most of my terminals are fish shells anyways.
|
||||
(format "Term<%s>" (s-trim-left (s-chop-prefix "fish" title))))
|
||||
|
||||
;; For any other application, a name is constructed from the
|
||||
;; window's class and name.
|
||||
(`(,class ,title) (format "%s<%s>" class (s-truncate 12 title)))))
|
||||
|
||||
;; EXWM launch configuration
|
||||
;;
|
||||
;; This used to use use-package, but when something breaks use-package
|
||||
;; it doesn't exactly make debugging any easier.
|
||||
|
||||
(let ((titlef (lambda ()
|
||||
(exwm-workspace-rename-buffer (create-window-name)))))
|
||||
(add-hook 'exwm-update-class-hook titlef)
|
||||
(add-hook 'exwm-update-title-hook titlef))
|
||||
|
||||
(fringe-mode 3)
|
||||
(exwm-enable)
|
||||
|
||||
;; 's-N': Switch to certain workspace
|
||||
(setq exwm-workspace-number 10)
|
||||
(dotimes (i 10)
|
||||
(exwm-input-set-key (kbd (format "s-%d" i))
|
||||
`(lambda ()
|
||||
(interactive)
|
||||
(exwm-workspace-switch-create ,i))))
|
||||
|
||||
;; Launch applications / any command with completion (dmenu style!)
|
||||
(exwm-input-set-key (kbd "s-d") #'counsel-linux-app)
|
||||
(exwm-input-set-key (kbd "s-x") #'ivy-run-external-command)
|
||||
(exwm-input-set-key (kbd "s-p") #'ivy-password-store)
|
||||
|
||||
;; Add X11 terminal selector to a key
|
||||
(exwm-input-set-key (kbd "C-x t") #'ts/switch-to-terminal)
|
||||
|
||||
;; Toggle between line-mode / char-mode
|
||||
(exwm-input-set-key (kbd "C-c C-t C-t") #'exwm-input-toggle-keyboard)
|
||||
|
||||
;; Volume keys
|
||||
(exwm-input-set-key (kbd "<XF86AudioMute>") #'volume-mute)
|
||||
(exwm-input-set-key (kbd "<XF86AudioRaiseVolume>") #'volume-up)
|
||||
(exwm-input-set-key (kbd "<XF86AudioLowerVolume>") #'volume-down)
|
||||
|
||||
;; Brightness keys
|
||||
(exwm-input-set-key (kbd "<XF86MonBrightnessDown>") #'brightness-down)
|
||||
(exwm-input-set-key (kbd "<XF86MonBrightnessUp>") #'brightness-up)
|
||||
(exwm-input-set-key (kbd "<XF86Display>") #'lock-screen)
|
||||
|
||||
;; Shortcuts for switching between keyboard layouts
|
||||
(defmacro bind-xkb (lang key)
|
||||
`(exwm-input-set-key (kbd (format "s-%s" ,key))
|
||||
(lambda ()
|
||||
(interactive)
|
||||
(set-xkb-layout ,lang))))
|
||||
|
||||
(bind-xkb "us" "k u")
|
||||
(bind-xkb "de" "k d")
|
||||
(bind-xkb "no" "k n")
|
||||
(bind-xkb "ru" "k r")
|
||||
|
||||
;; These are commented out because Emacs no longer starts (??) if
|
||||
;; they're set at launch.
|
||||
;;
|
||||
;; (bind-xkb "us" "л г")
|
||||
;; (bind-xkb "de" "л в")
|
||||
;; (bind-xkb "no" "л т")
|
||||
;; (bind-xkb "ru" "л к")
|
||||
|
||||
;; Line-editing shortcuts
|
||||
(exwm-input-set-simulation-keys
|
||||
'(([?\C-d] . delete)
|
||||
([?\C-w] . ?\C-c)))
|
||||
|
||||
;; Show time & battery status in the mode line
|
||||
(display-time-mode)
|
||||
(display-battery-mode)
|
||||
|
||||
;; enable display of X11 system tray within Emacs
|
||||
(exwm-systemtray-enable)
|
||||
|
||||
;; Configure xrandr (multi-monitor setup).
|
||||
;;
|
||||
;; This makes some assumptions about how my machines are connected to
|
||||
;; my home setup during the COVID19 isolation period.
|
||||
|
||||
(defun set-randr-config (screens)
|
||||
(setq exwm-randr-workspace-monitor-plist
|
||||
(-flatten (-map (lambda (screen)
|
||||
(-map (lambda (screen-id) (list screen-id (car screen))) (cdr screen)))
|
||||
screens))))
|
||||
|
||||
;; Layouts for Vauxhall (laptop)
|
||||
|
||||
(defun randr-vauxhall-layout-single ()
|
||||
"Laptop screen only!"
|
||||
(interactive)
|
||||
(set-randr-config '(("eDP1" (number-sequence 0 9))))
|
||||
(shell-command "xrandr --output eDP1 --auto --primary")
|
||||
(shell-command "xrandr --output HDMI1 --off")
|
||||
(shell-command "xrandr --output DP2 --off")
|
||||
(exwm-randr-refresh))
|
||||
|
||||
(defun randr-vauxhall-layout-all ()
|
||||
"Use all screens at home."
|
||||
(interactive)
|
||||
(set-randr-config
|
||||
'(("eDP1" 0)
|
||||
("HDMI1" 1 2 3 4 5)
|
||||
("DP2" 6 7 8 9)))
|
||||
|
||||
(shell-command "xrandr --output HDMI1 --right-of eDP1 --auto --primary")
|
||||
(shell-command "xrandr --output DP2 --right-of HDMI1 --auto")
|
||||
(exwm-randr-refresh))
|
||||
|
||||
(defun randr-vauxhall-layout-wide-only ()
|
||||
"Use only the wide screen at home."
|
||||
(interactive)
|
||||
(set-randr-config
|
||||
'(("eDP1" 8 9 0)
|
||||
("HDMI1" 1 2 4 5 6 7)))
|
||||
|
||||
(shell-command "xrandr --output DP2 --off")
|
||||
(shell-command "xrandr --output HDMI1 --right-of eDP1 --auto --primary")
|
||||
(exwm-randr-refresh))
|
||||
|
||||
;; Layouts for frog (desktop)
|
||||
|
||||
(defun randr-frog-layout-right-only ()
|
||||
"Use only the right screen on frog."
|
||||
(interactive)
|
||||
(set-randr-config `(("DP-1" ,(number-sequence 0 9))))
|
||||
(shell-command "xrandr --output DP-2 --off")
|
||||
(shell-command "xrandr --output DP-1 --auto --primary"))
|
||||
|
||||
(defun randr-frog-layout-both ()
|
||||
"Use the left and right screen on frog."
|
||||
(interactive)
|
||||
(set-randr-config `(("DP-2" 1 2 3 4 5)
|
||||
("DP-1" 6 7 8 9 0)))
|
||||
|
||||
(shell-command "xrandr --output DP-2 --auto --primary --left-of DP-1")
|
||||
(shell-command "xrandr --output DP-1 --auto --right-of DP-2"))
|
||||
|
||||
(pcase (s-trim (shell-command-to-string "hostname"))
|
||||
("vauxhall"
|
||||
(exwm-input-set-key (kbd "s-m s") #'randr-vauxhall-layout-single)
|
||||
(exwm-input-set-key (kbd "s-m a") #'randr-vauxhall-layout-all)
|
||||
(exwm-input-set-key (kbd "s-m w") #'randr-vauxhall-layout-wide-only))
|
||||
|
||||
("frog"
|
||||
(exwm-input-set-key (kbd "s-m b") #'randr-frog-layout-both)
|
||||
(exwm-input-set-key (kbd "s-m r") #'randr-frog-layout-right-only)))
|
||||
|
||||
(exwm-randr-enable)
|
||||
|
||||
;; Let buffers move seamlessly between workspaces by making them
|
||||
;; accessible in selectors on all frames.
|
||||
(setq exwm-workspace-show-all-buffers t)
|
||||
(setq exwm-layout-show-all-buffers t)
|
||||
|
||||
(provide 'desktop)
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
;; EShell configuration
|
||||
|
||||
(require 'eshell)
|
||||
|
||||
;; Generic settings
|
||||
;; Hide banner message ...
|
||||
(setq eshell-banner-message "")
|
||||
|
||||
;; Prompt configuration
|
||||
(defun clean-pwd (path)
|
||||
"Turns a path of the form /foo/bar/baz into /f/b/baz
|
||||
(inspired by fish shell)"
|
||||
(let* ((hpath (replace-regexp-in-string home-dir
|
||||
"~"
|
||||
path))
|
||||
(current-dir (split-string hpath "/"))
|
||||
(cdir (last current-dir))
|
||||
(head (butlast current-dir)))
|
||||
(concat (mapconcat (lambda (s)
|
||||
(if (string= "" s) nil
|
||||
(substring s 0 1)))
|
||||
head
|
||||
"/")
|
||||
(if head "/" nil)
|
||||
(car cdir))))
|
||||
|
||||
(defun vcprompt (&optional args)
|
||||
"Call the external vcprompt command with optional arguments.
|
||||
VCPrompt"
|
||||
(replace-regexp-in-string
|
||||
"\n" ""
|
||||
(shell-command-to-string (concat "vcprompt" args))))
|
||||
|
||||
(defmacro with-face (str &rest properties)
|
||||
`(propertize ,str 'face (list ,@properties)))
|
||||
|
||||
(defun prompt-f ()
|
||||
"EShell prompt displaying VC info and such"
|
||||
(concat
|
||||
(with-face (concat (clean-pwd (eshell/pwd)) " ") :foreground "#96a6c8")
|
||||
(if (= 0 (user-uid))
|
||||
(with-face "#" :foreground "#f43841")
|
||||
(with-face "$" :foreground "#73c936"))
|
||||
(with-face " " :foreground "#95a99f")))
|
||||
|
||||
|
||||
(setq eshell-prompt-function 'prompt-f)
|
||||
(setq eshell-highlight-prompt nil)
|
||||
(setq eshell-prompt-regexp "^.+? \\((\\(git\\|svn\\|hg\\|darcs\\|cvs\\|bzr\\):.+?) \\)?[$#] ")
|
||||
|
||||
;; Ignore version control folders in autocompletion
|
||||
(setq eshell-cmpl-cycle-completions nil
|
||||
eshell-save-history-on-exit t
|
||||
eshell-cmpl-dir-ignore "\\`\\(\\.\\.?\\|CVS\\|\\.svn\\|\\.git\\)/\\'")
|
||||
|
||||
;; Load some EShell extensions
|
||||
(eval-after-load 'esh-opt
|
||||
'(progn
|
||||
(require 'em-term)
|
||||
(require 'em-cmpl)
|
||||
;; More visual commands!
|
||||
(add-to-list 'eshell-visual-commands "ssh")
|
||||
(add-to-list 'eshell-visual-commands "tail")
|
||||
(add-to-list 'eshell-visual-commands "sl")))
|
||||
|
||||
(setq eshell-directory-name "~/.config/eshell/")
|
||||
|
||||
(provide 'eshell-setup)
|
||||
|
|
@ -1,287 +0,0 @@
|
|||
(require 'chart)
|
||||
(require 'dash)
|
||||
(require 'map)
|
||||
|
||||
(defun load-file-if-exists (filename)
|
||||
(if (file-exists-p filename)
|
||||
(load filename)))
|
||||
|
||||
(defun goto-line-with-feedback ()
|
||||
"Show line numbers temporarily, while prompting for the line number input"
|
||||
(interactive)
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setq-local display-line-numbers t)
|
||||
(let ((target (read-number "Goto line: ")))
|
||||
(avy-push-mark)
|
||||
(goto-line target)))
|
||||
(setq-local display-line-numbers nil)))
|
||||
|
||||
;; These come from the emacs starter kit
|
||||
|
||||
(defun esk-add-watchwords ()
|
||||
(font-lock-add-keywords
|
||||
nil '(("\\<\\(FIX\\(ME\\)?\\|TODO\\|DEBUG\\|HACK\\|REFACTOR\\|NOCOMMIT\\)"
|
||||
1 font-lock-warning-face t))))
|
||||
|
||||
(defun esk-sudo-edit (&optional arg)
|
||||
(interactive "p")
|
||||
(if (or arg (not buffer-file-name))
|
||||
(find-file (concat "/sudo:root@localhost:" (read-file-name "File: ")))
|
||||
(find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))
|
||||
|
||||
;; Open Fefes blog
|
||||
(defun fefes-blog ()
|
||||
(interactive)
|
||||
(eww "https://blog.fefe.de/"))
|
||||
|
||||
;; Open the NixOS man page
|
||||
(defun nixos-man ()
|
||||
(interactive)
|
||||
(man "configuration.nix"))
|
||||
|
||||
;; Open my monorepo in magit
|
||||
(defun depot-status ()
|
||||
(interactive)
|
||||
(magit-status depot-path))
|
||||
|
||||
;; Get the nix store path for a given derivation.
|
||||
;; If the derivation has not been built before, this will trigger a build.
|
||||
(defun nix-store-path (derivation)
|
||||
(let ((expr (concat "with import <nixos> {}; " derivation)))
|
||||
(s-chomp (shell-command-to-string (concat "nix-build -E '" expr "'")))))
|
||||
|
||||
(defun insert-nix-store-path ()
|
||||
(interactive)
|
||||
(let ((derivation (read-string "Derivation name (in <nixos>): ")))
|
||||
(insert (nix-store-path derivation))))
|
||||
|
||||
(defun toggle-force-newline ()
|
||||
"Buffer-local toggle for enforcing final newline on save."
|
||||
(interactive)
|
||||
(setq-local require-final-newline (not require-final-newline))
|
||||
(message "require-final-newline in buffer %s is now %s"
|
||||
(buffer-name)
|
||||
require-final-newline))
|
||||
|
||||
;; Helm includes a command to run external applications, which does
|
||||
;; not seem to exist in ivy. This implementation uses some of the
|
||||
;; logic from Helm to provide similar functionality using ivy.
|
||||
(defun list-external-commands ()
|
||||
"Creates a list of all external commands available on $PATH
|
||||
while filtering NixOS wrappers."
|
||||
(cl-loop
|
||||
for dir in (split-string (getenv "PATH") path-separator)
|
||||
when (and (file-exists-p dir) (file-accessible-directory-p dir))
|
||||
for lsdir = (cl-loop for i in (directory-files dir t)
|
||||
for bn = (file-name-nondirectory i)
|
||||
when (and (not (s-contains? "-wrapped" i))
|
||||
(not (member bn completions))
|
||||
(not (file-directory-p i))
|
||||
(file-executable-p i))
|
||||
collect bn)
|
||||
append lsdir into completions
|
||||
finally return (sort completions 'string-lessp)))
|
||||
|
||||
(defvar external-command-flag-overrides
|
||||
'(("google-chrome" . "--force-device-scale-factor=1.4"))
|
||||
|
||||
"This setting lets me add additional flags to specific commands
|
||||
that are run interactively via `ivy-run-external-command'.")
|
||||
|
||||
(defun run-external-command (cmd)
|
||||
"Execute the specified command and notify the user when it
|
||||
finishes."
|
||||
(let* ((extra-flags (cdr (assoc cmd external-command-flag-overrides)))
|
||||
(cmd (if extra-flags (s-join " " (list cmd extra-flags)) cmd)))
|
||||
(message "Starting %s..." cmd)
|
||||
(set-process-sentinel
|
||||
(start-process-shell-command cmd nil cmd)
|
||||
(lambda (process event)
|
||||
(when (string= event "finished\n")
|
||||
(message "%s process finished." process))))))
|
||||
|
||||
(defun ivy-run-external-command ()
|
||||
"Prompts the user with a list of all installed applications and
|
||||
lets them select one to launch."
|
||||
|
||||
(interactive)
|
||||
(let ((external-commands-list (list-external-commands)))
|
||||
(ivy-read "Command:" external-commands-list
|
||||
:require-match t
|
||||
:history 'external-commands-history
|
||||
:action #'run-external-command)))
|
||||
|
||||
(defun ivy-password-store (&optional password-store-dir)
|
||||
"Custom version of password-store integration with ivy that
|
||||
actually uses the GPG agent correctly."
|
||||
|
||||
(interactive)
|
||||
(ivy-read "Copy password of entry: "
|
||||
(password-store-list (or password-store-dir (password-store-dir)))
|
||||
:require-match t
|
||||
:keymap ivy-pass-map
|
||||
:action (lambda (entry)
|
||||
(let ((password (auth-source-pass-get 'secret entry)))
|
||||
(password-store-clear)
|
||||
(kill-new password)
|
||||
(setq password-store-kill-ring-pointer kill-ring-yank-pointer)
|
||||
(message "Copied %s to the kill ring. Will clear in %s seconds."
|
||||
entry (password-store-timeout))
|
||||
(setq password-store-timeout-timer
|
||||
(run-at-time (password-store-timeout)
|
||||
nil 'password-store-clear))))))
|
||||
|
||||
(defun ivy-browse-repositories ()
|
||||
"Select a git repository and open its associated magit buffer."
|
||||
|
||||
(interactive)
|
||||
(ivy-read "Repository: "
|
||||
(magit-list-repos)
|
||||
:require-match t
|
||||
:sort t
|
||||
:action #'magit-status))
|
||||
|
||||
(defun bottom-right-window-p ()
|
||||
"Determines whether the last (i.e. bottom-right) window of the
|
||||
active frame is showing the buffer in which this function is
|
||||
executed."
|
||||
(let* ((frame (selected-frame))
|
||||
(right-windows (window-at-side-list frame 'right))
|
||||
(bottom-windows (window-at-side-list frame 'bottom))
|
||||
(last-window (car (seq-intersection right-windows bottom-windows))))
|
||||
(eq (current-buffer) (window-buffer last-window))))
|
||||
|
||||
(defhydra mc/mark-more-hydra (:color pink)
|
||||
("<up>" mmlte--up "Mark previous like this")
|
||||
("<down>" mc/mmlte--down "Mark next like this")
|
||||
("<left>" mc/mmlte--left (if (eq mc/mark-more-like-this-extended-direction 'up)
|
||||
"Skip past the cursor furthest up"
|
||||
"Remove the cursor furthest down"))
|
||||
("<right>" mc/mmlte--right (if (eq mc/mark-more-like-this-extended-direction 'up)
|
||||
"Remove the cursor furthest up"
|
||||
"Skip past the cursor furthest down"))
|
||||
("f" nil "Finish selecting"))
|
||||
|
||||
;; Mute the message that mc/mmlte wants to print on its own
|
||||
(advice-add 'mc/mmlte--message :around (lambda (&rest args) (ignore)))
|
||||
|
||||
(defun mc/mark-dwim (arg)
|
||||
"Select multiple things, but do what I mean."
|
||||
|
||||
(interactive "p")
|
||||
(if (not (region-active-p)) (mc/mark-next-lines arg)
|
||||
(if (< 1 (count-lines (region-beginning)
|
||||
(region-end)))
|
||||
(mc/edit-lines arg)
|
||||
;; The following is almost identical to `mc/mark-more-like-this-extended',
|
||||
;; but uses a hydra (`mc/mark-more-hydra') instead of a transient key map.
|
||||
(mc/mmlte--down)
|
||||
(mc/mark-more-hydra/body))))
|
||||
|
||||
(defun memespace-region ()
|
||||
"Make a meme out of it."
|
||||
|
||||
(interactive)
|
||||
(let* ((start (region-beginning))
|
||||
(end (region-end))
|
||||
(memed
|
||||
(message
|
||||
(s-trim-right
|
||||
(apply #'string
|
||||
(-flatten
|
||||
(nreverse
|
||||
(-reduce-from (lambda (acc x)
|
||||
(cons (cons x (-repeat (+ 1 (length acc)) 32)) acc))
|
||||
'()
|
||||
(string-to-list (buffer-substring-no-properties start end))))))))))
|
||||
|
||||
(save-excursion (delete-region start end)
|
||||
(goto-char start)
|
||||
(insert memed))))
|
||||
|
||||
(defun insert-todo-comment (prefix todo)
|
||||
"Insert a comment at point with something for me to do."
|
||||
|
||||
(interactive "P\nsWhat needs doing? ")
|
||||
(save-excursion
|
||||
(move-end-of-line nil)
|
||||
(insert (format " %s TODO(%s): %s"
|
||||
(s-trim-right comment-start)
|
||||
(if prefix (read-string "Who needs to do this? ")
|
||||
(getenv "USER"))
|
||||
todo))))
|
||||
|
||||
;; Custom text scale adjustment functions that operate on the entire instance
|
||||
(defun modify-text-scale (factor)
|
||||
(set-face-attribute 'default nil
|
||||
:height (+ (* factor 5) (face-attribute 'default :height))))
|
||||
|
||||
(defun increase-default-text-scale (prefix)
|
||||
"Increase default text scale in all Emacs frames, or just the
|
||||
current frame if PREFIX is set."
|
||||
|
||||
(interactive "P")
|
||||
(if prefix (text-scale-increase 1)
|
||||
(modify-text-scale 1)))
|
||||
|
||||
(defun decrease-default-text-scale (prefix)
|
||||
"Increase default text scale in all Emacs frames, or just the
|
||||
current frame if PREFIX is set."
|
||||
|
||||
(interactive "P")
|
||||
(if prefix (text-scale-decrease 1)
|
||||
(modify-text-scale -1)))
|
||||
|
||||
(defun set-default-text-scale (prefix &optional to)
|
||||
"Set the default text scale to the specified value, or the
|
||||
default. Restores current frame's text scale only, if PREFIX is
|
||||
set."
|
||||
|
||||
(interactive "P")
|
||||
(if prefix (text-scale-adjust 0)
|
||||
(set-face-attribute 'default nil :height (or to 120))))
|
||||
|
||||
(defun scrot-select ()
|
||||
"Take a screenshot based on a mouse-selection and save it to
|
||||
~/screenshots."
|
||||
(interactive)
|
||||
(shell-command "scrot '$a_%Y-%m-%d_%s.png' -s -e 'mv $f ~/screenshots/'"))
|
||||
|
||||
(defun graph-unread-mails ()
|
||||
"Create a bar chart of unread mails based on notmuch tags.
|
||||
Certain tags are excluded from the overview."
|
||||
|
||||
(interactive)
|
||||
(let ((tag-counts
|
||||
(-keep (-lambda ((name . search))
|
||||
(let ((count
|
||||
(string-to-number
|
||||
(s-trim
|
||||
(notmuch-command-to-string "count" search "and" "tag:unread")))))
|
||||
(when (>= count 1) (cons name count))))
|
||||
(notmuch-hello-generate-tag-alist '("unread" "signed" "attachment" "important")))))
|
||||
|
||||
(chart-bar-quickie
|
||||
(if (< (length tag-counts) 6)
|
||||
'vertical 'horizontal)
|
||||
"Unread emails"
|
||||
(-map #'car tag-counts) "Tag:"
|
||||
(-map #'cdr tag-counts) "Count:")))
|
||||
|
||||
(defun notmuch-show-open-or-close-subthread (&optional prefix)
|
||||
"Open or close the subthread from (and including) the message at point."
|
||||
(interactive "P")
|
||||
(save-excursion
|
||||
(let ((current-depth (map-elt (notmuch-show-get-message-properties) :depth 0)))
|
||||
(loop do (notmuch-show-message-visible (notmuch-show-get-message-properties) prefix)
|
||||
until (or (not (notmuch-show-goto-message-next))
|
||||
(= (map-elt (notmuch-show-get-message-properties) :depth) current-depth)))))
|
||||
(force-window-update))
|
||||
|
||||
(defun vterm-send-ctrl-x ()
|
||||
"Sends `C-x' to the libvterm."
|
||||
(interactive)
|
||||
(vterm-send-key "x" nil nil t))
|
||||
|
||||
(provide 'functions)
|
||||
|
|
@ -1,287 +0,0 @@
|
|||
;;; init.el --- Package bootstrapping. -*- lexical-binding: t; -*-
|
||||
|
||||
;; Packages are installed via Nix configuration, this file only
|
||||
;; initialises the newly loaded packages.
|
||||
|
||||
(require 'use-package)
|
||||
(require 'seq)
|
||||
|
||||
(package-initialize)
|
||||
|
||||
;; Initialise all packages installed via Nix.
|
||||
;;
|
||||
;; TODO: Generate this section in Nix for all packages that do not
|
||||
;; require special configuration.
|
||||
|
||||
;;
|
||||
;; Packages providing generic functionality.
|
||||
;;
|
||||
|
||||
(use-package ace-window
|
||||
:bind (("C-x o" . ace-window))
|
||||
:config
|
||||
(setq aw-keys '(?f ?j ?d ?k ?s ?l ?a)
|
||||
aw-scope 'frame))
|
||||
|
||||
(use-package auth-source-pass :config (auth-source-pass-enable))
|
||||
|
||||
(use-package avy
|
||||
:bind (("M-j" . avy-goto-char)
|
||||
("M-p" . avy-pop-mark)
|
||||
("M-g g" . avy-goto-line)))
|
||||
|
||||
(use-package browse-kill-ring)
|
||||
|
||||
(use-package company
|
||||
:hook ((prog-mode . company-mode))
|
||||
:config (setq company-tooltip-align-annotations t))
|
||||
|
||||
(use-package counsel
|
||||
:after (ivy)
|
||||
:config (counsel-mode 1)
|
||||
:bind (("C-c r g" . counsel-rg)))
|
||||
|
||||
(use-package dash)
|
||||
(use-package dash-functional)
|
||||
|
||||
(use-package dottime
|
||||
:demand
|
||||
:after (notmuch telega)
|
||||
:config (dottime-display-mode t))
|
||||
|
||||
(use-package gruber-darker-theme)
|
||||
|
||||
(use-package eglot
|
||||
:custom
|
||||
(eglot-autoshutdown t)
|
||||
(eglot-send-changes-idle-time 0.3))
|
||||
|
||||
(use-package ht)
|
||||
|
||||
(use-package hydra)
|
||||
(use-package idle-highlight-mode :hook ((prog-mode . idle-highlight-mode)))
|
||||
|
||||
(use-package ivy
|
||||
:config
|
||||
(ivy-mode 1)
|
||||
(setq enable-recursive-minibuffers t)
|
||||
(setq ivy-use-virtual-buffers t))
|
||||
|
||||
(use-package ivy-pass :after (ivy))
|
||||
|
||||
(use-package ivy-prescient
|
||||
:after (ivy prescient)
|
||||
:config
|
||||
(ivy-prescient-mode)
|
||||
;; Fixes an issue with how regexes are passed to ripgrep from counsel,
|
||||
;; see raxod502/prescient.el#43
|
||||
(setf (alist-get 'counsel-rg ivy-re-builders-alist) #'ivy--regex-plus))
|
||||
|
||||
(use-package multiple-cursors)
|
||||
|
||||
(use-package notmuch
|
||||
:bind (:map global-map
|
||||
("s-g m" . notmuch)
|
||||
("s-g M" . counsel-notmuch)) ;; g m -> gmail
|
||||
:config
|
||||
(setq notmuch-search-oldest-first nil)
|
||||
(setq notmuch-show-all-tags-list t)
|
||||
(setq notmuch-hello-tag-list-make-query "tag:unread"))
|
||||
|
||||
(use-package paredit :hook ((lisp-mode . paredit-mode)
|
||||
(emacs-lisp-mode . paredit-mode)))
|
||||
|
||||
(use-package pinentry
|
||||
:config
|
||||
(setq epa-pinentry-mode 'loopback)
|
||||
(pinentry-start))
|
||||
|
||||
(use-package prescient
|
||||
:after (ivy counsel)
|
||||
:config (prescient-persist-mode))
|
||||
|
||||
(use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode))
|
||||
(use-package rainbow-mode)
|
||||
(use-package s)
|
||||
(use-package string-edit)
|
||||
|
||||
(use-package swiper
|
||||
:after (counsel ivy)
|
||||
:bind (("C-s" . swiper)))
|
||||
|
||||
(use-package telephone-line) ;; configuration happens outside of use-package
|
||||
(use-package term-switcher)
|
||||
(use-package undo-tree :config (global-undo-tree-mode))
|
||||
(use-package uuidgen)
|
||||
(use-package which-key :config (which-key-mode t))
|
||||
|
||||
;;
|
||||
;; Applications in emacs
|
||||
;;
|
||||
|
||||
(use-package magit
|
||||
:bind ("C-c g" . magit-status)
|
||||
:config (setq magit-repository-directories '(("/home/tazjin/projects" . 2)
|
||||
("/home/tazjin" . 1))))
|
||||
|
||||
(use-package org-journal
|
||||
;; Always use my own key to encrypt files. There seems to be no
|
||||
;; global way to set this, as `epa-file-encrypt-to' only has an
|
||||
;; effect as a file-local variable (?!)
|
||||
:hook ((org-journal-mode . (lambda ()
|
||||
(setq-local epa-file-encrypt-to
|
||||
"DCF34CFAC1AC44B87E26333136EE34814F6D294A"))))
|
||||
|
||||
:config
|
||||
(setq org-journal-dir "/ssh:camden.tazj.in:/home/tazjin/journal"
|
||||
org-journal-encrypt-journal t
|
||||
org-journal-file-type 'weekly
|
||||
org-journal-date-format "%A, %Y-%m-%d"
|
||||
org-journal-file-format "%Y%m%d-weekly"
|
||||
|
||||
;; Saturday, because reasons.
|
||||
org-journal-start-on-weekday 6)
|
||||
|
||||
;; org-journal doesn't actually enter its mode automatically if
|
||||
;; encryption is used (I'm not sure why), so this teaches Emacs to
|
||||
;; recognise the files.
|
||||
(add-to-list 'auto-mode-alist '("[0-9]-weekly\\.gpg\\'" . org-journal-mode)))
|
||||
|
||||
(use-package org-ql)
|
||||
|
||||
(use-package password-store)
|
||||
(use-package pg)
|
||||
(use-package restclient)
|
||||
|
||||
(use-package vterm
|
||||
:config (progn
|
||||
(setq vterm-shell "fish")
|
||||
(setq vterm-exit-functions
|
||||
(lambda (&rest _) (kill-buffer (current-buffer))))
|
||||
(setq vterm-set-title-functions
|
||||
(lambda (title)
|
||||
(rename-buffer
|
||||
(generate-new-buffer-name
|
||||
(format "vterm<%s>"
|
||||
(s-trim-left
|
||||
(s-chop-prefix "fish" title)))))))))
|
||||
|
||||
;;
|
||||
;; Packages providing language-specific functionality
|
||||
;;
|
||||
|
||||
(use-package cargo
|
||||
:hook ((rust-mode . cargo-minor-mode)
|
||||
(cargo-process-mode . visual-line-mode))
|
||||
:bind (:map cargo-minor-mode-map ("C-c C-c C-l" . ignore)))
|
||||
|
||||
(use-package dockerfile-mode)
|
||||
|
||||
(use-package erlang
|
||||
:hook ((erlang-mode . (lambda ()
|
||||
;; Don't indent after '>' while I'm writing
|
||||
(local-set-key ">" 'self-insert-command)))))
|
||||
|
||||
(use-package f)
|
||||
(use-package geiser)
|
||||
|
||||
(use-package go-mode
|
||||
:bind (:map go-mode-map ("C-c C-r" . recompile))
|
||||
:hook ((go-mode . (lambda ()
|
||||
(setq tab-width 2)
|
||||
(setq-local compile-command
|
||||
(concat "go build " buffer-file-name))))))
|
||||
|
||||
(use-package haskell-mode)
|
||||
|
||||
(use-package ielm
|
||||
:hook ((inferior-emacs-lisp-mode . (lambda ()
|
||||
(paredit-mode)
|
||||
(rainbow-delimiters-mode-enable)
|
||||
(company-mode)))))
|
||||
|
||||
(use-package jq-mode
|
||||
:config (add-to-list 'auto-mode-alist '("\\.jq\\'" . jq-mode)))
|
||||
|
||||
(use-package kotlin-mode
|
||||
:hook ((kotlin-mode . (lambda ()
|
||||
(setq indent-line-function #'indent-relative)))))
|
||||
|
||||
(use-package lsp-mode)
|
||||
|
||||
(use-package markdown-mode
|
||||
:config
|
||||
(add-to-list 'auto-mode-alist '("\\.txt\\'" . markdown-mode))
|
||||
(add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
|
||||
(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode)))
|
||||
|
||||
(use-package markdown-toc)
|
||||
|
||||
(use-package nix-mode
|
||||
:hook ((nix-mode . (lambda ()
|
||||
(setq indent-line-function #'nix-indent-line)))))
|
||||
|
||||
(use-package nix-util)
|
||||
(use-package nginx-mode)
|
||||
(use-package rust-mode)
|
||||
|
||||
(use-package sly
|
||||
:hook ((sly-mrepl-mode . (lambda ()
|
||||
(paredit-mode)
|
||||
(rainbow-delimiters-mode-enable)
|
||||
(company-mode))))
|
||||
:config
|
||||
(setq common-lisp-hyperspec-root "file:///home/tazjin/docs/lisp/"))
|
||||
|
||||
(use-package telega
|
||||
:bind (:map global-map ("s-t" . telega))
|
||||
:config (telega-mode-line-mode 1))
|
||||
|
||||
(use-package terraform-mode)
|
||||
(use-package toml-mode)
|
||||
(use-package web-mode)
|
||||
(use-package yaml-mode)
|
||||
|
||||
(defgroup tazjin nil
|
||||
"Settings related to my configuration")
|
||||
|
||||
(defcustom depot-path "/depot"
|
||||
"Local path to the depot checkout"
|
||||
:group 'tazjin)
|
||||
|
||||
;; Configuration changes in `customize` can not actually be persisted
|
||||
;; to the customise file that Emacs is currently using (since it comes
|
||||
;; from the Nix store).
|
||||
;;
|
||||
;; The way this will work for now is that Emacs will *write*
|
||||
;; configuration to the file tracked in my repository, while not
|
||||
;; actually *reading* it from there (unless Emacs is rebuilt).
|
||||
(setq custom-file (expand-file-name "~/depot/tools/emacs/config/custom.el"))
|
||||
(load-library "custom")
|
||||
|
||||
(defvar home-dir (expand-file-name "~"))
|
||||
|
||||
;; Seed RNG
|
||||
(random t)
|
||||
|
||||
;; Load all other Emacs configuration. These configurations are
|
||||
;; added to `load-path' by Nix.
|
||||
(mapc 'require '(desktop
|
||||
mail-setup
|
||||
look-and-feel
|
||||
functions
|
||||
settings
|
||||
modes
|
||||
bindings
|
||||
eshell-setup))
|
||||
(telephone-line-setup)
|
||||
(ace-window-display-mode)
|
||||
|
||||
;; If a local configuration library exists, it should be loaded.
|
||||
;;
|
||||
;; This can be provided by calling my Emacs derivation with
|
||||
;; `withLocalConfig'.
|
||||
(if-let (local-file (locate-library "local"))
|
||||
(load local-file))
|
||||
|
||||
(provide 'init)
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
;;; -*- lexical-binding: t; -*-
|
||||
|
||||
;; Hide those ugly tool bars:
|
||||
(tool-bar-mode 0)
|
||||
(scroll-bar-mode 0)
|
||||
(menu-bar-mode 0)
|
||||
(add-hook 'after-make-frame-functions
|
||||
(lambda (frame) (scroll-bar-mode 0)))
|
||||
|
||||
;; Don't do any annoying things:
|
||||
(setq ring-bell-function 'ignore)
|
||||
(setq initial-scratch-message "")
|
||||
|
||||
;; Remember layout changes
|
||||
(winner-mode 1)
|
||||
|
||||
;; Usually emacs will run as a proper GUI application, in which case a few
|
||||
;; extra settings are nice-to-have:
|
||||
(when window-system
|
||||
(setq frame-title-format '(buffer-file-name "%f" ("%b")))
|
||||
(mouse-wheel-mode t)
|
||||
(blink-cursor-mode -1))
|
||||
|
||||
;; Configure Emacs fonts.
|
||||
(let ((font (format "JetBrains Mono-%d" 12)))
|
||||
(setq default-frame-alist `((font . ,font)))
|
||||
(set-frame-font font t t))
|
||||
|
||||
;; Configure telephone-line
|
||||
(defun telephone-misc-if-last-window ()
|
||||
"Renders the mode-line-misc-info string for display in the
|
||||
mode-line if the currently active window is the last one in the
|
||||
frame.
|
||||
|
||||
The idea is to not display information like the current time,
|
||||
load, battery levels on all buffers."
|
||||
|
||||
(when (bottom-right-window-p)
|
||||
(telephone-line-raw mode-line-misc-info t)))
|
||||
|
||||
(defun telephone-line-setup ()
|
||||
(telephone-line-defsegment telephone-line-last-window-segment ()
|
||||
(telephone-misc-if-last-window))
|
||||
|
||||
;; Display the current EXWM workspace index in the mode-line
|
||||
(telephone-line-defsegment telephone-line-exwm-workspace-index ()
|
||||
(when (bottom-right-window-p)
|
||||
(format "[%s]" exwm-workspace-current-index)))
|
||||
|
||||
;; Define a highlight font for ~ important ~ information in the last
|
||||
;; window.
|
||||
(defface special-highlight '((t (:foreground "white" :background "#5f627f"))) "")
|
||||
(add-to-list 'telephone-line-faces
|
||||
'(highlight . (special-highlight . special-highlight)))
|
||||
|
||||
(setq telephone-line-lhs
|
||||
'((nil . (telephone-line-position-segment))
|
||||
(accent . (telephone-line-buffer-segment))))
|
||||
|
||||
(setq telephone-line-rhs
|
||||
'((accent . (telephone-line-major-mode-segment))
|
||||
(nil . (telephone-line-last-window-segment
|
||||
telephone-line-exwm-workspace-index))
|
||||
|
||||
;; TODO(tazjin): lets not do this particular thing while I
|
||||
;; don't actually run notmuch, there are too many things
|
||||
;; that have a dependency on the modeline drawing correctly
|
||||
;; (including randr operations!)
|
||||
;;
|
||||
;; (highlight . (telephone-line-notmuch-counts))
|
||||
))
|
||||
|
||||
(setq telephone-line-primary-left-separator 'telephone-line-tan-left
|
||||
telephone-line-primary-right-separator 'telephone-line-tan-right
|
||||
telephone-line-secondary-left-separator 'telephone-line-tan-hollow-left
|
||||
telephone-line-secondary-right-separator 'telephone-line-tan-hollow-right)
|
||||
|
||||
(telephone-line-mode 1))
|
||||
|
||||
;; Auto refresh buffers
|
||||
(global-auto-revert-mode 1)
|
||||
|
||||
;; Use clipboard properly
|
||||
(setq select-enable-clipboard t)
|
||||
|
||||
;; Show in-progress chords in minibuffer
|
||||
(setq echo-keystrokes 0.1)
|
||||
|
||||
;; Show column numbers in all buffers
|
||||
(column-number-mode t)
|
||||
|
||||
(defalias 'yes-or-no-p 'y-or-n-p)
|
||||
(defalias 'auto-tail-revert-mode 'tail-mode)
|
||||
|
||||
;; Style line numbers (shown with M-g g)
|
||||
(setq linum-format
|
||||
(lambda (line)
|
||||
(propertize
|
||||
(format (concat " %"
|
||||
(number-to-string
|
||||
(length (number-to-string
|
||||
(line-number-at-pos (point-max)))))
|
||||
"d ")
|
||||
line)
|
||||
'face 'linum)))
|
||||
|
||||
;; Display tabs as 2 spaces
|
||||
(setq tab-width 2)
|
||||
|
||||
;; Don't wrap around when moving between buffers
|
||||
(setq windmove-wrap-around nil)
|
||||
|
||||
(provide 'look-and-feel)
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
(require 'notmuch)
|
||||
(require 'counsel-notmuch)
|
||||
|
||||
;; (global-set-key (kbd "C-c m") 'notmuch-hello)
|
||||
;; (global-set-key (kbd "C-c C-m") 'counsel-notmuch)
|
||||
;; (global-set-key (kbd "C-c C-e n") 'notmuch-mua-new-mail)
|
||||
|
||||
(setq notmuch-cache-dir (format "%s/.cache/notmuch" (getenv "HOME")))
|
||||
(make-directory notmuch-cache-dir t)
|
||||
|
||||
;; Cache addresses for completion:
|
||||
(setq notmuch-address-save-filename (concat notmuch-cache-dir "/addresses"))
|
||||
|
||||
;; Don't spam my home folder with drafts:
|
||||
(setq notmuch-draft-folder "drafts") ;; relative to notmuch database
|
||||
|
||||
;; Mark things as read when archiving them:
|
||||
(setq notmuch-archive-tags '("-inbox" "-unread" "+archive"))
|
||||
|
||||
;; Show me saved searches that I care about:
|
||||
(setq notmuch-saved-searches
|
||||
'((:name "inbox" :query "tag:inbox" :count-query "tag:inbox AND tag:unread" :key "i")
|
||||
(:name "sent" :query "tag:sent" :key "t")
|
||||
(:name "drafts" :query "tag:draft")))
|
||||
(setq notmuch-show-empty-saved-searches t)
|
||||
|
||||
;; Mail sending configuration
|
||||
(setq send-mail-function 'sendmail-send-it) ;; sendmail provided by MSMTP
|
||||
(setq notmuch-always-prompt-for-sender t)
|
||||
(setq notmuch-mua-user-agent-function
|
||||
(lambda () (format "Emacs %s; notmuch.el %s" emacs-version notmuch-emacs-version)))
|
||||
(setq mail-host-address (system-name))
|
||||
(setq notmuch-mua-cite-function #'message-cite-original-without-signature)
|
||||
(setq notmuch-fcc-dirs nil) ;; Gmail does this server-side
|
||||
(setq message-signature nil) ;; Insert message signature manually with C-c C-w
|
||||
|
||||
;; Close mail buffers after sending mail
|
||||
(setq message-kill-buffer-on-exit t)
|
||||
|
||||
;; Ensure sender is correctly passed to msmtp
|
||||
(setq mail-specify-envelope-from t
|
||||
message-sendmail-envelope-from 'header
|
||||
mail-envelope-from 'header)
|
||||
|
||||
;; Store sent mail in the correct folder per account
|
||||
(setq notmuch-maildir-use-notmuch-insert nil)
|
||||
|
||||
;; I don't use drafts but I instinctively hit C-x C-s constantly, lets
|
||||
;; handle that gracefully.
|
||||
(define-key notmuch-message-mode-map (kbd "C-x C-s") #'ignore)
|
||||
|
||||
;; Define a telephone-line segment for displaying the count of unread,
|
||||
;; important mails in the last window's mode-line:
|
||||
(defvar *last-notmuch-count-redraw* 0)
|
||||
(defvar *current-notmuch-count* nil)
|
||||
|
||||
(defun update-display-notmuch-counts ()
|
||||
"Update and render the current state of the notmuch unread
|
||||
count for display in the mode-line.
|
||||
|
||||
The offlineimap-timer runs every 2 minutes, so it does not make
|
||||
sense to refresh this much more often than that."
|
||||
|
||||
(when (> (- (float-time) *last-notmuch-count-redraw*) 30)
|
||||
(setq *last-notmuch-count-redraw* (float-time))
|
||||
(let* ((inbox-unread (notmuch-saved-search-count "tag:inbox and tag:unread"))
|
||||
(notmuch-count (format "I: %s; D: %s" inbox-unread)))
|
||||
(setq *current-notmuch-count* notmuch-count)))
|
||||
|
||||
(when (and (bottom-right-window-p)
|
||||
;; Only render if the initial update is done and there
|
||||
;; are unread mails:
|
||||
*current-notmuch-count*
|
||||
(not (equal *current-notmuch-count* "I: 0; D: 0")))
|
||||
*current-notmuch-count*))
|
||||
|
||||
(telephone-line-defsegment telephone-line-notmuch-counts ()
|
||||
"This segment displays the count of unread notmuch messages in
|
||||
the last window's mode-line (if unread messages are present)."
|
||||
|
||||
(update-display-notmuch-counts))
|
||||
|
||||
(provide 'mail-setup)
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
;; Initializes modes I use.
|
||||
|
||||
(add-hook 'prog-mode-hook 'esk-add-watchwords)
|
||||
(add-hook 'prog-mode-hook 'hl-line-mode)
|
||||
|
||||
;; Use auto-complete as completion at point
|
||||
(defun set-auto-complete-as-completion-at-point-function ()
|
||||
(setq completion-at-point-functions '(auto-complete)))
|
||||
|
||||
(add-hook 'auto-complete-mode-hook
|
||||
'set-auto-complete-as-completion-at-point-function)
|
||||
|
||||
;; Enable rainbow-delimiters for all things programming
|
||||
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode)
|
||||
|
||||
;; Enable Paredit & Company in Emacs Lisp mode
|
||||
(add-hook 'emacs-lisp-mode-hook 'company-mode)
|
||||
|
||||
;; Always highlight matching brackets
|
||||
(show-paren-mode 1)
|
||||
|
||||
;; Always auto-close parantheses and other pairs
|
||||
(electric-pair-mode)
|
||||
|
||||
;; Keep track of recent files
|
||||
(recentf-mode)
|
||||
|
||||
;; Easily navigate sillycased words
|
||||
(global-subword-mode 1)
|
||||
|
||||
;; Transparently open compressed files
|
||||
(auto-compression-mode t)
|
||||
|
||||
;; Configure go-mode for Go2 Alpha
|
||||
(add-to-list 'auto-mode-alist '("\\.go2$" . go-mode))
|
||||
|
||||
(provide 'modes)
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
(require 'uniquify)
|
||||
|
||||
;; Move files to trash when deleting
|
||||
(setq delete-by-moving-to-trash t)
|
||||
|
||||
;; We don't live in the 80s, but we're also not a shitty web app.
|
||||
(setq gc-cons-threshold 20000000)
|
||||
|
||||
(setq uniquify-buffer-name-style 'forward)
|
||||
|
||||
; Fix some defaults
|
||||
(setq visible-bell nil
|
||||
inhibit-startup-message t
|
||||
color-theme-is-global t
|
||||
sentence-end-double-space nil
|
||||
shift-select-mode nil
|
||||
uniquify-buffer-name-style 'forward
|
||||
whitespace-style '(face trailing lines-tail tabs)
|
||||
whitespace-line-column 80
|
||||
default-directory "~"
|
||||
fill-column 80
|
||||
ediff-split-window-function 'split-window-horizontally
|
||||
initial-major-mode 'emacs-lisp-mode)
|
||||
|
||||
(add-to-list 'safe-local-variable-values '(lexical-binding . t))
|
||||
(add-to-list 'safe-local-variable-values '(whitespace-line-column . 80))
|
||||
|
||||
(set-default 'indent-tabs-mode nil)
|
||||
|
||||
;; UTF-8 please
|
||||
(setq locale-coding-system 'utf-8) ; pretty
|
||||
(set-terminal-coding-system 'utf-8) ; pretty
|
||||
(set-keyboard-coding-system 'utf-8) ; pretty
|
||||
(set-selection-coding-system 'utf-8) ; please
|
||||
(prefer-coding-system 'utf-8) ; with sugar on top
|
||||
|
||||
;; Make emacs behave sanely (overwrite selected text)
|
||||
(delete-selection-mode 1)
|
||||
|
||||
;; Keep your temporary files in tmp, emacs!
|
||||
(setq auto-save-file-name-transforms
|
||||
`((".*" ,temporary-file-directory t)))
|
||||
(setq backup-directory-alist
|
||||
`((".*" . ,temporary-file-directory)))
|
||||
|
||||
(remove-hook 'kill-buffer-query-functions 'server-kill-buffer-query-function)
|
||||
|
||||
;; Show time in 24h format
|
||||
(setq display-time-24hr-format t)
|
||||
|
||||
(provide 'settings)
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
# This file builds an Emacs pre-configured with the packages I need
|
||||
# and my personal Emacs configuration.
|
||||
#
|
||||
# On NixOS machines, this Emacs currently does not support
|
||||
# Imagemagick, see https://github.com/NixOS/nixpkgs/issues/70631.
|
||||
#
|
||||
# Forcing Emacs to link against Imagemagick currently causes libvterm
|
||||
# to segfault, which is a lot less desirable than not having telega
|
||||
# render images correctly.
|
||||
{ depot, lib, ... }:
|
||||
|
||||
let
|
||||
inherit (depot) third_party;
|
||||
|
||||
emacsWithPackages = (third_party.emacsPackagesGen third_party.emacs26).emacsWithPackages;
|
||||
|
||||
# $PATH for binaries that need to be available to Emacs
|
||||
emacsBinPath = lib.makeBinPath [ third_party.telega ];
|
||||
|
||||
identity = x: x;
|
||||
|
||||
tazjinsEmacs = pkgfun: (emacsWithPackages(epkgs: pkgfun(
|
||||
# Actual ELPA packages (the enlightened!)
|
||||
(with epkgs.elpaPackages; [
|
||||
ace-window
|
||||
avy
|
||||
flymake
|
||||
pinentry
|
||||
rainbow-mode
|
||||
undo-tree
|
||||
xelb
|
||||
]) ++
|
||||
|
||||
# MELPA packages:
|
||||
(with epkgs.melpaPackages; [
|
||||
ace-link
|
||||
browse-kill-ring
|
||||
cargo
|
||||
clojure-mode
|
||||
cmake-mode
|
||||
counsel
|
||||
counsel-notmuch
|
||||
dash-functional
|
||||
direnv
|
||||
dockerfile-mode
|
||||
eglot
|
||||
elixir-mode
|
||||
elm-mode
|
||||
erlang
|
||||
geiser
|
||||
go-mode
|
||||
gruber-darker-theme
|
||||
haskell-mode
|
||||
ht
|
||||
hydra
|
||||
idle-highlight-mode
|
||||
intero
|
||||
ivy
|
||||
ivy-pass
|
||||
ivy-prescient
|
||||
jq-mode
|
||||
kotlin-mode
|
||||
lispy
|
||||
lsp-mode
|
||||
magit
|
||||
markdown-toc
|
||||
meson-mode
|
||||
multi-term
|
||||
multiple-cursors
|
||||
nginx-mode
|
||||
nix-mode
|
||||
notmuch # this comes from pkgs.third_party
|
||||
org-journal
|
||||
org-ql
|
||||
paredit
|
||||
password-store
|
||||
pg
|
||||
polymode
|
||||
prescient
|
||||
protobuf-mode
|
||||
racket-mode
|
||||
rainbow-delimiters
|
||||
refine
|
||||
request
|
||||
restclient
|
||||
sly
|
||||
string-edit
|
||||
swiper
|
||||
telega
|
||||
telephone-line
|
||||
terraform-mode
|
||||
toml-mode
|
||||
transient
|
||||
use-package
|
||||
uuidgen
|
||||
web-mode
|
||||
websocket
|
||||
which-key
|
||||
yaml-mode
|
||||
yasnippet
|
||||
]) ++
|
||||
|
||||
# Custom packages
|
||||
(with depot.tools.emacs-pkgs; [
|
||||
dottime
|
||||
nix-util
|
||||
term-switcher
|
||||
|
||||
# patched / overridden versions of packages
|
||||
depot.third_party.emacs.exwm
|
||||
depot.third_party.emacs.rcirc
|
||||
depot.third_party.emacs.vterm
|
||||
depot.third_party.emacs.explain-pause-mode
|
||||
]))));
|
||||
in lib.fix(self: l: f: third_party.writeShellScriptBin "tazjins-emacs" ''
|
||||
export PATH="${emacsBinPath}:$PATH"
|
||||
exec ${tazjinsEmacs f}/bin/emacs \
|
||||
--debug-init \
|
||||
--no-site-file \
|
||||
--no-site-lisp \
|
||||
--no-init-file \
|
||||
--directory ${./config} ${if l != null then "--directory ${l}" else ""} \
|
||||
--eval "(require 'init)" $@
|
||||
'' // {
|
||||
# Call overrideEmacs with a function (pkgs -> pkgs) to modify the
|
||||
# packages that should be included in this Emacs distribution.
|
||||
overrideEmacs = f': self l f';
|
||||
|
||||
# Call withLocalConfig with the path to a *folder* containing a
|
||||
# `local.el` which provides local system configuration.
|
||||
withLocalConfig = confDir: self confDir f;
|
||||
|
||||
# Build a derivation that uses the specified local Emacs (i.e.
|
||||
# built outside of Nix) instead
|
||||
withLocalEmacs = emacsBin: third_party.writeShellScriptBin "tazjins-emacs" ''
|
||||
export PATH="${emacsBinPath}:$PATH"
|
||||
export EMACSLOADPATH="${(tazjinsEmacs f).deps}/share/emacs/site-lisp:"
|
||||
exec ${emacsBin} \
|
||||
--debug-init \
|
||||
--no-site-file \
|
||||
--no-site-lisp \
|
||||
--no-init-file \
|
||||
--directory ${./config} \
|
||||
${if l != null then "--directory ${l}" else ""} \
|
||||
--eval "(require 'init)" $@
|
||||
'';
|
||||
}) null identity
|
||||
Loading…
Add table
Add a link
Reference in a new issue