Skip to content

Latest commit

 

History

History
1287 lines (1050 loc) · 33.1 KB

config.org

File metadata and controls

1287 lines (1050 loc) · 33.1 KB

He-Macs

I have the power! - He-Man

Table of Contents

What is this?

Let’s forget about this dumb play on words between my name and a cartoon from the 80’s and actually explain what this file is.

Abstract

This is my attempt at writing a literate Emacs configuration using Org, a “simple outliner for note-taking and list management” that actually does way more. Although this configuration is for myself and is opinionated, anyone is free to watch, copy or use its content.

Why though?

Fame? No. Fun? Maybe. Having your whole configuration in a single file might be a little messy but a literate file such as this one looks like a neat idea to organize and document my dear Emacs configuration. Of course the file will eventually be gigantic but Org Mode makes it easy to manage. Documentation is also a huge plus since I usually get lost in the maze of Emacs Lisp that is my current config.

Installation

All you need to do is to clone this repository, I added the tangled file to git so the init.el is already here. Since I use submodules, you need to clone recursively this repository.

# Maybe backup you files first
mv ~/.emacs.d ~/.emacs.bak
git clone --recursive https://github.com/hmatheisen/.emacs.d.git ~/.emacs.d

Creating the files

Files to ignore

This is my .gitignore file.

.backups/
.cache/
.lsp-session-v1
auto-save-list/
bookmarks
custom.el
elpa/
eshell/
games/
ido.last
nov-places
network-security.data
newsticker
projectile-bookmarks.eld
projectile.cache
recentf
todos.org
tramp
transient/
xkcd/

init.el

;;; init.el --- Emacs Init File

;;; Commentary:
;;; My Emacs Init File
;;; This file is generted by `config.org', since there are no comments in here,
;;; you should go have a look there for more information.

;;; Code:

Initialization

These are the first few lines of code that start it all. They go into init.el and will be added to git since they are needed to install Org on a new system and therefore read this file ton install the rest of the configuration. I will keep maintaining init.el in this file since org-babel-tangle just rewrites the file if new modifications are made.

Custom constants/variables

(defconst *is-a-mac* (eq system-type 'darwin)
  "Check whether system is mac.")
(defconst *mono-font* "Iosevka Term"
  "Mono font to be used")
(defconst *font-size* 9
  "Font size in points")

Add package archives

Setup MELPA repositories.

(require 'package)
(add-to-list 'package-archives '("gnu"   . "https://elpa.gnu.org/packages/"))
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(add-to-list 'package-archives '("org"   . "https://orgmode.org/elpa/"))
(setq package-enable-at-startup nil)
(package-initialize)

Install use-package

use-package is quite handy and will allow us to require and install packages in a tidy way, we install it here and make sure it installs the packages we want by default.

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))
(eval-and-compile
  (require 'use-package-ensure)
  (setq use-package-always-ensure t))

Require personal packages

Those packages are installed with git submodules. They are isolated packages written by me so they don’t need any description here. We just add them to load path so that use-package can do the job later.

(add-to-list 'load-path "~/.emacs.d/site-lisp/theme-switcher")
(add-to-list 'load-path "~/.emacs.d/site-lisp/new-term")

Global settings

These are settings to change the look/behavior of Emacs using only native options. I regroup them by their package using use-package. There is nothing really fancy happening here, just cleaning up the UI and setting some variables. Since I always ensure packages by default, I make sure to add :ensure nil on native packages so use-package does not try to look for them in MELPA.

Settings without packages

These are settings defined in the C source code of emacs so they are not related to any Lisp packages, let’s put them in a package called emacs.

Macos

(use-package emacs
  :ensure nil
  :config
  ;; Avoid a few issues on MacOS
  (when *is-a-mac*
    (setq mac-option-modifier 'meta
          mac-command-modifier 'super
          mac-right-option-modifier 'nil
          select-enable-clipboard t))
  ;; title bar settings
  (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))
  (add-to-list 'default-frame-alist '(ns-appearance . dark))
  (setq ns-use-proxy-icon  nil)
  (setq frame-title-format nil))

UI/UX

(use-package emacs
  :ensure nil
  :config
  ;; Remove Toolbar
  (tool-bar-mode -1)
  ;; Disable menu bar
  (menu-bar-mode -1)
  ;; Enable downcase/upcase region
  (put 'downcase-region 'disabled nil)
  (put 'upcase-region 'disabled nil)
  ;; Trash can support
  (when *is-a-mac*
    (setq trash-directory "~/.Trash"))
  (setq delete-by-moving-to-trash t)
  ;; Indent using spaces
  (setq-default indent-tabs-mode nil)
  ;; Set tabs to 2
  (setq-default tab-width 2)
  ;; Make that damn bell shut up
  (setq ring-bell-function 'ignore)
  ;; Default truncate lines
  (setq-default truncate-lines t)
  ;; Unbind suspend keys
  (global-unset-key (kbd "C-z"))
  (global-unset-key (kbd "C-x C-z")))

Garbage collection

(use-package emacs
  :ensure nil
  :preface
  (defun garbage-collect-defer ()
    "Defer garbage collection."
    (setq gc-cons-threshold most-positive-fixnum
          gc-cons-percentage 0.6))
  (defun garbage-collect-restore ()
    "Return garbage collection to slightly higher parameter."
    (setq gc-cons-threshold 100000000
          gc-cons-percentage 0.1))
  :config
  ;; Set garbage collection
  (garbage-collect-defer)
  (add-hook 'emacs-startup-hook #'garbage-collect-restore)
  (add-hook 'minibuffer-setup-hook #'garbage-collect-defer)
  (add-hook 'minibuffer-exit-hook #'garbage-collect-restore))

Path

;; Resolve path issues
(use-package emacs
  :preface
  (defun add-to-path (path)
    "Add a path to `exec-path' and Emacs \"PATH\" variable."
    (add-to-list 'exec-path path)
    (setenv "PATH" (concat (getenv "PATH") ":" path)))
  :ensure nil
  :config
  ;; Add useful path to exec-path and PATH
  (add-to-path "/usr/local/bin")
  (add-to-path "/Library/TeX/texbin")
  (add-to-path "~/go/bin")
  (add-to-path "~/.cargo/bin"))

