Skip to content

Latest commit

 

History

History
1349 lines (1049 loc) · 37.1 KB

config.org

File metadata and controls

1349 lines (1049 loc) · 37.1 KB

Emacs config

Before anything, symlink this directory to .emacs.d. Then just start emacs and it will bootstrap itself.

Table Of Contents

Bootstrap

Improve compile time

(setq gc-cons-threshold 100000000)

diminish.el

We’ll also install diminish.el to use with use-package.

(use-package diminish :straight t)

Utils

Let’s define some utils to write our config. First, a function to get the cache root dir and another to get and create subdirs inside the cache dir.

(defun my/cache-dir ()
  (let ((d (file-name-as-directory (or (getenv "XDG_CACHE_HOME") (concat (file-name-as-directory (getenv "HOME")) ".cache/emacs.d")))))
    (when (not (file-directory-p d))
      (make-directory d t))
    d))

(defun my/app-cache-dir (app-name)
  (let ((d (file-name-as-directory (concat (my/cache-dir) app-name))))
    (when (not (file-directory-p d))
      (mkdir d))
      d))

Text editing

Modal editing

[TODO test meow instead]

We’ll use evil for modal editing.

First, let’s define a key to be the leader. There’s a package for that but I’m not sure if I need it yet.

(defcustom my/evil-leader-key
  "'"
  "Key to be used as prefix for a number of commands."
  :type "key"
  :group 'my/evil
  )

