diff options
Diffstat (limited to 'users/sterni/emacs')
-rw-r--r-- | users/sterni/emacs/default.nix | 80 | ||||
-rw-r--r-- | users/sterni/emacs/init.el | 257 | ||||
-rw-r--r-- | users/sterni/emacs/subscriptions.el | 84 |
3 files changed, 421 insertions, 0 deletions
diff --git a/users/sterni/emacs/default.nix b/users/sterni/emacs/default.nix new file mode 100644 index 000000000000..90b408d2d2fe --- /dev/null +++ b/users/sterni/emacs/default.nix @@ -0,0 +1,80 @@ +{ depot, pkgs, ... }: + +let + inherit (pkgs.emacsGcc.pkgs) withPackages; + + emacs = withPackages (epkgs: [ + # basic setup + epkgs.elpaPackages.undo-tree + epkgs.melpaPackages.evil + epkgs.melpaPackages.evil-collection + epkgs.melpaPackages.use-package + # languages + epkgs.bqn-mode + epkgs.elpaPackages.ada-mode + epkgs.melpaPackages.adoc-mode + epkgs.melpaPackages.direnv + epkgs.melpaPackages.dockerfile-mode + epkgs.melpaPackages.haskell-mode + epkgs.melpaPackages.jq-mode + epkgs.melpaPackages.languagetool + epkgs.melpaPackages.lsp-mode + epkgs.melpaPackages.lsp-haskell + epkgs.melpaPackages.markdown-mode + epkgs.melpaPackages.nix-mode + epkgs.melpaPackages.sly + epkgs.melpaPackages.yaml-mode + epkgs.rust-mode + epkgs.urweb-mode + # misc + epkgs.melpaPackages.hl-todo + epkgs.melpaPackages.paredit + epkgs.elpaPackages.rainbow-mode + epkgs.melpaPackages.rainbow-delimiters + # beyond text editing + epkgs.melpaPackages.elfeed + epkgs.melpaPackages.magit + epkgs.tvlPackages.tvl + ]); + + configDirectory = pkgs.symlinkJoin { + name = "emacs.d"; + paths = [ + ./. + (pkgs.writeTextFile { + name = "injected-emacs.d"; + destination = "/nix-inject.el"; + text = '' + ;; bqn-mode + (setq bqn-interpreter-path "${pkgs.cbqn}/bin/BQN") + + ;; languagetool + (setq languagetool-java-bin "${pkgs.jre}/bin/java" + languagetool-console-command "${pkgs.languagetool}/share/languagetool-commandline.jar" + languagetool-server-command "${pkgs.languagetool}/share/languagetool-server.jar" + languagetool-java-arguments '("-Dfile.encoding=UTF-8")) + + (provide 'nix-inject) + ''; + }) + ]; + postBuild = '' + rm "$out/default.nix" + ''; + }; +in + +# sadly we can't give an init-file via the command line +(pkgs.writeShellScriptBin "emacs" '' + exec ${emacs}/bin/emacs \ + --no-init-file \ + --directory ${configDirectory} \ + --eval "(require 'init)" \ + "$@" +'').overrideAttrs (super: { + buildCommand = '' + ${super.buildCommand} + + ln -s "${emacs}/bin/emacsclient" "$out/bin/emacsclient" + ''; +}) diff --git a/users/sterni/emacs/init.el b/users/sterni/emacs/init.el new file mode 100644 index 000000000000..c8c69af4eb01 --- /dev/null +++ b/users/sterni/emacs/init.el @@ -0,0 +1,257 @@ +;; Set default font and fallback font via set-fontset-font +;; TODO(sterni): Investigate why ZWJ sequences aren't shaped properly +(let ((mono-font "Bitstream Vera Sans Mono-12") + (emoji-font "Noto Color Emoji-12")) + (setq default-frame-alist `((font . ,mono-font))) + (set-frame-font mono-font t t) + (set-fontset-font t nil emoji-font)) + +(setq inhibit-startup-message t + display-time-24hr-format t + select-enable-clipboard t) + +;; Reload files +(global-auto-revert-mode 1) + +;; Indent +(setq-default indent-tabs-mode nil) +(setq tab-width 2 + css-indent-offset tab-width) + +;; UTF-8 +(setq locale-coding-system 'utf-8) +(set-terminal-coding-system 'utf-8) +(set-keyboard-coding-system 'utf-8) +(set-selection-coding-system 'utf-8) +(prefer-coding-system 'utf-8) + +;; Disable unnecessary GUI elements +(scroll-bar-mode 0) +(menu-bar-mode 0) +(tool-bar-mode 0) + +(add-hook 'after-make-frame-functions + (lambda (frame) (scroll-bar-mode 0))) + +;; don't center on cursor when scrolling +(setq scroll-conservatively 1) + +;; type less +(defalias 'yes-or-no-p 'y-or-n-p) + +;; Extra settings when graphical session +(when window-system + (setq frame-title-format '(buffer-file-name "%f" ("%b"))) + (mouse-wheel-mode t) + (blink-cursor-mode -1)) + +;; /tmp is a tmpfs, but we may want to recover from power loss +(custom-set-variables + `(temporary-file-directory ,(concat (getenv "HOME") "/.emacs/tmp"))) + +(setq auto-save-file-name-transforms + `((".*" ,temporary-file-directory t))) +(setq backup-directory-alist + `((".*" . ,temporary-file-directory))) +(setq undo-tree-history-directory-alist + `((".*" . ,temporary-file-directory))) +(setq backup-by-copying t) +(setq create-lockfiles nil) + +;; save history +(savehist-mode) +(setq savehist-additional-variables '(search-ring regexp-search-ring magit-cl-history)) + +;; buffers +;; unique component should come first for better completion +(setq uniquify-buffer-name-style 'forward) + +;; completions +(ido-mode 1) +(setq ido-enable-flex-matching t) +(ido-everywhere) +(fido-mode) + +;; Display column numbers +(column-number-mode t) +(setq-default fill-column 80) +(setq display-fill-column-indicator-column t) +(add-hook 'prog-mode-hook #'display-fill-column-indicator-mode) + +;; whitespace +(setq whitespace-style '(face trailing tabs) + whitespace-line-column fill-column) +(add-hook 'prog-mode-hook #'whitespace-mode) +(setq-default indicate-empty-lines t) +(setq-default indicate-buffer-boundaries 'left) +(setq sentence-end-double-space nil) + +;;; Configure built in modes + +;; Perl +(setq perl-indent-level 2) +(setq perl-continued-statement-offset 0) +(setq perl-continued-brace-offset 0) + +;; org mode + +(setq org-clock-persist 'history) +(org-clock-persistence-insinuate) + +(let ((org-folder (concat (getenv "HOME") "/files/sync/org"))) + (setq org-agenda-files (directory-files-recursively org-folder "\\.org$") + org-default-notes-file (concat org-folder "/inbox.org") + initial-buffer-choice org-default-notes-file)) + +;;; Configure packages +(require 'use-package) + +(package-initialize) + +(use-package undo-tree + :config + (global-undo-tree-mode) + (setq undo-tree-auto-save-history t)) + +(use-package magit + :after evil + :config + ; reset (buffer-local) fill-column value to emacs' default + ; gerrit doesn't like 80 column commit messages… + (add-hook 'git-commit-mode-hook (lambda () (setq fill-column 72))) + (evil-define-key 'normal 'global (kbd "<leader>gr") 'magit-status)) +(use-package tvl + :after magit + :custom tvl-depot-path (concat (getenv "HOME") "/src/depot")) + +(setq ediff-split-window-function 'split-window-horizontally) + +(use-package evil + :init + (setq evil-want-integration t) + (setq evil-want-keybinding nil) + (setq evil-shift-width 2) + (setq evil-split-window-below t) + (setq evil-split-window-right t) + (setq evil-undo-system 'undo-tree) + :config + (evil-mode 1) + (evil-set-leader 'normal ",") ;; TODO(sterni): space would be nice, but… + (evil-set-leader 'visual ",") + ;; buffer management + (evil-define-key 'normal 'global (kbd "<leader>bk") 'kill-buffer) + (evil-define-key 'normal 'global (kbd "<leader>bb") 'switch-to-buffer) + (evil-define-key 'normal 'global (kbd "<leader>bl") 'list-buffers) + ;; window management + (evil-define-key 'normal 'global (kbd "<leader>wk") 'delete-window) + (evil-define-key 'normal 'global (kbd "<leader>wo") 'delete-other-window) + (evil-define-key 'normal 'global (kbd "<leader>wh") 'split-window-below) + (evil-define-key 'normal 'global (kbd "<leader>wv") 'split-window-right) + (evil-define-key 'normal 'global (kbd "<leader>ww") 'other-window) + ;; emacs + (evil-define-key 'visual 'global (kbd "<leader>ee") 'eval-region) + (evil-define-key 'normal 'global (kbd "<leader>ee") 'eval-last-sexp) + (evil-define-key 'normal 'global (kbd "<leader>ep") 'eval-print-last-sexp) + (evil-define-key 'normal 'global (kbd "<leader>eh") 'help) + ;; modify what is displayed + (evil-define-key 'normal 'global (kbd "<leader>dw") + (lambda () + (interactive) + (whitespace-mode 'toggle) + (display-fill-column-indicator-mode 'toggle))) + ;; org-mode + (evil-define-key 'normal 'global (kbd "<leader>oa") 'org-agenda) + (evil-define-key 'normal 'global (kbd "<leader>oc") 'org-capture) + ;; elfeed bindings for evil (can't use-package elfeed apparently) + (evil-define-key 'normal 'global (kbd "<leader>ff") 'elfeed) + (evil-define-key '(normal visual) elfeed-search-mode-map + (kbd "o") 'elfeed-search-browse-url + (kbd "r") 'elfeed-search-untag-all-unread + (kbd "u") 'elfeed-search-tag-all-unread + (kbd "<leader>ff") 'elfeed-search-fetch + (kbd "<leader>fc") 'elfeed-db-compact + (kbd "<leader>fr") 'elfeed-search-update--force)) + +(use-package evil-collection + :after evil + :config + (evil-collection-init)) + +;; parens +(use-package rainbow-delimiters + :hook ((prog-mode . rainbow-delimiters-mode))) + +(setq show-paren-delay 0) +(show-paren-mode) + +(use-package paredit + :hook ((emacs-lisp-mode . paredit-mode) + (lisp-mode . paredit-mode) + (ielm-mode . paredit-mode) + (lisp-interaction-mode . paredit-mode))) + +(use-package nix-mode :mode "\\.nix\\'") +(use-package nix-drv-mode :mode "\\.drv\\'") + +(use-package direnv + :config (direnv-mode)) + +(use-package haskell-mode) +(use-package lsp-mode + :hook ((haskell-mode . lsp-deferred)) + :commands (lsp lsp-deferred)) +(use-package lsp-haskell) + +(use-package urweb-mode) +(use-package bqn-mode + :mode "\\.bqn\\'" + :custom bqn-mode-map-prefix "C-s-") ; probably rather using C-\ +(use-package yaml-mode) +(use-package dockerfile-mode) +(use-package jq-mode + :config (add-to-list 'auto-mode-alist '("\\.jq\\'" . jq-mode))) +(use-package rust-mode) +(use-package sly + :after evil + :hook ((sly-mrepl-mode . (lambda () + (enable-paredit-mode) + (rainbow-delimiters-mode-enable)))) + :config + (evil-define-key '(normal insert) sly-mrepl-mode-map (kbd "C-r") 'isearch-backward)) + +(use-package ada-mode) + +(use-package rainbow-mode) +(use-package hl-todo + :hook ((prog-mode . hl-todo-mode)) + :config + (setq hl-todo-keyword-faces + '(("TODO" . "#FF0000") + ("FIXME" . "#FF0000") + ("HACK" . "#7f7f7f") + ("XXX" . "#aa0000")))) + +(use-package markdown-mode + :commands (markdown-mode gfm-mode) + :mode (("\\.md\\'" . markdown-mode))) +(use-package adoc-mode + :mode (("\\.adoc\\'" . adoc-mode))) +(use-package languagetool + :after evil + :custom + languagetool-java-arguments '("-Dfile.encoding=UTF-8") + languagetool-default-language "en-GB" + languagetool-mother-tongue "de-DE" + :config + (evil-define-key 'normal 'global (kbd "<leader>ll") 'languagetool-check) + (evil-define-key 'normal 'global (kbd "<leader>lc") 'languagetool-correct-at-point) + (evil-define-key 'normal 'global (kbd "<leader>ls") 'languagetool-set-language) + (evil-define-key 'normal 'global (kbd "<leader>lr") 'languagetool-clear-buffer)) + +(unless (server-running-p) + (server-start)) + +(require 'subscriptions) +(require 'nix-inject) + +(provide 'init) diff --git a/users/sterni/emacs/subscriptions.el b/users/sterni/emacs/subscriptions.el new file mode 100644 index 000000000000..50bfff81f667 --- /dev/null +++ b/users/sterni/emacs/subscriptions.el @@ -0,0 +1,84 @@ +;;; elfeed subscriptions + +(setq elfeed-feeds + (append + ;; immutable subscriptions tracked in git + '(("https://repology.org/maintainer/sternenseemann%40systemli.org/feed-for-repo/nix_unstable/atom" dashboard releases) + ("http://hundimbuero.blogspot.com/feeds/posts/default?alt=rss" blog cool-and-nice) + ("gopher://text.causal.agency/0feed.atom" blog) + ("http://xsteadfastx.org/feed/" blog cool-and-nice) + ("https://tvl.fyi/feed.atom" blog cool-and-nice) + ("https://hannes.robur.coop/atom" blog) + ("https://stevelosh.com/rss.xml" blog) + ("https://planet.lisp.org/rss20.xml" blog) + ("https://hyperthings.garden/rss/all-posts.xml" blog) + ("https://blog.benjojo.co.uk/rss.xml" blog) + ("https://leahneukirchen.org/blog/index.atom" blog cool-and-nice) + ("https://leahneukirchen.org/trivium/index.atom" blog links cool-and-nice) + ("https://firefly.nu/feeds/all.atom.xml" blog cool-and-nice) + ("https://tazj.in/feed.atom" blog cool-and-nice) + ("https://alyssa.is/feed.xml" blog cool-and-nice) + ("https://eta.st/feed.xml" blog cool-and-nice) + ("https://spectrum-os.org/git/www/atom/bibliography.html" links blog) + ("https://rachelbythebay.com/w/atom.xml" blog) + ("http://evrl.com/feed.xml" blog) + ("https://vulns.xyz/feed.xml" blog) + ("https://www.german-foreign-policy.com/?type=9818" news) + ("https://niedzejkob.p4.team/rss.xml" blog) + ("https://grahamc.com/feed/" blog) + ("https://michael.stapelberg.ch/feed.xml" blog) + ("https://kazu-yamamoto.hatenablog.jp/feed" blog) + ("https://ariadne.space/feed/" blog) + ("https://bodil.lol/rss.xml" blog) + ("http://blog.nullspace.io/feed.xml" blog) + ("https://blog.kingcons.io/rss.xml" blog) + ("http://jaspervdj.be/rss.xml" blog) + ("https://www.imperialviolet.org/iv-rss.xml" blog) + ("https://latacora.micro.blog/feed.xml" blog) + ("https://22gato.tumblr.com/rss" pictures cool-and-nice) + ("https://theprofoundprogrammer.com/rss" blog) + ("https://wiki.openlab-augsburg.de/_feed" openlab) + ("http://shitopenlabsays.tumblr.com/rss" openlab) + ("http://suckless.org/atom.xml" releases) + ("https://kristaps.bsd.lv/lowdown/atom.xml" releases) + ("http://0pointer.net/blog/index.atom" blog) + ("https://emacsninja.com/feed.atom" blog) + ("https://emacshorrors.com/feed.atom" blog) + ("http://therealmntmn.tumblr.com/rss" blog) + ("http://blog.duangle.com/feeds/posts/default" blog) + ("http://blog.johl.io/atom.xml" blog) + ("http://blog.z3bra.org/rss/feed.xml" blog) + ("http://ccc.de/de/rss/updates.xml" news) + ;; ("http://fabienne.us/feed/" blog) ; database error + ("http://feeds.feedburner.com/baschtcom" blog) + ("http://ffaaaffaffaffaa.tumblr.com/rss" pictures) + ("http://fnordig.de/feed.xml" blog) + ("http://fotografiona.tumblr.com/rss" pictures) + ("https://grandhotel-cosmopolis.org/de/feed" news) + ("http://guteaussicht.org/rss" pictures) + ("http://konvergenzfehler.de/feed/" blog) + ("https://markuscisler.com/feed.xml" blog) + ("http://n00bcore.de/feed/" podcast) + ("http://spacethatneverwas.tumblr.com/rss" pictures) + ("http://theresa.someserver.de/blog/?feed=rss2" blog) + ("http://www.frumble.de/blog/feed/" blog) + ("http://www.plomlompom.de/PlomRogue/plomwiki.php?action=Blog_Atom" blog) + ("http://www.whvrt.de/rss" pictures) + ("http://www.windytan.com/feeds/posts/default" blog) + ("https://echtsuppe.wordpress.com/feed/" blog defunct) + ("https://mgsloan.com/feed.xml" blog) + ("https://notes.sterni.lv/atom.xml" me) + ("http://arduina.net/feed/" defunct blog) + ("http://beza1e1.tuxen.de/blog_en.atom" blog) + ("https://anchor.fm/s/94bb000/podcast/rss" podcast)) + ;; http://www.wollenzin.de/feed/ ;_; + + ;; add more feeds from an untracked file in $HOME + (let ((file (concat (getenv "HOME") + "/.config/emacs-custom/mutable-subscriptions.el"))) + (when (file-exists-p file) + (read (with-temp-buffer + (insert-file-contents file) + (buffer-string))))))) + +(provide 'subscriptions) |