UTF-8

(use-package emacs
  :ensure nil
  :config
  ;; Set utf8 everywhere
  (prefer-coding-system 'utf-8)
  (setq locale-coding-system 'utf-8)
  (set-language-environment "UTF-8")
  (set-default-coding-systems 'utf-8)
  (set-terminal-coding-system 'utf-8)
  (set-keyboard-coding-system 'utf-8)
  (set-selection-coding-system 'utf-8))

Half scroll

(use-package emacs
  :ensure nil
  :preface
  (defun zz-scroll-half-page (direction)
    "Scrolls half page up if `direction' is non-nil, otherwise will scroll half page down."
    (let ((opos (cdr (nth 6 (posn-at-point)))))
      ;; opos = original position line relative to window
      (move-to-window-line nil)  ;; Move cursor to middle line
      (if direction
          (recenter-top-bottom -1)  ;; Current line becomes last
        (recenter-top-bottom 0))  ;; Current line becomes first
      (move-to-window-line opos)))  ;; Restore cursor/point position

  (defun zz-scroll-half-page-down ()
    "Scrolls exactly half page down keeping cursor/point position."
    (interactive)
    (zz-scroll-half-page nil))

  (defun zz-scroll-half-page-up ()
    "Scrolls exactly half page up keeping cursor/point position."
    (interactive)
    (zz-scroll-half-page t))
  :config
  (global-set-key (kbd "C-v") 'zz-scroll-half-page-down)
  (global-set-key (kbd "M-v") 'zz-scroll-half-page-up))

Custom

The custom file is not really useful here since every parameter is set using elisp.

(use-package custom
  :ensure nil
  :config
  (setq custom-safe-themes t)
  (setq custom-file (expand-file-name "custom.el" user-emacs-directory)))

Mail

Setup auth information. .authinfo.gpg file is the encrypted authentication source file used by different backends. We tell Emacs to use this file for authentication. Then setup user full name and mail address. Two GPG related environment variables are created to make decryption work inside Emacs.

(use-package auth-source
  :ensure nil
  :config
  (setq auth-sources '("~/.authinfo.gpg" "~/.authinfo"))
  (setq user-full-name "Henry MATHEISEN")
  (setq user-mail-address "henry.mthsn@gmail.com")
  ;; Disable external pin entry
  (setenv "GPG_AGENT_INFO" nil)
  ;; Solve ioctl common error with GPG
  (setenv "GPG_TTY" "$(tty)"))

Configure default SMTP server. This allows Emacs to look for the right line in the .authinfo.gpg when it needs credentials. We use SSL to encrypt sent mails. And set Emacs to use SMTP as the main mail sending method.

(use-package smtpmail
  :config
  (setq smtpmail-smtp-server "smtp.gmail.com"
        smtpmail-smtp-service 465
        smtpmail-stream-type 'ssl
        ;; Set smtp method for sending mail
        send-mail-function 'smtpmail-send-it
        message-send-mail-function 'message-smtpmail-send-it))

Message mode is the mode I use to send mails. Here, we tell it to sign mail with my name and mail address.

(use-package message
  :ensure nil
  :config
  (setq mail-signature "Henry MATHEISEN\nhenry.mthsn@gmail.com\n"
        message-signature "Henry MATHEISEN\nhenry.mthsn@gmail.com\n"))

Using Emacs GUI, I want an internal pinentry program. EPA allows to use Emacs Minibuffer for GPG pinentry.

(use-package "epa-file"
  :ensure nil
  :config
  (setq epa-pinentry-mode 'loopback))

Gnus

Gnus early configuration. Only reads mail from my Gmail account for now.

(use-package gnus
  :defer t
  :ensure nil
  :config
  (setq gnus-select-method '(nnnil))
  (setq gnus-secondary-select-methods
        '((nnimap "GMAIL"
                 (nnimap-address "imap.gmail.com")
                 (nnimap-server-port "imaps")
                 (nnimap-stream ssl))))
  ;; Make Gnus NOT ignore [Gmail] mailboxes
  (setq gnus-ignored-newsgroups "^to\\.\\|^[0-9. ]+\\( \\|$\\)\\|^[\"]\"[#'()]"))

Terminal binary

On MacOS, I use a new version of bash installed with brew since I can’t update the default one. Therefore the path is changed to /usr/local/bin/bash.

(use-package term
  :ensure nil
  :config
  (if *is-a-mac*
      (setq explicit-shell-file-name "/usr/local/bin/bash")
    (setq explicit-shell-file-name "/bin/bash")))

Window

Change keybindings to resize window so I can just keep pressing them. Also I change the default keybindings to go to another window since C-x o is a little too long in my opinion. It is now remapped to ace-window which is handy when the number of windows starts to grow.

(use-package "window"
  :ensure nil
  :preface
  (defun hma/split-window-right ()
    "Splits window on the right then focus on that window"
    (interactive)
    (split-window-right)
    (other-window 1))
  (defun hma/split-window-below ()
    "Splits windmow below then focus on that window"
    (interactive)
    (split-window-below)
    (other-window 1))
  :config
  ;; Resizing
  (global-set-key (kbd "M--") 'shrink-window)
  (global-set-key (kbd "M-+") 'enlarge-window)
  (global-set-key (kbd "C--") 'shrink-window-horizontally)
  (global-set-key (kbd "C-+") 'enlarge-window-horizontally)
  ;; Other window (windmove is also setup but this can be easier)
  (global-set-key (kbd "M-o") 'other-window)
  (global-set-key (kbd "M-O") '(lambda ()
                                 (interactive)
                                 (other-window -1)))
  ;; scroll window up/down by one line
  (global-set-key (kbd "M-n") '(lambda ()
                                 (interactive)
                                 (scroll-up-command 1)))
  (global-set-key (kbd "M-p") '(lambda ()
                                 (interactive)
                                 (scroll-down-command 1)))
  ;; Use by own split functions
  (global-set-key (kbd "C-x 2") 'hma/split-window-below)
  (global-set-key (kbd "C-x 3") 'hma/split-window-right)
  (global-set-key (kbd "C-<tab>") 'next-buffer)
  (global-set-key (kbd "C-S-<tab>") 'previous-buffer))

(use-package ace-window
  :config (global-set-key (kbd "C-x o") 'ace-window))

WindMove

Use windmove to move around multiple windows easily

(use-package windmove
  :ensure nil
  :config
  (windmove-default-keybindings))

Y or N > Yes or No

Answer by y or n instead of yes of no.

(use-package "subr"
  :ensure nil
  :config (fset 'yes-or-no-p 'y-or-n-p))

Time mode

Display time on mode line.

(use-package time
  :ensure nil
  :config (display-time-mode t))

Simple

Display line numbers in mode line and undo keybinding.

(use-package simple
  :ensure nil
  :config
  (column-number-mode t)
  (global-set-key (kbd "s-<backspace>")
                  (lambda ()
                    (interactive)
                    (kill-line 0))))

Display battery level

Display battery level inm mode line.

(use-package battery
  :ensure nil
  :config (display-battery-mode t))

Line numbers

Display line numbers every prog-mode.

(use-package display-line-numbers
  :ensure nil
  :hook (prog-mode . display-line-numbers-mode)
        (yaml-mode . display-line-numbers-mode))

Files

Make sure that all backup files only exist in one place and always ask before quitting Emacs.

(use-package files
  :ensure nil
  :config
  (setq backup-directory-alist '(("." . "~/.emacs.d/.backups")))
  (setq confirm-kill-emacs #'yes-or-no-p))

Frame settings

Enable full frame on Emacs startup.

(use-package frame
  :ensure nil
  :config
  (add-hook 'after-init-hook 'toggle-frame-fullscreen))

Faces

Set the different fonts

(use-package faces
  :ensure nil
  :config
  (set-face-attribute 'default
                      nil
                      :family *mono-font*
                      :height (* *font-size* 10))

  (set-face-attribute 'fixed-pitch
                      nil
                      :family *mono-font*
                      :height (* *font-size* 10))

  (set-face-attribute 'variable-pitch
                      nil
                      :family "Raleway"
                      :height (* *font-size* 12)))

Winner mode

Allows to revert changes on the window configuration.

(use-package winner
  :ensure nil
  :config (winner-mode t))

Modern region behavior

Replace the active region when typing/yanking text, which is a little handier than the default behaviour.

(use-package delsel
  :ensure nil
  :config (delete-selection-mode +1))

No scroll bar

I mean who likes this, really?

(use-package scroll-bar
  :ensure nil
  :config (scroll-bar-mode -1))

Matching Parentheses

Show matching paren, quite useful for every languages especially Lisp!

(use-package paren
  :ensure nil
  :init (setq show-paren-delay 0)
  :config (show-paren-mode t))

Ediff

Enter ediff with side-by-side buffers to better compare the differences.

(use-package ediff
  :ensure nil
  :config (setq ediff-split-window-function 'split-window-horizontally))

Auto-pair

Auto close quote, parentheses, brackets, etc.

(use-package elec-pair
  :ensure nil
  :hook (prog-mode . electric-pair-mode))

Use ibuffer

Use ibuffer instead of default list buffer.

(use-package "ibuffer"
  :ensure nil
  :config
  ;; Replace command to ibuffer
  (global-set-key (kbd "C-x C-b") 'ibuffer)
  ;; Filter groups
  (setq ibuffer-saved-filter-groups
        '(("default"
           ("buffers"      (or (name . "\*dashboard\*")
                               (name . "\*scratch\*")))
           ("clojure"      (or (mode . clojure-mode)
                               (name . "\*cider")
                               (name . "\*nrepl")))
           ("magit"        (name . "magit*"))
           ("he-macs"      (filename . ".emacs.d"))
           ("org"          (mode . org-mode))
           ("dired"        (mode . dired-mode))
           ("code"         (filename . "Projets")))))
  ;; Add hook
  (add-hook 'ibuffer-mode-hook
            '(lambda ()
               (ibuffer-switch-to-saved-filter-groups "default")))
  ;; Do not show groups that are empty
  (setq ibuffer-show-empty-filter-groups nil)
  ;; Do not prompt when deleting a new buffer
  (setq ibuffer-expert t))

Compile

Set keybinding for the recompile command.

(use-package compile
  :ensure nil
  :config
  (global-set-key (kbd "C-c C-k") 'recompile))

Info

Change one info-mode keybinding to my scroll command.

(use-package info
  :ensure nil
  :config
  (define-key Info-mode-map (kbd "M-n") '(lambda ()
                                           (interactive)
                                           (scroll-up-command 1))))

JS

Set indent level for javascript/json files.

(use-package js
  :ensure nil
  :config
  (setq js-indent-level 2))

Shell script

(use-package sh-script
  :ensure nil
  :config (setq sh-basic-offset 2))

Align

(use-package align
  :ensure nil
  :config
  (defun hma/align-equals (beg end)
    "Align `=' signs in a given region."
    (interactive "r")
    (align-regexp beg
                  end
                  "\\(\\s-*\\)=")))

MWheel

Settings concerning mouse scroll in GUI

(use-package mwheel
  :ensure nil
  :config (setq mouse-wheel-progressive-speed nil
                mouse-wheel-scroll-amount '(1 ((shift) . 1))))

Third-party Packages

Here are all the packages I require from MELPA.

Themes

Currently using the perfect Modus themes.

(use-package modus-vivendi-theme
  :defer t
  :init
  (setq modus-vivendi-theme-distinct-org-blocks t
        modus-vivendi-theme-rainbow-headings t
        modus-vivendi-theme-slanted-constructs t
        modus-vivendi-theme-bold-constructs t
        modus-vivendi-theme-scale-headings t
        modus-vivendi-theme-scale-1 1.05
        modus-vivendi-theme-scale-2 1.1
        modus-vivendi-theme-scale-3 1.15
        modus-vivendi-theme-scale-4 1.2))
(use-package modus-operandi-theme
  :defer t
  :init
  (setq modus-operandi-theme-distinct-org-blocks t
        modus-operandi-theme-rainbow-headings t
        modus-operandi-theme-slanted-constructs t
        modus-operandi-theme-bold-constructs t
        modus-operandi-theme-scale-headings t
        modus-operandi-theme-scale-1 1.05
        modus-operandi-theme-scale-2 1.1
        modus-operandi-theme-scale-3 1.15
        modus-operandi-theme-scale-4 1.2))

Diminish

(use-package diminish
  :defer t
  :after use-package)

Ivy

I use Ivy as as a completion frontend, it integrates really well with other super cool tools such as Swiper and Counsel. There are other choices for this such as Helm that I don’t really like or the default Ido mode that I should try one day.

(use-package counsel
  :defer t
  :diminish ivy-mode counsel-mode
  :bind (("C-s" . swiper-isearch))
  :hook ((after-init . ivy-mode)
         (ivy-mode . counsel-mode))
  :init
  (setq ivy-use-virtual-buffers t)
  (setq ivy-count-format "(%d/%d) "))

Code Completion

I use lsp-mode as my completion tool. Language Server Protocols allows to use the most modern code completions since they use servers as completion engines and lsp-mode is a great Emacs client for it. I also use company-mode for the frontend completion.

(use-package lsp-mode
  :defer t
  :init (setq lsp-keymap-prefix "C-c l")
  :hook ((python-mode . lsp)
         (go-mode . lsp)
         (ruby-mode . lsp)
         (typescript-mode . lsp)
         (rust-mdoe . lsp)
         (web-mode . lsp))
  :commands lsp
  :config
  ;; Do not use lsp for linting
  (setq lsp-diagnostic-package :none))

(use-package company-mode
  :defer t
  :diminish company-mode
  :init
  (setq company-selection-wrap-around t)
  (setq company-minimum-prefix-length 1)
  (setq company-idle-delay 0)
  (with-eval-after-load 'company
    (define-key company-active-map (kbd "M-n") nil)
    (define-key company-active-map (kbd "M-p") nil)
    (define-key company-active-map (kbd "C-n") 'company-select-next)
    (define-key company-active-map (kbd "C-p") 'company-select-previous))
  :ensure company
  :hook ((after-init . global-company-mode)
          (company-mode . (lambda ()
                            (diminish 'company-mode)))))

(use-package company-lsp
  :defer t
  :after (company lsp)
  :init
  (push 'company-lsp company-backends)
  :commands company-lsp)

Org Mode

I use org mode fo lots of things epacially to write this file. It’s just really great!

(use-package org
  :defer t
  :diminish visual-line-mode auto-fill-function
  :preface
  (defun hma/org-mode-hook ()
    (org-indent-mode 1)
    (visual-line-mode 1)
    (flyspell-mode 1)
    (auto-fill-mode 1)
    (variable-pitch-mode))
  :hook ((org-mode . hma/org-mode-hook)
         (org-indent-mode . (lambda ()
                              (diminish 'org-indent-mode)))
         (flyspell-mode . (lambda ()
                            (diminish 'flyspell-mode))))
  :config
  ;; Do not set headings face attributes if onve of the modus themes
  ;; is enabled since they already set this up.
  (set-face-attribute 'org-document-title nil :height 200)
  (unless (or (member 'modus-operandi custom-enabled-themes)
              (member 'modus-vivendi custom-enabled-themes))
    (set-face-attribute 'org-level-1        nil :height 160)
    (set-face-attribute 'org-level-2        nil :height 150))
  ;; Unbind C-<tab> to use 'next-buffer
  (define-key org-mode-map (kbd "C-<tab>") nil))

(use-package org-bullets
  :defer t
  :hook (org-mode . org-bullets-mode))

(use-package toc-org
  :defer t
  :hook ((org-mode      . toc-org-mode)
         (markdown-mode . toc-org-mode)))

Markdown mode

(use-package markdown-mode
  :defer t
  :config
  (setq markdown-fontify-code-blocks-natively t))

Magit

Magit is an awesome git wrapper, everyone loves it, I love it and I use it everyday.

(use-package magit
  :defer t
  :bind ("C-x g" . 'magit-status))

Flycheck

Flycheck linter.

(use-package flycheck
  :diminish
  :config (global-flycheck-mode t))

Projectile

Testing Projectile for project management.

(use-package projectile
  :defer t
  :diminish
  :config
  (projectile-mode t)
  (setq projectile-completion-system 'ivy)
  (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map))

Neotree

Tree file structure for Emacs

(use-package neotree
  :defer t
  :config
  (setq neo-window-fixed-size nil)
  (setq neo-theme (if (display-graphic-p) 'icons 'arrow))
  (setq neo-hidden-regexp-list '("\\.git$"))
  :bind (([f8] . neotree-toggle)))

Which key

This is great to get a list of available commands while typing a key chord.

(use-package which-key
  :diminish which-key-mode
  :config
  (which-key-mode +1)
  (setq which-key-idle-delay 0.2
        which-key-idle-secondary-delay 0.2))

Undo tree

Handy features for undo/redo

(use-package undo-tree
  :diminish undo-tree-mode
  :config
  (global-set-key "\C-z" 'undo)
  (global-undo-tree-mode))

All the icons

Icons support in Emacs

(use-package all-the-icons
  :defer t)

Dashboard

I just think it’s neat!

(use-package dashboard
  :diminish page-break-lines-mode
  :config
  (dashboard-setup-startup-hook)
  (setq dashboard-startup-banner 'official
        dashboard-items '((bookmarks . 10)
                          (recents . 5))
        dashboard-center-content t
        dashboard-set-heading-icons t
        dashboard-set-file-icons    t
        dashboard-banner-logo-title "Welcome to He-Macs!"))

Snippets

(use-package yasnippet
  :diminish yas-minor-mode
  :config (yas-global-mode t))

Clojure

Clojure mode

Install clojure-mode for editing.

(use-package clojure-mode
  :defer t)

CIDER

Install CIDER for REPL support and other intractive features.

(use-package cider
  :defer t)

Typescript

I use typescript mode instead of tide since I am already using lsp as a completion engine.

(use-package typescript-mode
  :defer t
  :config
  (setq typescript-indent-level 2))

Docker

To provide support fo docker I use docker-mode which is a wrapper for the Docker CLI and dockerfile-mode which allows syntax highlighting for Dockerfiles.

(use-package docker
  :defer t
  :bind ("C-c d" . docker))

(use-package dockerfile-mode)

YAML

(use-package yaml-mode
  :defer t)

Go

(use-package go-mode
  :defer t
  :config
  (defun lsp-go-install-save-hooks ()
    (add-hook 'before-save-hook #'lsp-format-buffer t t)
    (add-hook 'before-save-hook #'lsp-organize-imports t t))
  (add-hook 'go-mode-hook #'lsp-go-install-save-hooks))

LaTeX

(use-package tex
  :defer t
  :diminish auto-fill-function
  :ensure auctex
  :config
  ;; Disable auto locale
  (setq TeX-auto-local nil)
  ;; Set TEXINPUTS to recognize classes in custom directory on MacOS
  (when *is-a-mac*
    (setenv "TEXINPUTS" (concat (getenv "TEXINPUTS")
                                ":$HOME/Documents/Notes/classes")))
  :hook (LaTeX-mode . (lambda () (auto-fill-mode 1)
                                 (set-fill-column 80))))

RVM

(use-package rvm
  :config
  ;; Unset BUNDLE_PATH set by rvm because somehow it causes bundler to
  ;; install gems in another path than the default one
  (rvm-use-default)
  (setenv "BUNDLE_PATH"))

Ruby

;; Auto close for ruby
(use-package ruby-electric
  :diminish ruby-electric-mode
  :defer t
  :hook (ruby-mode . ruby-electric-mode))

Olivetty

Useful when writing prose.

(use-package olivetti
  :defer t
  :config (setq olivetti-body-width 110))

Terraform

(use-package terraform-mode
  :defer t
  :bind (("C-c SPC" . hma/align-equals)))

Beacon

Never lose the cursor again.

(use-package beacon
  :diminish beacon-mode
  :config (beacon-mode t))

IMenu-list

Creates a side buffer with the a list of imenu.

(use-package imenu-list
  :config (global-set-key (kbd "C-:") #'imenu-list-smart-toggle))

Evil

It is treason then…

(use-package evil
  :init
  ;; Default state is emacs so Evil is only active when toggling it
  ;; with `C-!'
  (setq evil-toggle-key "C-x C-z")
  :config
  ;; Switch on Evil mode
  (evil-mode t)
  (setq evil-default-state 'emacs))

Personal Packages

This part is about configuring packages that are not part of GNU Emacs but written by me. I chose not to upload them on MELPA since similar version of thos packages already exists, I just didn’t like them :)

This package allows to toggle a small terminal window on the bottom of the screen. It has a few other features like making it bigger or smaller and quitting by closing the shell process and killing the window. It is somewhat similar to what you would find in more modern editors such as VS Code.

(use-package new-term
  :preface
  (defun hma/new-term-hook ()
    (define-key term-raw-map (kbd "C-c <up>") 'bigger-term-window)
    (define-key term-raw-map (kbd "C-c <down>") 'smaller-term-window)
    (define-key term-raw-map (kbd "C-c q") 'quit-term))
  :ensure nil
  :init
  (setq new-shell "/usr/local/bin/bash")
  (global-set-key (kbd "C-x t") 'toggle-term-window)
  (add-hook 'term-mode-hook 'hma/new-term-hook))

This allows me to configure a theme for the day and a theme for the night that automatically switches at given time.

(use-package theme-switcher
  :ensure nil
  :init
  (setq day-hour 09)
  (setq night-hour 15)
  (setq day-theme 'modus-operandi)
  (setq night-theme 'modus-vivendi))

Closing files

init.el

;;; init.el ends here