(defvar my/evil-leader-key-map
  (let ((m (make-sparse-keymap)))
    (define-key m "f" 'find-file)
    (define-key m "b" 'switch-to-buffer)
    (define-key m "x" 'execute-extended-command)
    (define-key m "k" 'kill-buffer)
    (define-key m "o" 'other-window)
    (define-key m "?" 'xref-find-references)
    m))

We’ll need to initialize general.el so we can have a leader key taking precedence over evil-collection stuff:

(use-package general :straight t
  :init
  (setq general-override-states '(insert
                                  emacs
                                  hybrid
                                  normal
                                  visual
                                  motion
                                  operator
                                  replace)))

Now the actual package:

(use-package evil :straight t
  :after (general)
  :init
  (setq evil-want-keybinding nil)
  (setq evil-undo-system 'undo-tree)
  (setq evil-want-fine-undo t)
  :config
  (evil-mode 1)
  (general-define-key
   :states '(normal visual motion)
   :keymaps 'override
   my/evil-leader-key my/evil-leader-key-map)
  :bind
  (:map evil-normal-state-map
        ("." . nil)
        ("C-." . nil)
        :map evil-motion-state-map
        ("H" . nil)
        ("L" . nil)
        :map evil-insert-state-map
        ("C-k" . nil)))

(use-package evil-collection :straight t
  :after (evil)
  :custom
  (evil-collection-setup-minibuffer t)
  :init
  (evil-collection-init))

We’ll also add evil-visualstar so we can search text that is selected using visual mode:

(use-package evil-visualstar :straight t
  :config
  (global-evil-visualstar-mode +1))

Indentation

Let’s start by setting indent to spaces by default.

(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)

Scrolling

(setq scroll-step 1)

Crux - or better move-beginning-of-line

We’ll install crux basically for the crux-move-beginning-of-line.

(use-package crux :straight t
  :bind
  ([remap move-beginning-of-line] . crux-move-beginning-of-line))

Parenthesis

Coloring them:

(use-package rainbow-delimiters :straight t
  :hook (prog-mode . rainbow-delimiters-mode))

Showing the matching one:

(show-paren-mode 1)
(set-face-attribute 'show-paren-match nil :weight 'extra-bold)
(set-face-attribute 'show-paren-mismatch nil :weight 'extra-bold)

Show line numbers

(use-package display-line-numbers
  :init
  (setq display-line-numbers-type 'relative)
  :config
  (global-display-line-numbers-mode t))

Show hex colors

rainbow-mode matches the background color to the color represented by a text (eg the hex “#efefef”)

(use-package rainbow-mode :straight t)

Keymap to toggle line wrap

Useful when reading logs

(global-set-key (kbd "C-c $") 'toggle-truncate-lines)

Keep files clear of trailing whitespaces

We delete whitespaces on the save hook:

(add-hook 'before-save-hook 'delete-trailing-whitespace)

Up/downcase region commands

(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)

Better undo

(use-package undo-tree :straight t
  :diminish undo-tree-mode
  :init
  (setq undo-tree-auto-save-history t)
  (setq undo-tree-history-directory-alist (list (cons ".*" (my/app-cache-dir "undo-tree"))))
  :config
  (global-undo-tree-mode 1))

Spell checking

We’ll use ispell.

(use-package ispell :straight t
  :init
  (setq ispell-dictionary "american"))

Associated with flyspell to highlight spelling errors.

(use-package flyspell
  :straight t
  :hook ((prog-mode . flyspell-prog-mode)
         (text-mode . flyspell-mode))
  :bind (:map flyspell-mode-map
              ("C-;" . nil)
              ("C-." . nil))
  :diminish flyspell-mode flyspell-prog-mode)

[TODO: flyspell defines C-M i which clashes with autocompletions]

Completion

I’ve used helm for maybe 8 years now, so it’s time to try something new, so let’s try vertico. Its main selling point for me is the simplicity and that it ties to the default completion framework built in to Emacs.

(use-package vertico :straight t
  :bind
  (:map vertico-map
  ("C-j" . vertico-next)
  ("C-k" . vertico-previous))
  :init
  (vertico-mode))

(use-package vertico-directory
  :load-path "straight/build/vertico/extensions"
  :requires (vertico)
  :bind
  (:map vertico-map
        ("M-h" . vertico-directory-up)))

(use-package emacs
  :init
  ;; Do not allow the cursor in the minibuffer prompt
  (setq minibuffer-prompt-properties
        '(read-only t cursor-intangible t face minibuffer-prompt))
  (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode))

And let’s use orderless as the completion style (it’s a fuzzy matching style of completing, instead of the default prefix match).

(use-package orderless :straight t
  :init
  (setq completion-styles '(orderless)
        completion-category-defaults nil
        completion-category-overrides '((file (styles partial-completion)))))

(TODO: test prescient.el instead of orderless)

And marginalia:

(use-package marginalia :straight t
  ;; Either bind `marginalia-cycle` globally or only in the minibuffer
  :bind (("M-A" . marginalia-cycle)
         :map minibuffer-local-map
         ("M-A" . marginalia-cycle))

  ;; The :init configuration is always executed (Not lazy!)
  :init

  ;; Must be in the :init section of use-package such that the mode gets
  ;; enabled right away. Note that this forces loading the package.
  (marginalia-mode))

We’ll also need embark for actions on the completing candidates:

(use-package embark :straight t

  :bind
  (("C-." . embark-act)
   ("C-;" . embark-dwim))

  :config

  ;; Hide the mode line of the Embark live/completions buffers
  (add-to-list 'display-buffer-alist
               '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
                 nil
                 (window-parameters (mode-line-format . none)))))

Now let’s install yasnippet.

(use-package yasnippet :straight t
  :diminish yas-minor-mode
  :bind (:map my/evil-leader-key-map
              ("y" . yas-insert-snippet))
  :config
  (yas-global-mode 1))

Finally, for a better completion command:

(global-set-key (kbd "C-;") #'completion-at-point)

Automatically reload change files

(auto-revert-mode +1)

Increment number package

This gives us commands to increment/decrement numbers at point.

(use-package shift-number :straight t
  :bind (:map my/evil-leader-key-map
              ("+" . shift-number-up)
              ("-" . shift-number-down)))

Quality of Life

Set default browser

Set browser function to find the default OS browser to open URLs.

(setq browse-url-browser-function 'browse-url-default-browser)

Save history

Well, emacs has a mode for saving history of stuff written in the minibuffer. Let’s enable that

(use-package savehist
  :init
  (savehist-mode))

scratch buffer major mode

(setq initial-major-mode 'markdown-mode)

Change confirmation prompt to ask just for “y” or “n”

(defalias 'yes-or-no-p 'y-or-n-p)

Disable lockfiles

Never saw the need for that

(setq create-lockfiles nil)

Fixing autosave/backup files

One annoying thing is the temporary files that emacs creates on the same folder as our source. We’ll instruct emacs to store these files in a temporary dir.

(setq backup-directory-alist
      `((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms
      `((".*" ,temporary-file-directory t)))

More ergonomic exec-command bind

(global-set-key (kbd "C-x C-m") 'execute-extended-command)
(global-set-key (kbd "M-x") nil)

which-key

Great mode for completing the next keys you can enter after a prefix.

(use-package which-key :straight t
  :config
  (which-key-mode))

Improve eldoc

Tells eldoc to show documentation from different sources concatenated.

(use-package eldoc :straight t
  :diminish eldoc-mode
  :custom
  (eldoc-echo-area-prefer-doc-buffer t)
  :config
  (global-eldoc-mode 1)
  (setq eldoc-documentation-function #'eldoc-documentation-compose))

better help buffers

(use-package helpful
  :straight t
  :bind (("C-h f" . helpful-callable)
         ("C-h v" . helpful-variable)
         ("C-h k" . helpful-key)
         ("C-h f" . helpful-function)
         ("C-h c" . helpful-command)))

Navigation

Project.el

(use-package project
  :after (evil general)
  :config
  <<project-el-kill-buffers>>
  <<project-el-override-leader-key>>)

We are making use of a custom command to save all buffers from the project:

;; copied predicate from project.el
(defun my/project-buffer-p (project buf)
  (let ((root (expand-file-name (file-name-as-directory (project-root project)))))
    (string-prefix-p root (expand-file-name
                           (buffer-local-value 'default-directory buf)))))

;; let's define a function to save all buffers from a project
(defun my/project-save-buffers ()
  "Save buffers for a given project"
  (interactive)
  (let ((pr (project-current)))
    (save-some-buffers nil (lambda () (my/project-buffer-p pr (current-buffer))))))

(define-key project-prefix-map "s" #'my/project-save-buffers)

And finally let’s define a prefix for the project key map:

(general-define-key
 :states '(normal visual motion)
 :keymaps 'override
 "SPC" project-prefix-map)

Window config history

This is done using winner-mode

(winner-mode 1)

Avy (goto char)

(use-package avy :straight t
  :after (evil)
  :bind (("M-g e" . avy-goto-word-0)
         :map evil-normal-state-map
         ("`" . avy-goto-word-0)))

Consult

(use-package consult :straight t
  :after (evil project)
  :bind
  (:map project-prefix-map
   ("/" . consult-ripgrep)
   :map evil-normal-state-map
   ("Q" . consult-goto-line)
   :map my/evil-leader-key-map
   ("/" . consult-ripgrep))
  :init
  (setq completion-in-region-function (lambda (&rest args)
                                        (apply (if vertico-mode
                                                   #'consult-completion-in-region
                                                 #'completion--in-region)
                                               args))))

And since we’re using embark, let’s also install embark-consult:

(use-package embark-consult :straight t)

Programming

Eglot

I use Eglot for almost every language I program.

(use-package eglot
  :bind
  (:map my/evil-leader-key-map
   ("e r" . eglot-code-actions)
   ("e e" . eglot-reconnect)
   ("e m" . eglot-rename)
   ("e I" . eglot-organize-imports))
  :config
  (add-to-list 'eglot-stay-out-of "eldoc-documentation-function$")
  (add-to-list 'eglot-stay-out-of 'eldoc-documentation-strategy)
  :hook
  (before-save . (lambda () (when (eglot-managed-p) (with-demoted-errors "Error when eglot-format-buffer: %s" (eglot-format-buffer))))))

Syntax checking

(use-package flymake
  :diminish flymake-mode
  :bind (:map my/evil-leader-key-map
              (">" . flymake-goto-next-error)
              ("<" . flymake-goto-prev-error))
  :hook (prog-mode . flymake-mode))

EditorConfig

Seems pretty useful to share settings between editors, so let’s configure it:

(use-package editorconfig
  :straight t
  :config
  (editorconfig-mode 1))

Git

Let’s install magit first.

(use-package magit
  :straight t
  :after (project)
  :bind
  (("C-c m s" . magit-status)
   ("C-c m b" . magit-blame-addition)
   :map magit-mode-map
   ("<SPC>" . nil))
  :init
  (setq magit-last-seen-setup-instructions "1.4.0")
  (setq magit-git-executable "git")
  ;; See https://github.com/magit/magit/issues/2541
  (setq magit-display-buffer-function
        (lambda (buffer)
          (display-buffer
           buffer (if (and (derived-mode-p 'magit-mode)
                           (memq (with-current-buffer buffer major-mode)
                                 '(magit-process-mode
                                   magit-revision-mode
                                   magit-diff-mode
                                   magit-stash-mode
                                   magit-status-mode)))
                      nil
                    '(display-buffer-same-window)))))
  (defun my/project-magit ()
    (interactive)
    (magit-status (car (project-roots (project-current)))))
  (define-key project-prefix-map (kbd "g") 'my/project-magit)
  (add-to-list 'project-switch-commands '(my/project-magit "Magit Status")))

Now to configure the commit buffer with spellcheck and markdown:

(use-package flyspell :straight t
  :after (magit)
  :hook
  (git-commit-mode . turn-on-flyspell))

(use-package markdown-mode :straight t
  :after (magit)
  :hook
  (git-commit-mode . markdown-mode))

Structured editing

(use-package evil-cleverparens :straight t)

(use-package evil-surround :straight t
  :config (global-evil-surround-mode 1))

(use-package symex :straight t
  :bind (:map my/evil-leader-key-map
              (";" . symex-mode-interface))
  :config
  (symex-initialize))

Syntax highlighting

Let’s list all the language grammars we have:

(setq treesit-language-source-alist
      '((bash "https://github.com/tree-sitter/tree-sitter-bash")
        (cmake "https://github.com/uyha/tree-sitter-cmake")
        (css "https://github.com/tree-sitter/tree-sitter-css")
        (elisp "https://github.com/Wilfred/tree-sitter-elisp")
        (elixir "https://github.com/elixir-lang/tree-sitter-elixir")
        (go "https://github.com/tree-sitter/tree-sitter-go")
        (gleam "https://github.com/gleam-lang/tree-sitter-gleam")
        (html "https://github.com/tree-sitter/tree-sitter-html")
        (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src")
        (json "https://github.com/tree-sitter/tree-sitter-json")
        (make "https://github.com/alemuller/tree-sitter-make")
        (markdown "https://github.com/ikatyang/tree-sitter-markdown")
        (python "https://github.com/tree-sitter/tree-sitter-python")
        (toml "https://github.com/tree-sitter/tree-sitter-toml")
        (tsx        "https://github.com/tree-sitter/tree-sitter-typescript"
                    "v0.20.3"
                    "tsx/src")
        (typescript "https://github.com/tree-sitter/tree-sitter-typescript"
                    "v0.20.3"
                    "typescript/src")
        (yaml "https://github.com/ikatyang/tree-sitter-yaml")))

And a command to install all the listed grammars:

(defun my/install-all-language-grammars ()
  (interactive)
  (mapc #'treesit-install-language-grammar (mapcar #'car treesit-language-source-alist)))

Now I can call it interactively any time I want to refresh my language grammars.

PlantUML

Cool for making uml charts.

(use-package plantuml-mode
  :straight t
  :mode ("\\.puml\\'" . plantuml-mode)
  :config
  (setq plantuml-jar-path "~/.local/plantuml/plantuml.jar")
  (setq plantuml-default-exec-mode 'jar))

Very useful inside org-mode, so let’s install the org babel extension:

(use-package ob-plantuml
  :config
  (setq org-plantuml-jar-path "~/utils/jars/plantuml.jar"))

direnv

(use-package direnv :straight t
  :config
  (direnv-mode))

JSON

We’ll install json and jsonnet modes:

(use-package json-mode :straight t
  :config
  (add-to-list 'auto-mode-alist '("\\.json.base\\'" . json-mode)))

(use-package jsonnet-mode :straight t
  :config
  (add-to-list 'auto-mode-alist '("\\.libjsonnet\\'" . jsonnet-mode)))

Markdown

(use-package markdown-mode :straight t
  :mode
  ("\\.markdown\\'" . markdown-mode)
  ("\\.md\\'" . markdown-mode))

yaml

(use-package yaml-mode :straight t)

protobuf

(use-package protobuf-mode :straight t
  :mode ("\\.proto$" . protobuf-mode))

Terraform

(use-package terraform-mode :straight t)

C/C++

(use-package cc-mode :straight t
  :hook
  (c-c++-mode . (lambda () (setq require-final-newline t)))
  :init
  (setq c-default-style "linux"
        c-basic-offset 4))

CMake

(use-package cmake-mode :straight t)

Go

(use-package go-mode :straight t
  :after (eglot)
  :hook
  (go-ts-mode . eglot-ensure)
  (go-mode . eglot-ensure)
  :config
  (unless (treesit-language-available-p 'go)
    (treesit-install-language-grammar 'go))
  (add-to-list 'major-mode-remap-alist '(go-mode . go-ts-mode)))

Let’s also add a helper package to run go tests:

(use-package gotest :straight t)

Snippets

# -*- mode: snippet -*-
# name: Tabular test boilerplate
# key: tc
# --
testCases := []struct {
    name     string
    $1
}{$2}

for _, tc := range testCases {
    t.Run(tc.name, func(t *testing.T) {
        $3
    })
}
# -*- mode: snippet -*-
# name: Error wrapper func
# key: wrapErr
# --
wrapErr := func(err error) error {
    return fmt.Errorf("$1: %w", err)
}

Web-mode

This is the final configuration:

(use-package web-mode :demand t
  :after (eglot)
  :straight t
  :mode (("\\.html?\\'" . web-mode))

  :config
  (setq web-mode-enable-auto-closing t)
  (setq web-mode-enable-auto-pairing t)
  (setq web-mode-code-indent-offset 2)
  (setq web-mode-markup-indent-offset 2)
  (setq web-mode-enable-literal-interpolation t))

Svelte

(require 'eglot)
(require 'web-mode)
(define-derived-mode my/svelte-mode web-mode "svelte"
  "Major mode for editing .svelte files using web-mode and LSP support")
(add-to-list 'auto-mode-alist '("\\.svelte\\'" . my/svelte-mode))
(add-hook 'my/svelte-mode-hook #'eglot-ensure)
(add-to-list 'eglot-server-programs '(my/svelte-mode . ("svelteserver" "--stdio")))

Typescript

Let’s configure the basics first:

(use-package typescript-ts-mode
  :straight t
  :mode (("\\.ts\\'" . typescript-ts-mode)
         ("\\.tsx\\'" . tsx-ts-mode)))

Now the LS

(use-package typescript-ts-mode
  :after (eglot)
  :hook
  (typescript-ts-mode . eglot-ensure)
  (tsx-ts-mode . eglot-ensure))

Snippets

# -*- mode: snippet -*-
# name: react-fc-ts
# key: fct
# --
import * as React from "react"

export interface ${1:component}Props {}

const $1: React.FC<$1Props> = (props) => {
     $2
}

export default $1;
# -*- mode: snippet -*-
# name: react-storybook-ts
# key: tstory
# --
import React from 'react';

import { ComponentStory, ComponentMeta } from '@storybook/react';

import ${1:MyComponent}, { $1Props } from '.';

export default {
    component: $1,
} as ComponentMeta<typeof $1>;

export const Basic: ComponentStory<typeof $1> = () => (<$1 />);

Dockerfiles

(use-package dockerfile-mode :straight t)

Clojure

Let’s add clojure-mode and cider:

(use-package clojure-mode :straight t
  :after (eglot evil-cleverparens)
  :hook
  (clojure-mode . eglot-ensure)
  (clojure-mode . evil-cleverparens-mode))

(use-package cider :straight t)

OCaml

(use-package tuareg :straight t
  :after (eglot)
  :hook (tuareg-mode . eglot-ensure))

Scala

(use-package scala-mode :straight t
  :after (eglot)
  :hook (scala-mode . eglot-ensure))

Nix

(use-package nix-mode :straight t
  :mode "\\.nix\\'"
  :after (eglot)
  :hook (nix-mode . eglot-ensure))

Bazel

(use-package bazel :straight t)

WKT

Well that’s something I’ll rarely use, but it’s nice to have the syntax highlighting for examples:

(use-package wkt-mode
  :straight (:type git
             :repo "https://github.com/orontee/wkt-mode"))

Lua

(use-package lua-mode :straight t)

Elixir

(use-package elixir-mode :straight t)
(use-package elixir-ts-mode :straight t)

(use-package eglot :straight t
  :after (elixir-mode)
  :config
  :hook
  (elixir-mode . eglot-ensure)
  (elixir-ts-mode . eglot-ensure)
  :config
  (add-to-list 'eglot-server-programs
               `((elixir-ts-mode heex-ts-mode elixir-mode) .
                 ("~/.local/elixir-ls/language_server.sh"))))

(use-package inf-elixir :straight t)

(use-package ob-elixir :straight t)

codeium

Github copilot works great, but I hate that it doesn’t plug into company mode. This made me try alternatives and I found this.

(use-package codeium
    :straight '(:type git :host github :repo "Exafunction/codeium.el")
    :init
    (add-to-list 'completion-at-point-functions #'codeium-completion-at-point)
    :config
    ;; (setq use-dialog-box nil) ;; do not use popup boxes

    ;; get codeium status in the modeline
    (setq codeium-mode-line-enable
        (lambda (api) (not (memq api '(CancelRequest Heartbeat AcceptCompletion)))))
    (add-to-list 'mode-line-format '(:eval (car-safe codeium-mode-line)) t)
    ;; alternatively for a more extensive mode-line
    ;; (add-to-list 'mode-line-format '(-50 "" codeium-mode-line) t)

    ;; use M-x codeium-diagnose to see apis/fields that would be sent to the local language server
    (setq codeium-api-enabled
        (lambda (api)
            (memq api '(GetCompletions Heartbeat CancelRequest GetAuthToken RegisterUser auth-redirect AcceptCompletion)))))

Github Copilot

Let’s jump in the bandwagon…

(use-package copilot
  :straight (:host github :repo "zerolfx/copilot.el" :files ("dist" "*.el"))
  :ensure t
  :hook (prog-mode . copilot-mode)
  :bind (:map copilot-completion-map
              ("C-y" . copilot-accept-completion)
              ("M-n" . copilot-next-completion)
              ("M-p" . copilot-previous-completion)))

Rust

(use-package rust-mode :straight t
  :after (eglot)
  :hook (rust-mode . eglot-ensure))

Zig

(use-package zig-mode :straight t
  :after (eglot)
  :hook (zig-mode . eglot-ensure))

Gleam

First the basic mode setup.

(use-package gleam-ts-mode
  :straight (:host github :repo "gleam-lang/gleam-mode" :branch "gleam-ts-mode")
  :config
  (add-to-list 'auto-mode-alist '("\\.gleam\\'" . gleam-ts-mode)))

Now treesit:

(use-package gleam-ts-mode
  :after (treesit)
  :config
  (add-to-list 'treesit-language-source-alist '(gleam "https://github.com/gleam-lang/tree-sitter-gleam"))
  (unless (treesit-language-available-p 'gleam)
    (treesit-install-language-grammar 'gleam)))

And finally eglot;

(use-package gleam-ts-mode
  :after (eglot)
  :hook (gleam-ts-mode . eglot-ensure))

Writing

Org-mode

We install org-mode using straight so we get the newest version

(use-package org :straight t
  :init
  (setq org-log-done 'time
        org-src-fontify-natively t
        org-log-into-drawer t
        org-confirm-babel-evaluate nil
        org-src-preserve-indentation nil
        org-edit-src-content-indentation 0)

  :hook
  (org-babel-after-execute . org-redisplay-inline-images)

  :config
  ;; load basic languages I use regularly inside org blocks
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((dot . t) ; graphviz
     (shell . t)
     (lisp . t)
     (emacs-lisp . t)
     (gnuplot . t)
     (plantuml . t)))
  (add-to-list 'org-export-backends 'md))

Github-flavored markdown exporter:

(use-package ox-gfm :straight t
  :after (org)
  :config
  (require 'ox-gfm))

One cool little tool is toc-org. It maintains an up to date TOC for us - very nice for seeing org files on Github.

(use-package toc-org :straight t
  :after (org)
  :hook
  (org-mode . toc-org-enable))

org-roam

I plan on using org-roam to start taking better notes.

(use-package org-roam :straight t
  :after (org)
  :init
  (setq org-roam-directory "~/reps/caioaao/slipbox")
  :config
  (org-roam-db-autosync-mode)
  :bind
  (("C-c n f" . org-roam-node-find)
   :map org-mode-map
        ("C-c n l" . org-roam-buffer-toggle)
        ("C-c n i" . org-roam-node-insert))
  :catch (lambda (keyword error)
           (message (error-message-string error))))

GUI

Let’s install the theme first:

(use-package doom-themes :straight t
  :config (load-theme 'doom-nord t))

Let’s remove all the window decorations here. We don’t need stuff for clicking if we don’t use mouse!

(setq default-frame-alist '((undecorated . t)
                            (drag-internal-border . 1)
                            (internal-border-width . 5)))
(tool-bar-mode -1)
(menu-bar-mode -1)
(scroll-bar-mode -1)

We also don’t need the startup screen or the scratch message:

(setq-default inhibit-startup-screen t)
(setq-default initial-scratch-message nil)

Now highlight current line everywhere

(global-hl-line-mode +1)

And the mode-line now. I really like what awesome-tray’s author had to say about the mode-line:

I don’t like mode-line, it’s too high, affect me to read the code. With Emacs, we only need to focus on very little information, such as time, current mode, git branch. Excessive information can seriously interfere with our attention.

Because of that, I decided to tray the more minimalistic ‘awesome-tray’.

(use-package awesome-tray
  :straight (:type git :host github :repo "manateelazycat/awesome-tray")
  :after (doom-themes)
  :init
  (setq awesome-tray-active-modules '("location" "evil" "buffer-name" "git" "mode-name"))
  (setq awesome-tray-mode-line-inactive-color (doom-lighten (doom-color 'bg) 0.2))
  (setq awesome-tray-mode-line-active-color (doom-lighten (doom-color 'bg) 0.5))
  :config
  (awesome-tray-mode 1))

Other

Copy environment variables

Let’s copy locale variables and the exec path.

(use-package exec-path-from-shell :straight t
  :config
  (setq exec-path-from-shell-check-startup-files nil)
  (exec-path-from-shell-initialize)
  (exec-path-from-shell-copy-envs '("LANG" "LC_ALL")))

Dired

Lest add more switches to dired, and also remove the bindings that clash with my own/evil’s

(use-package dired
  :after (evil evil-collection)
  :bind (:map dired-mode-map
              ("<SPC>" . nil))
  :config
  (setq dired-listing-switches "-alh")
  :hook (evil-collection-setup . (lambda (&rest args) (evil-define-key 'normal 'dired-mode-map "<SPC>" nil))))

GPG

In Ubuntu we need to copy SSH_AUTH_SOCK variable for some reason, so let’s use exec-path-from-shell

(use-package exec-path-from-shell :straight t
  :config
  (exec-path-from-shell-copy-env "SSH_AUTH_SOCK"))

Presentation mode

When I’m pairing remotely I need to set the font face bigger, so let’s add a keybind for that.

(define-minor-mode my/presentation-toggle-mode
  "Controls a toggle for 'presentation' mode.")


(defvar my/presentation-on? nil)

(defun my/presentation-toggle () (interactive)
       (if my/presentation-on?
           (progn (set-face-attribute 'default nil :height 100)
       (setq my/presentation-on? nil))
         (set-face-attribute 'default nil :height 200)
       (setq my/presentation-on? t)))

;; Local Variables: ;; eval: (add-hook ‘after-save-hook (lambda ()(if (y-or-n-p “Reload?”)(load-file user-init-file))) nil t) ;; eval: (add-hook ‘after-save-hook (lambda ()(if (y-or-n-p “Tangle?”)(org-babel-tangle))) nil t) ;; End: