This is my configuration for Emacs, both on my Ubuntu PC, Arch-running-ex-chromebook and work Windows laptop. There are some differences between the configs for the different machines, so I have several versions being tangled from this config.
I would say this is fairly close to a vanilla Emacs. Once I get something working fairly well, I’m usually happy with it, and don’t feel the need to tinker anymore. Most of packages I only use with the most basic setup, because that’s fine for me. Some inspiration comes from David Wilson’s wonderful Emacs from scratch https://github.com/daviwil/emacs-from-scratch, developed live on his YouTube.
I decided to make a literate config file mostly because of the different versions I need for my different machines, and this makes it easier to keep track of them.
Melpa and use-package for installing and handling packages
;; Enables basic packaging support
(require 'package)
;; MELPA
;; Adds the Melpa archive to the list of available repositories
(add-to-list 'package-archives
'("melpa" . "http://melpa.org/packages/")
'("gnu" . "https://elpa.gnu.org/packages/")
)
;; Initializes the package infrastructure
(package-initialize)
;; USE-PACKAGE
;; If we don't have the use-package package, we need to refresh contents and install it. The rest will be installed with it
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
For GIT straight from Emacs, because Magit is the best.
;; MAGIT
(use-package magit
:ensure t)
Mostly for shell, elisp and python.
;; ORG-BABEL
(org-babel-do-load-languages
'org-babel-load-languages
'(
(python . t)
(shell . t)
(emacs-lisp . t)))
;; to syntax highlight code in babel and to remove the "Do you want to execute?" question
(setq org-confirm-babel-evaluate nil
org-src-fontify-natively t
org-src-tab-acts-natively t
org-src-preserve-indentation t
)
(setq python-indent-guess-indent-offset nil)
(setq python-indent-offset 4)
Vertico is a completion framework. And also allows to write space in minibuffer, which doesn’t work in out-of-the-box Emacs.
;; VERTICO
(use-package vertico
:ensure t
:init
(vertico-mode)
:config
(setq enable-recursive-minibuffers t))
Allows for completion in any order.
;; ORDERLESS
(use-package orderless
:ensure t
:custom
(completion-styles '(orderless basic))
(completion-category-overrides '((file (styles basic partial-completion)))))
Adds useful information to the minibuffer for each of the options.
;; MARGINALIA
(use-package marginalia
:ensure t
:config
(marginalia-mode))
Embark allows for a context menu, kind of like a right-click.
;; EMBARK
(use-package embark
:ensure t
:bind
(("C-." . embark-act)) ;; pick some comfortable binding
)
Ox-hugo is an interface with Hugo, a system for making static sites.
;; OX-HUGO
(use-package ox-hugo
:ensure t
:pin melpa
:after ox
)
Interfacing with languagetool for spelling and style check. I only have this one on my home coputer.
(use-package languagetool
:ensure t
:defer t
:commands (languagetool-check
languagetool-clear-suggestions
languagetool-correct-at-point
languagetool-correct-buffer
languagetool-set-language
languagetool-server-mode
languagetool-server-start
languagetool-server-stop)
:config
(setq languagetool-java-arguments '("-Dfile.encoding=UTF-8")
languagetool-console-command "~/.languagetool/languagetool-commandline.jar"
languagetool-server-command "~/.languagetool/languagetool-server.jar"))
Changing to ef-themes from Protesilaos from modus themes.
;; THEME
(require 'ef-themes)
(load-theme 'ef-autumn :no-confirm)
(setq ef-themes-to-toggle '(ef-autumn ef-cyprus))
(define-key global-map (kbd "<f5>") #'ef-themes-toggle)
On my chromearch, I only have a very very barebones installation of Arch, because the thing is a brick. So Emacs also doubles as a “desktop”. I obviously use EXWM for that.
I mostly followed the configuration example https://github.com/ch11ng/exwm/wiki/Configuration-Example, with some small changes. Like adding a system tray.
;; EXWM
;; Disable menu-bar, tool-bar and scroll-bar to increase the usable space.
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
;; Also shrink fringes to 1 pixel.
(fringe-mode 1)
;; Turn on `display-time-mode' if you don't use an external bar.
(setq display-time-default-load-average nil)
(display-time-mode t)
;;;; Below are configurations for EXWM.
;; Load EXWM.
(require 'exwm)
;; System tray
(require 'exwm-systemtray)
(exwm-systemtray-enable)
;;(setq exwm-systemtray-height 30)
;; Set the initial number of workspaces (they can also be created later).
(setq exwm-workspace-number 4)
;; All buffers created in EXWM mode are named "*EXWM*". You may want to
;; change it in `exwm-update-class-hook' and `exwm-update-title-hook', which
;; are run when a new X window class name or title is available. Here's
;; some advice on this topic:
;; + Always use `exwm-workspace-rename-buffer` to avoid naming conflict.
;; + For applications with multiple windows (e.g. GIMP), the class names of
; all windows are probably the same. Using window titles for them makes
;; more sense.
;; In the following example, we use class names for all windows except for
;; Java applications and GIMP.
(add-hook 'exwm-update-class-hook
(lambda ()
(unless (or (string-prefix-p "sun-awt-X11-" exwm-instance-name)
(string= "gimp" exwm-instance-name))
(exwm-workspace-rename-buffer exwm-class-name))))
(add-hook 'exwm-update-title-hook
(lambda ()
(when (or (not exwm-instance-name)
(string-prefix-p "sun-awt-X11-" exwm-instance-name)
(string= "gimp" exwm-instance-name))
(exwm-workspace-rename-buffer exwm-title))))
;; Global keybindings can be defined with `exwm-input-global-keys'.
;; Here are a few examples:
(setq exwm-input-global-keys
`(
;; Bind "s-r" to exit char-mode and fullscreen mode.
(,(kbd "C-c R") . exwm-reset)
;; Bind "C-c C-k" to enter char-mode
(,(kbd "C-c C-k") . exwm-input-release-keyboard)
;; Bind "s-&" to launch applications ('M-&' also works if the output
;; buffer does not bother you).
(,(kbd "C-c y") . (lambda (command)
(interactive (list (read-shell-command "$ ")))
(start-process-shell-command command nil command)))
))
;; The following example demonstrates how to use simulation keys to mimic
;; the behavior of Emacs. The value of `exwm-input-simulation-keys` is a
;; list of cons cells (SRC . DEST), where SRC is the key sequence you press
;; and DEST is what EXWM actually sends to application. Note that both SRC
;; and DEST should be key sequences (vector or string).
(setq exwm-input-simulation-keys
'(
;; movement
([?\C-b] . [left])
([?\M-b] . [C-left])
([?\C-f] . [right])
([?\M-f] . [C-right])
([?\C-p] . [up])
([?\C-n] . [down])
([?\C-a] . [home])
([?\C-e] . [end])
([?\M-v] . [prior])
([?\C-v] . [next])
([?\C-d] . [delete])
([?\C-k] . [S-end delete])
;; cut/paste.
([?\C-w] . [?\C-x])
([?\M-w] . [?\C-c])
([?\C-y] . [?\C-v])
;; search
([?\C-s] . [?\C-f])))
;; Do not forget to enable EXWM. It will start by itself when things are
;; ready. You can put it _anywhere_ in your configuration.
(exwm-enable)
(start-process-shell-command "cbatticon" nil "cbatticon")
Various settings that I always want. (- Start citar-org-roam.)
- Allow for manual resizing of images in org.
- Increase size of latex fragments.
- Enable word wrap.
- Use visual bell instead of the horrible sound.
- Autosaving and reloading from disk comes from https://whhone.com/emacs-config/#taking-note-with-org-roam.
- Delete selection before pasting over also from https://whhone.com/emacs-config/#taking-note-with-org-roam.
- Disable splash screen.
- Smooth scrolling is from https://www.emacswiki.org/emacs/SmoothScrolling.
;; ===================================
;; Basic Customization
;; ===================================
;; Set org-image width to nil, so it can be set manually
(setq org-image-actual-width nil)
;; Enable word wrap
(add-hook 'text-mode-hook 'turn-on-visual-line-mode)
;; Set visible bell instead of sound
(setq visible-bell 1)
;; Auto save buffer if idled for 2 seconds.
(setq auto-save-timeout 2)
(auto-save-visited-mode +1)
;; Watch and reload the file changed on the disk.
(global-auto-revert-mode +1)
(setq auto-revert-remote-files t)
;; Delete the selected text first before editing.
(delete-selection-mode +1)
;; Disable splash screen
(setq inhibit-startup-message t)
;; Smooth Scrolling
(setq scroll-conservatively 10000
scroll-step 1)
Using mixed-pitch mode (from Ricing org-mode), so I can have code and normal text in one file and the text looks nicer. But I am not using my own fonts here, just the modus-themes defaults.
;; MIXED-PITCH
(use-package mixed-pitch
:ensure t
:hook
(text-mode . mixed-pitch-mode)
;;:config
;;(set-face-attribute 'default nil :font "DejaVu Sans Mono" :height 130)
;;(set-face-attribute 'fixed-pitch nil :font "DejaVu Sans Mono")
;;(set-face-attribute 'variable-pitch nil :font "DejaVu Sans")
)
#!/bin/bash
# Function to pull changes for a given repository
function pull_changes {
local repo_path=$1
if [[ -z "$repo_path" ]]; then
echo "Repository path is required."
return 1
fi
if [[ ! -d "$repo_path" ]]; then
echo "Directory $repo_path does not exist."
return 1
fi
# Navigate to the Git repository
cd "$repo_path" || return 1
# Get the current branch
currentBranch=$(git symbolic-ref --short HEAD)
if [[ -z "$currentBranch" ]]; then
echo "Failed to determine the current branch in $repo_path."
return 1
fi
echo "Current branch in $repo_path: $currentBranch"
# Pull changes from the remote repository
echo "Pulling changes for branch $currentBranch..."
git pull origin "$currentBranch"
}
# List of repositories
repos=(
"/home/nori/Documents/noriparelius"
"/home/nori/.emacs.d"
)
# Iterate over the list and call the function for each repository
for repo in "${repos[@]}"; do
pull_changes "$repo"
done
read -p "Press enter to continue"
#!/bin/bash
# Function to commit and push changes for a given repository
function commit_and_push {
local repo_path=$1
if [[ -z "$repo_path" ]]; then
echo "Repository path is required."
return 1
fi
if [[ ! -d "$repo_path" ]]; then
echo "Directory $repo_path does not exist."
return 1
fi
# Navigate to the Git repository
cd "$repo_path" || return 1
# Get the current branch
currentBranch=$(git symbolic-ref --short HEAD)
if [[ -z "$currentBranch" ]]; then
echo "Failed to determine the current branch in $repo_path."
return 1
fi
echo "Current branch in $repo_path: $currentBranch"
# Check for changes
if [[ -n $(git status --porcelain) ]]; then
echo "Changes detected in $repo_path, staging changes..."
git add -A
# Get current date and time
currentDate=$(date +'%Y-%m-%d')
currentTime=$(date +'%H-%M')
# Commit changes with a message
echo "Committing changes..."
git commit -m "Automated commit on $currentDate at $currentTime"
else
echo "No changes to commit in $repo_path."
fi
# Push changes to the remote repository
echo "Pushing changes to $currentBranch..."
git push origin "$currentBranch"
}
# List of repositories
repos=(
"/home/nori/Documents/noriparelius"
)
# Iterate over the list and call the function for each repository
for repo in "${repos[@]}"; do
commit_and_push "$repo"
done
read -p "Press enter to continue"
(defun nori-autopull ()
"Run my git autopull Bash script."
(interactive)
(shell-command "bash /home/nori/.emacs.d/autopull.sh"))
(defun nori-autopush ()
"Run my git autocommitpush Bash script."
(interactive)
(shell-command "bash /home/nori/.emacs.d/autocommitpush.sh"))
(add-to-list 'magit-no-confirm 'stage-all-changes) ;; not to be asked to stage all changes, so I can have the next hook
<<melpa>>
<<magit>>
<<org-babel>>
<<vertico>>
<<orderless>>
<<marginalia>>
<<embark>>
<<ox-hugo>>
<<languagetool>>
<<theme>>
<<custom1>>
<<mixed-pitch>>
<<autopullpush>>
;; Enable line numbers globally
;;(global-linum-mode t) deprecated since Emacs 29 https://emacs.stackexchange.com/questions/78369/what-to-use-instead-of-linum-mode-in-emacs-29
(global-display-line-numbers-mode t)
(add-hook 'kill-emacs-hook #'nori-autopush) ;; to run it on exit
(nori-autopull)
;; User-Defined init.el ends here
<<melpa>>
;;<<magit>> works terribly on windows
<<org-babel>>
<<vertico>>
<<orderless>>
<<marginalia>>
<<embark>>
<<ox-hugo>>
<<languagetool>>
<<theme>>
<<custom1>>
<<mixed-pitch>>
(defun nori-autopull-work ()
"Run my git autopull Batch file."
(interactive)
(compile "C:/Users/ELPAR/AppData/Roaming/.emacs.d/autopull-work.bat"))
(defun nori-autopush-work ()
"Run my git autocommitpush Batch file."
(interactive)
(compile "C:/Users/ELPAR/AppData/Roaming/.emacs.d/autopush-work.bat"))
;;(add-hook 'kill-emacs-hook #'nori-autopush-work) ;; doesn't work, it's async
(nori-autopull-work)
;; Enable line numbers globally
;;(global-linum-mode t) deprecated since Emacs 29 https://emacs.stackexchange.com/questions/78369/what-to-use-instead-of-linum-mode-in-emacs-29
(global-display-line-numbers-mode t)
(setq package-install-upgrade-built-in t)
;; User-Defined init.el ends here
The only thing happening here is chosing which config to load, depending on which machine I am on. I figured the easiest was to distinguish them by the name of the computer.
(cond
((equal system-name "NoriPCdebian")
(load "~/.emacs.d/home.el"))
((equal system-name "MU386U")
(load "C:/Users/ELPAR/AppData/Roaming/.emacs.d/work.el")))