Skip to content

Latest commit

 

History

History
1118 lines (880 loc) · 32.6 KB

configuration.org

File metadata and controls

1118 lines (880 loc) · 32.6 KB

Emacs Configuration

Early Configuration

Increase Garbage Collection Threshold

Let’s increase emacs’ garbage collector threshold and inhibit font cache compression:

(setq gc-cons-threshold (* 100 1024 1024)
      inhibit-compacting-font-caches t)

Track Initialization Time

This little snippet from System Crafters helps us track emacs initialization time

(defun fb/display-startup-time ()
  (message "Emacs loaded in %s with %d garbage collections."
           (format "%.2f seconds"
                   (float-time
                    (time-subtract after-init-time before-init-time)))
           gcs-done))

(add-hook 'emacs-startup-hook #'fb/display-startup-time)

Package System

The first thing we need to do is initialize emacs’s package system. That’s achieved with the following elisp code.

 (require 'package)

 (setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")

 (add-to-list 'package-archives
		  '("melpa" . "http://melpa.org/packages/"))
 (add-to-list 'package-archives
		  '("elpa" . "https://elpa.gnu.org/packages/"))

 (package-initialize)

The Basics

User Name, Email, etc

This is where I’ll setup some basic defaults for emacs. Things like user-full-name, user-mail-address and similar will be here.

(setq user-full-name "Felipe Balbi"
      user-mail-address "[email protected]"
      calendar-latitude 60.17
      calendar-longitude 24.94
      calendar-location-name "Helsinki, FI"
      inhibit-startup-screen t
      make-backup-files nil)
(global-prettify-symbols-mode t)

Windows Specific Settings

If I’m running on windows, let’s make things a little saner.

(if (eq system-type 'windows-nt)
    (setq-default visible-bell t
                  buffer-file-coding-system 'utf-8-unix))

Host Specific Settings

Depending on the machine I am, I might need some extra configuration. For example, at the office I need a proxy to get through to the outside world. To cope with that, I’ll add an optional site-local.el file on such machines and conditionally load it.

(let ((filename (concat "~/.emacs.d/" (system-name) ".org.gpg")))
  (if (file-exists-p filename)
      (org-babel-load-file filename)))

Prevent Accidentally closing emacs

I tend to hit C-x C-c by accident all the time. This little trick helps me a lot

(setq confirm-kill-emacs 'yes-or-no-p)

Numbers, numbers, numbers

(setq fill-column 80)
(column-number-mode)

(add-hook 'prog-mode-hook #'display-line-numbers-mode)
(add-hook 'tex-mode-hook #'display-line-numbers-mode)

Indentation

Some indentation configuration using mode-specific hooks

(add-hook 'sh-mode-hook
          (lambda ()
            (setq sh-basic-offset 2)))

(add-hook 'ruby-mode-hook
          (lambda ()
            (setq ruby-indent-level 2)))

(add-hook 'js-mode-hook
          (lambda ()
            (setq js-indent-level 2)
            (setq indent-tabs-mode nil)))

(add-hook 'rust-mode-hook
          (lambda ()
            (setq indent-tabs-mode nil)))

(add-hook 'sgml-mode-hook
          (lambda ()
            (setq indent-tabs-mode nil)))

(add-hook 'c-mode-hook
          (lambda ()
            (c-set-style "linux")
            (setq c-basic-offset 8
                  c-block-comment-prefix "* ")
            (c-set-offset 'arglist-intro '++)
            (c-set-offset 'arglist-cont '++)
            (c-set-offset 'arglist-cont-nonempty '++)
            (setq indent-tabs-mode t)))

(add-hook 'c++-mode-hook
          (lambda ()
            (c-set-style "gnu")
            (setq c-basic-offset 4)
            (setq c-block-comment-prefix "* ")
            (setq indent-tabs-mode nil)))

(add-hook 'lisp-mode-hook
          (lambda ()
            (setq indent-tabs-mode nil)))

(add-hook 'scheme-mode-hook
          (lambda ()
            (setq indent-tabs-mode nil)))

(add-hook 'awk-mode-hook
          (lambda ()
            (c-set-style "awk")))

Highlight Current Line

And I like to highlight current line

(global-hl-line-mode)

Current Time

I wanna see a simple clock in my modeline, so let’s enable display-time-mode

(setq display-time-24hr-format t)
(display-time-mode 1)

Default grep options

Better grep:

(setq grep-command "grep --color -nH -e")

Always follow symlinks

(setq vc-follow-symlinks t)

Disable lockfiles

(setq create-lockfiles nil)

Setup a new home for custom-file

Well, I don’t want custom touching my beautiful init.el. Let’s give it a dumping ground.

(unless (file-exists-p "~/.emacs.d/custom.el")
  (with-temp-buffer (write-file "~/.emacs.d/custom.el")))

(setq custom-file "~/.emacs.d/custom.el")
(load custom-file)

Bars, Menus, Tooltips

We really don’t need bars for everything when you’re using keyboard only.

(scroll-bar-mode -1)
(horizontal-scroll-bar-mode -1)
(menu-bar-mode -1)
(tool-bar-mode -1)
(tooltip-mode -1)

Setup native-comp

(setq native-comp-deferred-compilation t)
(setq native-comp-async-report-warnings-errors nil)

Install use-package if necessary

use-package let’s me quickly and easily rebuild my configuration by simply cloning this repository and opening emacs. The first time, it will install all required packages.

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(eval-when-compile
  (require 'use-package))

While at that, also make sure that use-package will ensure and defer by default

(setq use-package-always-ensure t
      use-package-always-defer  t)

Setup fontaine

I like to use Iosevka Comfy for pretty much everything.

(use-package fontaine
  :ensure t
  :init
  (setq fontaine-latest-state-file
        (locate-user-emacs-file "fontaine-latest-state.eld"))
  (fontaine-set-preset (or (fontaine-restore-latest-preset) 'regular))
  (add-hook 'kill-emacs-hook #'fontaine-store-latest-preset)
  (add-hook 'modus-themes-after-load-theme-hook #'fontaine-apply-current-preset)
  :bind
  (("C-c f" . fontaine-set-preset)
   ("C-c F" . fontaine-set-face-font))
  :custom
  (fontaine-presets
   '((tiny
      :default-family "Iosevka Comfy Wide Fixed"
      :default-height 100)
     (small
      :default-family "Iosevka Comfy Fixed"
      :default-height 120)
     (regular
      :default-height 140)
     (medium
      :default-height 160)
     (large
      :default-weight semilight
      :default-height 180
      :bold-weight extrabold)
     (presentation
      :default-weight semilight
      :default-height 180
      :bold-weight extrabold)
     (jumbo
      :default-weight semilight
      :default-height 200
      :bold-weight extrabold)
     (t
      :default-family "Iosevka Comfy"
      :default-weight regular
      :default-height 140
      :fixed-pitch-family nil	       ; falls back to :default-family
      :fixed-pitch-weight nil	       ; falls back to :default-weight
      :fixed-pitch-height 1.0
      :fixed-pitch-serif-family nil    ; falls back to :default-family
      :fixed-pitch-serif-weight nil    ; falls back to :default-weight
      :fixed-pitch-serif-height 1.0
      :variable-pitch-family "Iosevka Comfy Duo"
      :variable-pitch-weight nil
      :variable-pitch-height 1.0
      :bold-family nil		; use whatever the underlying face has
      :bold-weight bold
      :italic-family nil
      :italic-slant italic
      :line-spacing nil))))

Setup PATH variable

Always set PATH and MANPATH from shell, even when initialized from GUI helpers like dmenu or Spotlight

(use-package exec-path-from-shell
  :unless (string-equal system-type "windows-nt")
  :demand t
  :init
  (exec-path-from-shell-initialize)
  (exec-path-from-shell-copy-envs '("LANG" "GPG_AGENT_INFO" "SSH_AUTH_SOCK")))

Setup auto-fill-mode

I like to have auto-fill-mode enabled on all my text buffers. Easiest way of achieve that is to add turn-on-auto-fill to text-mode-hook

(add-hook 'text-mode-hook 'turn-on-auto-fill)

Setup ef-themes

The ef-themes package is created and maintained by Prot. Very pleasing to look at.

(use-package ef-themes
  :defer nil
  :ensure t
  :custom
  (ef-themes-to-toggle '(ef-melissa-light ef-melissa-dark))

  (ef-themes-headings
   '((0 . (variable-pitch light 1.9))
     (1 . (variable-pitch light 1.8))
     (2 . (variable-pitch regular 1.7))
     (3 . (variable-pitch regular 1.6))
     (4 . (variable-pitch regular 1.5))
     (5 . (variable-pitch 1.4))
     (6 . (variable-pitch 1.3))
     (7 . (variable-pitch 1.2))
     (t . (variable-pitch 1.1))))

  (ef-themes-mixed-fonts t)
  (ef-themes-variable-pitch-ui t)
  (ef-themes-region '(intense no-extend neutral))

  :config
  (ef-themes-select 'ef-melissa-light)

  :bind ("<f5>" . ef-themes-toggle))

Setup geiser

guile is a language that lately I’ve been trying to get acquainted to and, as such, I need a cool way of communicating with a REPL from inside emacs. gueiser seems to be a good choice for that

(use-package geiser
  :custom
  (geiser-active-implementations '(mit guile racket)))

(use-package geiser-guile
  :after geiser)

(use-package geiser-mit
  :after geiser)

(use-package geiser-racket
  :after geiser)

Setup paredit

This is probably the most awkward mode to get used to. Still, it’s so darn helpful that I just have to use it.

(use-package paredit
  :hook ((emacs-lisp-mode
          ielm-mode
          lisp-mode
          lisp-interaction-mode
          scheme-mode) . enable-paredit-mode)
  :init
  (add-hook 'eval-expression-minibuffer-setup-hook #'enable-paredit-mode))

Setup show-parens

This makes it a lot easier to see matching parens

(show-paren-mode 1)

Setup rainbow-delimiters

As a complement to paredit I want my parens to be easy to see, hence rainbow-delimiters

   (use-package rainbow-delimiters
     :hook
     ((emacs-lisp-mode
	ielm-mode
	lisp-mode
	lisp-interaction-mode
	scheme-mode) . rainbow-delimiters-mode))

Setup prettify-symbols-mode

I like to have nice looking lambda characters on all my lisp-y modes. Let’s push the lambda character to other mode hooks too.

We also have a rather cute symbol for function on js-mode.

(defun push-pretty-characters ()
  "Push pretty characters to mode-specific prettify-symbols-alist"
  (push '("lambda" . #x03bb) prettify-symbols-alist))

(add-hook 'emacs-lisp-mode-hook       #'push-pretty-characters)
(add-hook 'eval-expression-minibuffer-setup-hook #'push-pretty-characters)
(add-hook 'ielm-mode-hook             #'push-pretty-characters)
(add-hook 'lisp-mode-hook             #'push-pretty-characters)
(add-hook 'lisp-interaction-mode-hook #'push-pretty-characters)
(add-hook 'scheme-mode-hook           #'push-pretty-characters)

(add-hook 'js-mode-hook (lambda ()
                          (push '("function" . ) prettify-symbols-alist)))

Setup vertico, consult, orderless, corfu, and marginalia

Okay, I’m a bit tired of helm. Let’s switch over to vertico and figure out what I’ve been missing.

(use-package vertico
  :demand t
  :custom
  (vertico-cycle t)
  :init
  (vertico-mode t))

(use-package orderless
  :demand t
  :after vertico
  :custom
  (completion-styles '(orderless basic))
  (completion-category-overrides '((file (styles basic partial-completion)))))

(use-package consult
  :demand t
  :after vertico
  :config
  ;; Use `consult-completion-in-region' if Vertico is enabled.
  ;; Otherwise use the default `completion--in-region' function.
  (setq completion-in-region-function
        (lambda (&rest args)
          (apply (if vertico-mode
                     #'consult-completion-in-region
                   #'completion--in-region)
                 args)))
  :bind (("C-s" . consult-line)
         ("C-r" . consult-line)
         ("C-c g" . consult-git-grep)
         ("C-c o" . consult-imenu)
         ("C-x b" . consult-buffer)
         ("C-x C-d" . project-find-file)
         ("M-y" . consult-yank-pop)
         ("M-g M-g" . consult-goto-line)
         ("C-h a" . consult-apropos)
         :map minibuffer-local-map
         ("C-r" . consult-history)))

(use-package marginalia
  :demand t
  :after vertico
  :init
  (marginalia-mode t))

(use-package corfu
  :after vertico
  :custom
  (corfu-cycle t)
  (corfu-auto t)
  (corfu-separator ?\s)
  (corfu-quit-no-match 'separator)

  :init
  (global-corfu-mode))

(use-package emacs
  :init
  (setq completion-cycle-threshold 5)

  (setq read-extended-command-predicate
        #'command-completion-default-include-p)

  ;; Enable indentation+completion using the TAB key.
  ;; `completion-at-point' is often bound to M-TAB.
  (setq tab-always-indent 'complete))

Setup spacious-padding

(use-package spacious-padding
  :if (display-graphic-p)
  :custom
  (spacious-padding-widths
   '(:internal-border-width 15
     :header-line-width 4
     :mode-line-width 6
     :tab-width 4
     :right-divider-width 30
     :scroll-bar-width 8
     :fringe-width 8))
  (spacious-padding-subtle-mode-line
   '(:mode-line-active default
     :mode-line-inactive window-divider))
  :init
  (spacious-padding-mode 1))

Setup org-mode

Setup org and org-bullets

org is emacs’s organizer package. I use it a lot and really enjoy it. Let’s set it up.

First we will be using our local copy of org git tree:

(defun fb/org-habit-find-file ()
  "Open my personal habits file. It's always placed under
`org-directory' named `habit.org"
  (interactive)
  (let ((habit-file-name (concat (file-name-as-directory org-directory) "habit.org")))
    (find-file habit-file-name)))

(use-package org
  :hook (org-mode . (lambda () (org-indent-mode t)))

  :bind
  (("C-c l" . org-store-link)
   ("C-c a" . org-agenda)
   ("C-c c" . org-capture)
   ("C-c b" . org-switchb)
   ("C-c h" . fb/org-habit-find-file))

  :custom
  (org-directory "~/workspace/org")
  (org-id-track-globally t)
  (org-agenda-skip-deadline-if-done t)
  (org-agenda-skip-scheduled-if-done t)
  (org-return-follows-link t)
  (org-ellipsis "")
  (org-startup-folded 'content)
  (org-src-fontify-natively t)
  (org-src-tab-acts-natively t)
  (org-enforce-todo-dependencies t)
  (org-enforce-todo-checkbox-dependencies t)
  (org-agenda-dim-blocked-tasks t)
  (org-highlight-latex-and-related '(native latex script))
  (org-confirm-babel-evaluate
   (lambda (lang body)
     (not (memq (intern lang) '(c shell python dot ditaa)))))

  ;; Log timestamp upon completion
  (org-log-done 'time)

  ;; Priorities
  (org-highest-priority ?A)
  (org-lowest-priority ?E)
  (org-default-priotiy ?E)

  ;; Keywords
  (org-todo-keywords
   '((sequence "TODO(t)" "IN PROGRESS(p)" "|"
               "DONE(d)" "CANCELED(c)"
               "BLOCKED(b)" "AWAITING(a)")))

  :config
  (require 'org-tempo nil t)
  (require 'ox-odt nil t)
  (require 'ox-md nil t)
  (setq org-latex-pdf-process
        '("latexmk -xelatex -bibtex -shell-escape -f -pdf %f"))
  (setq org-latex-listings 'minted)
  (setq org-latex-minted-options
        '(("linenos=true")))
  (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
  (add-to-list 'org-structure-template-alist '("cc" . "src c"))
  (add-to-list 'org-structure-template-alist '("rs" . "src rust"))
  (add-to-list 'org-structure-template-alist '("sh" . "src shell"))
  (add-to-list 'org-structure-template-alist '("hs" . "src haskell"))
  (add-to-list 'org-structure-template-alist '("js" . "src js"))
  (add-to-list 'org-modules 'org-habit)

  (org-babel-do-load-languages 'org-babel-load-languages '((emacs-lisp . t)
                                                           (C . t)
                                                           (python . t)
                                                           (shell . t)
                                                           (sql . t)
                                                           (dot . t)))

  (add-to-list 'org-latex-classes
               '("scrreprt" "\\documentclass[11pt]{scrreprt}"
                 ("\\chapter{%s}" . "\\chapter*{%s}")
                 ("\\section{%s}" . "\\section*{%s}")
                 ("\\subsection{%s}" . "\\subsection*{%s}")
                 ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
                 ("\\paragraph{%s}" . "\\paragraph*{%s}")
                 ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))

  (add-to-list 'org-latex-classes
               '("scrbook" "\\documentclass[11pt]{scrbook}"
                 ("\\chapter{%s}" . "\\chapter*{%s}")
                 ("\\section{%s}" . "\\section*{%s}")
                 ("\\subsection{%s}" . "\\subsection*{%s}")
                 ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
                 ("\\paragraph{%s}" . "\\paragraph*{%s}")
                 ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))

  (add-to-list 'org-latex-classes
               '("scrartcl" "\\documentclass[11pt]{scrartcl}"
                 ("\\section{%s}" . "\\section*{%s}")
                 ("\\subsection{%s}" . "\\subsection*{%s}")
                 ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
                 ("\\paragraph{%s}" . "\\paragraph*{%s}")
                 ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))))

(use-package org-bullets
  :hook (org-mode . org-bullets-mode)
  :custom
  (org-hide-leading-stars t))

Setup ox-ioslide

ox-ioslide helps us exporting org documents to Google I/O HTML5 slides. This can come in very handy ;-)

(use-package ox-ioslide)

Setup ox-rst

ox-rst will be used to export org documents to ReST format which is used as Linux’ documentation source.

(use-package ox-rst)

Setup org-roam

(use-package org-roam
  :init
  (setq org-roam-v2-ack t)

  :custom
  (org-roam-directory "~/workspace/org/roam/")
  (org-roam-completion-everywhere t)
  (org-roam-completion-system 'default)
  (org-roam-dailies-directory "daily/")

  (org-roam-capture-templates
   '(("d" "default" plain "\n\n- tags :: \n\n%?"
      :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
                         "#+title: ${title}\n")
      :unnarrowed t)

     ("b" "Book " plain
      "\n- Author: %^{Author}\n- Year: %^{Year}\n- tags :: [[id:c18f7b2a-0b63-4d74-b420-c2fd997d4b93][Book]] [[id:00b5343e-e227-4cf1-b64e-c516e4151fe1][Reading]]\n\n%?"
      :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
      :unnarrowed t)

     ("p" "Person " plain
      "\n\n- tags :: [[id:55532c03-7cbd-4193-bed3-6752c37a22db][People]]\n- Email: %^{Email}\n\n%?"
      :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
      :unnarrowed t)

     ("m" "Meeting " plain
      "\n\n- Date :: %<%Y-%m-%d>\n- Attendees :: %?\n- tags :: [[id:e6d9bbff-585a-47fd-9559-8728458faf8a][Meeting]]\n* Agenda\n\n-"
      :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n")
      :unnarrowed t)))

  :bind (("C-c n l" . org-roam-buffer-toggle)
         ("C-c n e" . org-roam-extract-subtree)
         ("C-c n f" . org-roam-node-find)
         ("C-c n g" . org-roam-graph)
         ("C-c n i" . org-roam-node-insert)
         ("C-c n c" . org-roam-capture)
         ("C-c n r" . org-roam-ref-add)
         ("C-c n R" . org-roam-ref-remove)
         ("C-c n t" . org-roam-tag-add)
         ("C-c n T" . org-roam-tag-remove)
         ("C-c n a" . org-roam-alias-add)
         ("C-c n A" . org-roam-alias-remove)
         ;; Dailies
         ("C-c n d" . org-roam-dailies-goto-date)
         ("C-c n j" . org-roam-dailies-goto-today)
         ("C-c n y" . org-roam-dailies-goto-yesterday))
  :config
  (add-to-list 'display-buffer-alist
               '("\\*org-roam\\*"
                 (display-buffer-in-direction)
                 (direction . right)
                 (window-width . 0.5)
                 (window-height . fit-window-to-buffer)))
  (org-roam-db-autosync-enable))

(use-package org-roam-ui
  :after org-roam
  :config
  (setq org-roam-ui-sync-theme t
        org-roam-ui-follow t
        org-roam-ui-update-on-save t
        org-roam-ui-open-on-start t)

  ;; normally we'd recommend hooking orui after org-roam, but since
  ;; org-roam does not have a hookable mode anymore, you're advised to
  ;; pick something yourself if you don't care about startup time, use:
  ;;
  ;; :hook (after-init . org-roam-ui-mode)
)

Setup magit

This is simple to configure.

(use-package magit
  :config (setq magit-diff-use-overlays nil
                magit-commit-arguments '("--signoff"))
  :bind ("C-x g" . magit-status))

Setup eshell

Really not much here, I just need a key chord to start eshell at will

(use-package eshell
  :bind ("C-c t" . eshell))

(defun eshell-fn-on-files (f1 f2 files)
  (unless (null files)
    (let ((filenames (flatten-list files)))
      (funcall f1 (car filenames))
      (when (cdr filenames)
        (mapcar f2 (cdr filenames)))
      "")))

(defun eshell/less (&rest files)
  "Improved less functionality using `view-file'."
  (eshell-fn-on-files 'view-file
                      'view-file-other-window files))

(defun eshell/e (&rest files)
  "Call `find-file' on the arguments."
  (eshell-fn-on-files 'find-file
                      'find-file-other-window files))

(defalias 'eshell/emacs 'eshell/e)

Setup engine-mode

engine-mode helps me starting out searches from within emacs. It’s a bit useful and I kinda like it.

(use-package engine-mode
  :config
  (engine/set-keymap-prefix (kbd "C-c s"))

  (defengine duckduckgo
    "https://duckduckgo.com/?q=%s"
    :keybinding "d")

  (defengine google
    "https://www.google.com/search?ie=utf-8&oe=utf-8&q=%s"
    :keybinding "g")

  (defengine wikipedia
    "https://en.wikipedia.org/w/index.php?title=Special:Search&go=Go&search=%s"
    :keybinding "w")

  (defengine wolfram-alpha
    "https://www.wolfram-alpha.com/input/?i=%s")

  (defengine youtube
    "https://www.youtube.com/results?aq=f&oq=&search_query=%s"
    :keybinding "y")

  (defengine 17track
    "http://www.17track.net/en/track?nums=%s"
    :keybinding "t")

  (engine-mode t))

Setup notmuch

Using notmuch as my email client and indexer

(use-package notmuch
  ;; :ensure nil
  :config
  (require 'smtpmail)
  (add-hook 'message-setup-hook 'mml-secure-message-sign-pgpmime)
  (setq-default message-kill-buffer-on-exit t
                mail-specify-envelope-from t
                message-send-mail-function 'message-smtpmail-send-it
                mml-secure-smime-sign-with-sender t
                mml-secure-openpgp-sign-with-sender t
                smtpmail-smtp-server "mail.kernel.org"
                smtpmail-smtp-service 587
                smtpmail-smtp-user "balbi"
                notmuch-crypto-process-mime t
                notmuch-show-stash-mlarchive-link-alist '(("Lore" . "https://lore.kernel.org/r/")
                                                          ("Gmane" . "https://mid.gmane.org/")
                                                          ("MARC" . "https://marc.info/?i=")
                                                          ("Mail Archive, The" . "https://mid.mail-archive.com/"))

                notmuch-show-indent-content nil)) ; my saved searches are missing. Should they be in site-local.el ?

Setup ledger-mode

I use ledger-mode for managing my finances.

(use-package ledger-mode
  :config
  (add-to-list 'auto-mode-alist '("\\.ledger\\'" . ledger-mode))
  (setq ledger-clear-whole-transactions t
        ledger-reconcile-default-commodity ""
        ledger-reconcile-force-window-bottom t
        ledger-master-file "~/workspace/accounting/general.ledger"
        ledger-reports '(("bal" "%(binary) -f %(ledger-file) bal -B")
                         ("reg" "%(binary) -f %(ledger-file) reg")
                         ("payee" "%(binary) -f %(ledger-file) reg @%(payee)")
                         ("account" "%(binary) -f %(ledger-file) reg %(account)"))))

Setup restclient

Well, maybe I could play a bit with restclient every now and again :-)

(use-package restclient)

Setup octave-mode

Use *.m as default extension for octave files

(add-to-list 'auto-mode-alist '("\\.m$" . octave-mode))

Setup markdown-mode

(use-package markdown-mode
  :mode (("README\\.md\\'" . gfm-mode)
         ("\\.md\\'" . markdown-mode)
         ("\\.markdown\\'" . markdown-mode))
  :init (setq markdown-command "pandoc"))

Setup yasnippet

(use-package yasnippet
  :demand t
  :config
  (setq yas-verbosity 1
        yas-wrap-around-region t)

  (with-eval-after-load 'yasnippet
    (setq yas-snippet-dirs (list "~/.emacs.d/personal-snippets")))

  (yas-reload-all)
  (yas-global-mode))

Setup sly

I’ve started reading Land Of Lisp and will, therefore, play around with Common Lisp. For that, I’ll be using sly with sbcl

(use-package sly
  :custom
  (inferior-lisp-program "sbcl"))

Setup haskell-mode

Learning me some haskell.

(use-package haskell-mode
  :init
  (add-hook 'haskell-mode-hook #'interactive-haskell-mode)
  (add-hook 'haskell-mode-hook #'haskell-indentation-mode))

Setup multiple-cursors

(use-package multiple-cursors
  :demand t
  :bind (("C->" . mc/mark-next-like-this)
         ("C-<" . mc/mark-previous-like-this)
         ("C-c C-<" . mc/mark-all-like-this)
         ("C-S-c C-S-c" . mc/edit-lines)))

Setup dts-mode

(use-package dts-mode
  :pin elpa)

Setup cmake-mode

I have a few projects using cmake as the build system, cmake-mode at least gives me a sensible mode for editting those files.

(use-package cmake-mode)

Setup erc

(use-package erc-hl-nicks
  :after erc)

(use-package erc-image
  :after erc)

(use-package erc-hl-nicks
  :after erc)

(use-package erc
  :commands erc
  :custom
  (erc-nick '("balbi" "balbi_" "felipebalbi"))
  (erc-user-full-name "Felipe Balbi")
  (erc-interpret-mirc-color t)
  (erc-lurker-hide-list '("JOIN" "PART" "QUIT"))
  (erc-track-exclude-types '("JOIN" "NICK" "QUIT" "MODE"))
  (erc-track-enable-keybindings nil)
  (erc-track-visibility nil) ; Only use the selected frame for visibility
  (erc-fill-column 80)
  (erc-fill-function 'erc-fill-static)
  (erc-fill-static-center 20)
  (erc-default-server "irc.libera.chat")
  (erc-autojoin-channels-alist '(("libera.chat" "#emacs" "#guix" "#systemcrafters")))
  (erc-quit-reason (lambda (s) (or s "Later...")))
  (erc-modules
   '(autoaway autojoin button completion image fill irccontrols keep-place
              list match menu move-to-prompt netsplit networks noncommands
              readonly ring stamp track hl-nicks)))

Setup scad-mode

Should we play with some openscad?

(use-package scad-mode)

Setup proof-general

Proof general is used to communicate with proof assistants. As I want to work through the Software Foundations Books, I’ll rely on proof-general to communicate with Coq.

(use-package proof-general
  :ensure t)

Setup rust-mode

Let’s play with rust

(use-package rust-mode
  :config
  (setq indent-tabs-mode nil)
  :custom
  (rust-format-on-save t))

(use-package cargo
  :after rust-mode
  :hook (rust-mode . cargo-minor-mode)
  :bind
  ("C-c C-c n" . cargo-process-new))

(use-package rustic
  :after rust-mode
  :config
  (setq rustic-format-on-save t)
  (setq rustic-lsp-client 'eglot)
  (setq rustic-lsp-server 'rust-analyzer)
  (setq rustic-rustfmt-config-alist '((edition . "2021"))))

Setup eglot

(use-package eglot
  :hook ((rust-mode python-mode) . eglot-ensure)
  :config
  (add-to-list 'eglot-server-programs '(rust-mode . ("rust-analyzer"))))

Setup elec-pair

(use-package elec-pair
  :hook ((c-mode cc-mode rust-mode) . electric-pair-local-mode))

Setup nov

(use-package nov
  :ensure t)

All The Icons

(use-package all-the-icons)

(use-package all-the-icons-dired
  :hook (dired-mode . all-the-icons-dired-mode))

Outro

Some extra keybindings for myself

These are super helpful for day to day use

(define-key global-map (kbd "C-1") 'text-scale-increase)
(define-key global-map (kbd "C-0") 'text-scale-decrease)

Enable some disabled commands

Few commands I want to use but are disabled by default

(put 'narrow-to-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)
(put 'dired-find-alternate-file 'disabled nil)

GnuPG 2

We’re gonna tell emacs to use gpg2

(setq epg-gpg-program "/usr/bin/gpg2")

Reduce Garbage Collection Threshold

(setq gc-cons-threshold (* 2 1024 1024))