Baemacs is a GNU/Emacs configuration packaged within org-mode
. It provides a
concise abstraction, this file you’re reading, to stage and detect changes which
automatically updates on start of GNU/Emacs.
The file you’re reading contains all configuration details. It uses org-mode
to capture documentation and code blocks which are written to their respective
target files. When GNU/Emacs is started, if the README.org
file has been
changed it triggers rewriting the configuration files.
This section demonstrates how I build GNU/Emacs on Fedora Linux. Doing so is entirely optional as many systems provide GNU/Emacs with support for nativecomp, tree-sitter and other newer features enabled.
$ sudo dnf install \
autoconf cairo-devel giflib-devel gmp-devel gnutls-devel gnutls-utils \
gpm-devel gtk+-devel gtk3-devel harfbuzz-devel jansson-devel lcms2-devel \
libgccjit-devel libjpeg-devel libotf-devel libpng-devel librsvg2-devel \
libtiff-devel libtree-sitter-devel libwebp-devel libXpm-devel make \
ncurses-devel openssl-devel sqlite-devel systemd-devel texinfo zlib-devel
$ git clone --branch=emacs-29 --depth=1 https://github.com/emacs-mirror/emacs
$ cd emacs
$ ./autogen.sh
$ ./configure \
CFLAGS="-O2 -g3 -march=native -pipe" \
--with-cairo=yes --with-dbus=yes --with-file-notification=yes \
--with-gif=yes --with-gnutls=yes --with-gpm=yes --with-jpeg=yes \
--with-json=yes --with-libgmp=yes --with-libsystemd=yes \
--with-mailutils=yes --with-modules=yes --with-native-compilation=aot \
--with-pgtk=yes --with-png=yes --with-pop=no --with-rsvg=yes \
--with-selinux=yes --with-sound=no --with-sqlite3=yes --with-threads=yes \
--with-tiff=yes --with-tree-sitter=yes --with-webp=yes --with-x=no \
--with-xml2=yes --with-xpm=yes --with-zlib=yes
$ make -j$(grep -c ^processor /proc/cpuinfo)
$ sudo make install
Clone this repo into $HOME/.config/emacs
, then write the configuration by
using org-babel-tangle-file
:
$ git clone --depth 1 https://github.com/jcmdln/baemacs.git ~/.config/emacs
$ emacs -Q --batch --eval="
(progn
(require 'org)
(org-babel-tangle-file (concat user-emacs-directory \"README.org\"))
)"
When GNU/Emacs is started, any remaining configuration steps will be performed such as installing and compiling packages.
;;; early-init.el ---- Baemacs early initialization file
;;; Commentary:
;; Emacs will look for this specific file before initializing the GUI and
;; other such things.
;;; Code:
Rather than Emacs customization being appended to the end of the configuration
file, in our case init.el
, we may specify an alternate custom-file
:
(setq custom-file (concat user-emacs-directory "custom.el"))
(setq prefer-coding-system 'utf-8
set-default-coding-systems 'utf-8
set-language-environment "UTF-8"
set-locale-environment "en_US.UTF-8")
(setenv "EDITOR" "emacsclient")
(setenv "GIT_EDITOR" "emacsclient")
(setenv "MANPATH" (getenv "MANPATH"))
(setenv "PAGER" "cat")
(setenv "PATH" (getenv "PATH"))
(setenv "PROMPT_COMMAND" "")
(setenv "SHELL" (getenv "SHELL"))
(setenv "TERM" (getenv "TERM"))
(require 'package)
(if (fboundp 'native-compile)
(setq package-native-compile t))
(setq package-user-dir (concat user-emacs-directory "pkg/"))
(setq package-archives '(("elpa" . "https://elpa.gnu.org/packages/")
("melpa-stable" . "https://stable.melpa.org/packages/")
("melpa" . "https://melpa.org/packages/"))
package-archive-priorities '(("elpa" . 3)
("melpa-stable" . 2)
("melpa" . 1)))
(when (< emacs-major-version 27)
(package-initialize))
The first package we’ll ensure exists is use-package, which the rest of this file relies on for handling per-package configuration. In newer versions of Emacs use-package is now a built-in, but we should check to be nice to older versions:
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(eval-when-compile
(require 'use-package)
(require 'bind-key))
Some decent use-package tweaks are to defer loading a package unless demanded, ensure a package exists or can be retrieved before loading its configuration, and check that use-package is installed and active before attempting to initialize:
(setq use-package-always-ensure 't
use-package-check-before-init 't)
The second package will keep our Emacs configuration directory nice and tidy by adjusting the locations of configuration files. It uses a unixy format, which is a nice change.
(use-package no-littering
:commands (dired-create-directory no-littering-expand-var-file-name)
:init
(setq auto-save-file-name-transforms `((".*" ,(no-littering-expand-var-file-name "auto-save/") 't))
baemacs/auto-save-dir (concat user-emacs-directory "var/auto-save"))
(if (not (file-directory-p baemacs/auto-save-dir))
(dired-create-directory baemacs/auto-save-dir)))
I don’t find the toolbars to be useful comparatively to the amount of visual space they consume. The following will disable the various toolbars when their functions are bound, which prevents them from ever being initialized:
(when (fboundp 'menu-bar-mode) (menu-bar-mode -1))
(when (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
(when (fboundp 'tool-bar-mode) (tool-bar-mode -1))
After initialization completes, we’ll end up with some clutter that is not very helpful for long-time Emacs users.
- Remove the default scratch buffer message
- Disable the splash screen
- Disable the startup buffer menu
(setq initial-scratch-message ""
inhibit-splash-screen 't
inhibit-startup-buffer-menu 't)
One big annoyance is Emacs arbitrary splitting my window to show a newly
created buffer. This is especially annoying when I run a command myself such as
M-x man
which causes arbitrary splits.
Here we will enforce always re-using the currently selected frame when a new buffer is opened or focused. This works in most cases, though as shown below certain things like ‘man’ will not respect our choices and require specific adjustment. Some things like ‘gnus’ should still make splits as they want, so we won’t look for every possible edge condition to normalize this behavior.
(add-to-list 'display-buffer-alist '("*Help*" display-buffer-same-window))
(add-to-list 'display-buffer-alist '("*Man*" display-buffer-same-window))
(setq pop-up-frames nil
pop-up-windows nil)
(provide 'early-init)
;;; early-init.el ends here
Emacs will look for this specific file once it reaches the init phase. Here we will make modifications to things that ship with Emacs and should be changed as early as possible.
;;; init.el ---- Baemacs initialization file
;;; Commentary:
;; Emacs will look for this specific file once it reaches the
;; initialization phase. Here we will make modifications to things that
;; ship with Emacs and should be changed early.
;;; Code:
In terms of appearance, I prefer to have as little wasted space and visual clutter as possible. I make no attempt to completely restyle Emacs, preferring instead to make slight modifications.
This probably isn’t needed, but we’ll set the default font to the monospace font defined on the system.
(set-face-attribute :family "Monospace")
Rather than include yet another theme, we’ll use the tango-dark theme.
(load-theme 'tango-dark 't)
There are some general-purpose changes to make for editing files, which ideally
if I ever get around to incorporating site-start.el
will allow loading a
slim, nimble instance of Emacs when needed. For now I’ll leave these changes
here.
(setq backup-by-copying 't)
This part is a bit unorganized though reduces clutter by inhibiting buffers and adjusting how the clipboard works in Emacs.
(setq save-interprogram-paste-before-kill 't
select-enable-primary nil)
(add-hook 'after-init-hook
(lambda() (delete-selection-mode 1)))
- Scroll line-by-line
- Preserve the cursor position when scrolling
- No scroll margins
- Don’t scroll past the end of a buffer
(setq auto-window-vscroll nil
scroll-conservatively 101
scroll-margin 0
scroll-preserve-screen-position 1
scroll-step 1
scroll-up-aggressively 0.0
scroll-down-aggressively 0.0)
Display line numbers in most types of modes where it makes sense.
(add-hook 'after-init-hook
(lambda()
(add-hook 'conf-mode-hook 'display-line-numbers-mode)
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
(add-hook 'org-mode-hook 'display-line-numbers-mode)
(add-hook 'text-mode-hook 'display-line-numbers-mode)))
- Show column numbers
- Ensure
\n
always precedes EOF - When
show-paren-mode
is enabled, delay showing match for 330ms - Disable the
visual-bell
(setq column-number-mode 't
require-final-newline 't
show-paren-delay 0.33
visible-bell nil)
Highlight matching parenthesis, always.
(add-hook 'after-init-hook (lambda() (show-paren-mode 't)))
Before saving, remove any trailing whitespace characters.
(add-hook 'before-save-hook 'delete-trailing-whitespace)
When Visual Line mode is enabled, ‘word-wrap’ is turned on in this buffer, and simple editing commands are redefined to act on visual lines, not logical lines.
(add-hook 'after-init-hook (lambda() (global-visual-line-mode 't)))
(defalias 'yes-or-no-p 'y-or-n-p)
(global-set-key (kbd "M--")
(lambda()
(interactive)
(split-window-vertically)
(other-window 1 nil)
(switch-to-next-buffer)))
(global-set-key (kbd "M-=")
(lambda()
(interactive)
(split-window-horizontally)
(other-window 1 nil)
(switch-to-next-buffer)))
(global-set-key (kbd "C-c c") 'comment-or-uncomment-region)
(global-set-key (kbd "<M-down>") 'windmove-down)
(global-set-key (kbd "<M-left>") 'windmove-left)
(global-set-key (kbd "<M-right>") 'windmove-right)
(global-set-key (kbd "<M-up>") 'windmove-up)
(setq mouse-wheel-follow-mouse 't
mouse-wheel-progressive-speed nil
mouse-wheel-scroll-amount '(3 ((shift) . 3))
mouse-yank-at-point 't)
(add-hook 'after-init-hook (lambda() (xterm-mouse-mode 1)))
(global-set-key (kbd "<mouse-4>") (lambda() (interactive) (scroll-down-line 3)))
(global-set-key (kbd "<mouse-5>") (lambda() (interactive) (scroll-up-line 3)))
At the end of initialization, ensure that README.org
is not newer than
config.el
, otherwise rebuild our configuration files and byte-compile them.
(defun baemacs/reconfig()
"Reconfigure Baemacs by writing and loading our config."
(require 'org)
(interactive)
(org-babel-tangle-file (concat user-emacs-directory "README.org")))
(if (file-newer-than-file-p (concat user-emacs-directory "README.org")
(concat user-emacs-directory "early-init.el"))
(baemacs/reconfig))
(load (concat user-emacs-directory "config.el"))
(provide 'init)
;;; init.el ends here
This is a non-standard file that is referenced at the end of init.el
which
contains our extra package and language definitions. Before we add anything to
this file, first we’ll add the file header:
;;; config.el ---- Baemacs configuration file
;;; Commentary:
;; This is a non-standard file that is referenced at the end of 'init.el'
;; which contains our extra package and language definitions.
;;; Code:
Circe is a Client for IRC in Emacs.
https://stable.melpa.org/#/circe https://github.com/emacs-circe/circe
(use-package circe
:defer 't
:commands (enable-lui-logging-globally lui-set-prompt)
:config
(setq circe-default-part-message ""
circe-default-quit-message ""
circe-format-server-topic "*** Topic: {userhost}: {topic-diff}"
circe-reduce-lurker-spam 't
circe-use-cycle-completion 't
lui-fill-type nil
lui-time-stamp-format "%H:%M:%S"
lui-time-stamp-position 'left-margin)
(add-hook 'circe-server-mode-hook (lambda() (require 'circe-chanop)))
(add-hook 'circe-chat-mode-hook
(lambda()
(lui-set-prompt
(concat (propertize
(concat (buffer-name) ":")
'face 'circe-prompt-face)
" "))))
(add-hook 'lui-mode-hook
(lambda()
(setq fringes-outside-margins 't
left-margin-width 9
word-wrap 't
wrap-prefix "")))
(enable-circe-color-nicks)
(if (file-exists-p (concat user-emacs-directory "usr/circe.el"))
(load-file (concat user-emacs-directory "usr/circe.el"))))
Company is a modular completion framework. Modules for retrieving completion candidates are called backends, modules for displaying them are frontends.
https://stable.melpa.org/#/company https://github.com/company-mode/company-mode
(use-package company
:config
(setq company-begin-commands '(self-insert-command)
company-idle-delay 0.3
company-echo-delay 0
company-tooltip-limit 20)
:hook
((prog-mode . company-mode)
(text-mode . company-mode)))
(use-package counsel
:bind (("<f1> f" . counsel-describe-function)
("<f1> l" . counsel-find-library)
("<f1> v" . counsel-describe-variable)
("<f2> i" . counsel-info-lookup-symbol)
("<f2> u" . counsel-unicode-char)
("C-s" . counsel-grep-or-swiper)
("C-c g" . counsel-git)
("C-c j" . counsel-git-grep)
("C-c l" . counsel-ag)
("C-r" . counsel-minibuffer-history)
("C-x C-f" . counsel-find-file)
("C-x l" . counsel-locate)
("M-x" . counsel-M-x)))
(use-package diff-hl
:demand 't
:commands (diff-hl-mode diff-hl-margin-mode)
:hook ((conf-mode prog-mode text-mode) . diff-hl-mode)
:config
(when (eq window-system nil)
(add-hook 'after-init-hook
(lambda()
(add-hook 'conf-mode-hook 'diff-hl-margin-mode)
(add-hook 'org-mode-hook 'diff-hl-margin-mode)
(add-hook 'prog-mode-hook 'diff-hl-margin-mode)
(add-hook 'text-mode-hook 'diff-hl-margin-mode)))))
(use-package editorconfig
:hook
(prog-mode-hook . (lambda()
(add-hook 'before-save-hook
(lambda() (editorconfig-apply) (editorconfig-format-buffer))
nil 'local)))
:init (editorconfig-mode 1))
(use-package eglot
:commands (eglot-ensure)
:config
(setq eglot-auto-display-help-buffer nil
eglot-put-doc-in-help-buffer nil)
(add-to-list 'eglot-server-programs '(c-mode . ("clangd")))
(add-to-list 'eglot-server-programs '(c++-mode . ("clangd")))
(add-to-list 'eglot-server-programs '(rust-mode . ("rust-analyzer")))
:hook (((c-mode c++-mode go-mode python-mode rust-mode zig-mode) . 'eglot-ensure)
((c-mode c++-mode) . (lambda() (fset 'c-indent-region 'clang-format-region)))
(eglot-managed-mode . (lambda() (add-hook 'before-save-hook 'eglot-format-buffer nil 'local)))))
(use-package eldoc
:commands (global-eldoc-mode)
:config (setq eldoc-echo-area-use-multiline-p nil))
This package provides an extensible web feed reader, supporting both RSS and Atom.
(use-package elfeed
:config
(setq elfeed-search-filter "@1-week-ago +unread "
url-queue-timeout 10)
(if (file-exists-p (concat user-emacs-directory "usr/elfeed.el"))
(load-file (concat user-emacs-directory "usr/elfeed.el"))))
(use-package eshell
:commands
(baemacs/eshell/clear
baemacs/eshell/prompt-function
eshell
eshell-new
eshell-truncate-buffer
eshell/basename
eshell/pwd)
:config
(defun baemacs/eshell/clear()
"Clear the current eshell buffer by truncating the contents."
(interactive)
(setq-local eshell-buffer-maximum-lines 0)
(eshell-truncate-buffer))
(defun baemacs/eshell/prompt-function()
"Custom eshell prompt."
(interactive)
(lambda ()
(concat "[" (user-login-name) "@"
(car (split-string (system-name) "\\.")) " "
(if (string= (eshell/pwd) (getenv "HOME"))
"~" (eshell/basename (eshell/pwd))) "]"
(if (= (user-uid) 0) "# " "$ "))))
(setq eshell-banner-message ""
eshell-cmpl-cycle-completions nil
eshell-error-if-no-glob 't
eshell-hist-ignoredups 't
eshell-history-size 4096
eshell-prefer-lisp-functions 't
eshell-prompt-function (baemacs/eshell/prompt-function)
eshell-prompt-regexp "^[^#$\n]*[#$] "
eshell-save-history-on-exit 't
eshell-scroll-to-bottom-on-input nil
eshell-scroll-to-bottom-on-output nil
eshell-scroll-show-maximum-output nil)
:init
(add-hook 'eshell-mode-hook (lambda() (defalias 'eshell/clear 'baemacs/eshell/clear)))
(defun baemacs/eshell-new()
"Open a new instance of eshell."
(interactive)
(eshell 'N)))
I like eww, but it was missing a few things for me to use it as my primary browser for non-interactive sites. Here we will ensure that eww is our primary browser when visiting links, and that images are blocked by default. Should you have multiple eww buffers open and want to toggle displaying images in a specific buffer, you may now do so.
(use-package eww
:commands (eww
eww-mode
eww-reload
baemacs/eww-toggle-images
baemacs/eww-new)
:config
(when window-system
(defun baemacs/eww-toggle-images()
"Toggle blocking images in eww."
(interactive)
(if (bound-and-true-p shr-blocked-images)
(setq-local shr-blocked-images nil)
(setq-local shr-blocked-images ""))
(eww-reload))
(setq shr-blocked-images ""))
:init
(defun baemacs/eww-new()
"Open a new instance of eww."
(interactive)
(let ((url (read-from-minibuffer "Enter URL or keywords: ")))
(switch-to-buffer (generate-new-buffer "*eww*"))
(eww-mode)
(eww url)))
(setq browse-url-browser-function 'eww-browse-url))
(use-package eww-lnum
:bind (:map eww-mode-map
("f" . eww-lnum-follow)
("F" . eww-lnum-universal))
:commands (eww-lnum-follow eww-lnum-universal))
(use-package flycheck
:hook (prog-mode . flycheck-mode))
I’ve bounced between using “real” email clients and gnus quite a few times, though here we will attempt to make gnus behave like other clients.
(use-package gnus
:bind (("<M-down>" . windmove-down)
("<M-up>" . windmove-up))
:config
(add-to-list 'mm-discouraged-alternatives "text/html")
(add-to-list 'mm-discouraged-alternatives "text/richtext")
(setq gnus-permanently-visible-groups ".*"
gnus-show-threads 't
gnus-sum-thread-tree-false-root ""
gnus-sum-thread-tree-indent " "
gnus-sum-thread-tree-leaf-with-other "├─> "
gnus-sum-thread-tree-root ""
gnus-sum-thread-tree-single-leaf "╰─> "
gnus-sum-thread-tree-vertical "│ "
gnus-summary-line-format "%U%R:%-15,15o %-20,20A %-3,3t %B%s\n"
gnus-summary-thread-gathering-function 'gnus-gather-threads-by-subject
gnus-thread-hide-subtree 't
gnus-thread-sort-functions '(gnus-thread-sort-by-date))
(if (file-exists-p (concat user-emacs-directory "usr/gnus.el"))
(load-file (concat user-emacs-directory "usr/gnus.el")))
:hook ((gnus-summary-prepared . gnus-summary-sort-by-most-recent-date)
(gnus-group-mode . gnus-group-sort-groups-by-alphabet)))
This package provides an alternative to the built-in Emacs help that provides much more contextual information.
(use-package helpful
:bind (("C-h C" . #'helpful-command)
("C-h F" . #'helpful-function)
("C-h f" . #'helpful-callable)
("C-h k" . #'helpful-key)
("C-h v" . #'helpful-variable)))
I’m not a fan of the default ibuffer behavior, if the total size of this section does not make that clear. Here we will sort buffers, show human readable sizes, and define a ton of filter groups.
(use-package ibuffer
:bind (("C-x C-b" . ibuffer)
("<C-tab>" . next-buffer)
("<C-iso-lefttab>" . previous-buffer))
:commands (ibuffer-switch-to-saved-filter-groups)
:config
(add-hook 'ibuffer-auto-mode-hook
(lambda()
(ibuffer-switch-to-saved-filter-groups "default")))
(define-ibuffer-column size-h
(:name "Size" :inline 't)
(cond ((> (buffer-size) (* 1000 1000 1000))
(format "%7.1fG" (/ (buffer-size) 1000000000.0)))
((> (buffer-size) (* 1000 1000))
(format "%7.1fM" (/ (buffer-size) 1000000.0)))
((> (buffer-size) 1000)
(format "%7.1fK" (/ (buffer-size) 1000.0)))
('t (format "%8d" (buffer-size)))))
(setq ibuffer-show-empty-filter-groups nil
ibuffer-saved-filter-groups
(quote (("default"
("emacs"
(or (name . "^\\*Completions\\*$")
(name . "^\\*Customize\\*")
(name . "^\\*Disabled\s.*\\*$")
(name . "^\\*Help\\*$")
(name . "^\\*Messages\\*$")
(name . "^\\*scratch\\*.*$")))
("apps"
(or (mode . dired-mode)
(mode . eshell-mode)))
("dev"
(or (name . "^\\*clang")
(name . "^\\*gcc")
(name . "^\\*RTags")
(name . "^\\*rdm\\*")
(name . "magit")
(name . "COMMIT_EDITMSG")
(name . "^\\*Flycheck")
(name . "^\\*Flyspell")))
("docs"
(or (name . "^\\*Man\s.*\s.*\\*$")
(name . "^\\*WoMan\s.*\s.*\\*$")
(mode . pdf-view-mode)))
("irc"
(or (mode . circe-mode)
(mode . circe-channel-mode)
(mode . circe-query-mode)
(mode . circe-server-mode)))
("logs"
(or (name . "^\\*EGLOT.*")
(name . "^\\*eldoc\\*$")
(name . "-Log\\*$")
(name . "\slog\\*$")))
("mail"
(or (mode . message-mode)
(mode . bbdb-mode)
(mode . mail-mode)
(mode . gnus-group-mode)
(mode . gnus-summary-mode)
(mode . gnus-article-mode)
(name . "^\\.bbdb$")
(name . "^\\.newsrc-dribble")))
("web"
(or (mode . eww-mode)
(name . "^\\*elfeed")))
)))
ibuffer-formats '((mark
modified read-only " "
(name 35 35 :left :nil) " "
(size-h 9 -1 :right) " "
(mode 16 16 :left :elide) " "
filename-and-process)))
:hook ((ibuffer . ibuffer-auto-mode)
(ibuffer-mode . ibuffer-do-sort-by-alphabetic)))
(use-package ivy
:bind
(("C-c C-r" . ivy-resume)
("<f6>" . ivy-resume))
:commands (ivy-mode)
:config
(setq ivy-use-virtual-buffers 't
enable-recursive-minibuffers 't)
:hook (after-init . (lambda() (ivy-mode 1))))
(use-package ivy-rich
:commands (ivy-rich-mode)
:hook (ivy-mode . (lambda() (ivy-rich-mode 1))))
(use-package magit
:bind ("C-c C-c" . with-editor-finish)
:demand 't)
(use-package org
:bind
(:map org-mode-map
([remap backward-paragraph] . nil)
([remap forward-paragraph] . nil)
("C-S-<down>" . nil)
("C-S-<up>" . nil)
("M-<down>" . nil)
("M-<up>" . nil)
("S-<left>" . nil)
("S-<right>" . nil))
:config
(set-face-attribute 'org-block nil :background "#111111" :extend 't)
(setq org-src-fontify-natively 't
org-src-tab-acts-natively 't
org-support-shift-select 'always)
(setq org-babel-load-languages
'((C . t)
(awk . t)
(emacs-lisp . t)
(lisp . t)
(makefile . t)
(scheme . t)
(shell . t)
(sql . t)
(sqlite . t)))
:hook
((org-metadown . windmove-down)
(org-metaleft . windmove-left)
(org-metaright . windmove-right)
(org-metaup . windmove-up)
(org-mode . (lambda() (setq-local indent-tabs-mode nil))))
:mode ("\\.org$" . org-mode))
(use-package company-org-block
:after (company org)
:config (setq company-org-block-edit-style 'auto)
:init
(add-hook 'org-mode-hook
(lambda ()
(add-to-list (make-local-variable 'company-backends) 'company-org-block))))
(use-package org-drill
:after (org)
:commands (org-drill)
:defer 't)
(use-package toc-org
:after (org)
:commands (toc-org-enable)
:hook (org-mode . toc-org-enable))
(provide 'config)
;;; config.el ends here
(use-package rainbow-delimiters
:hook ((conf-mode prog-mode text-mode) . rainbow-delimiters-mode))
(use-package ranger
:commands (ranger-override-dired-mode)
:init (ranger-override-dired-mode 't))
(use-package scratch
:commands (baemacs/scratch-new)
:init
(defun baemacs/scratch-new()
"Open a new scratch buffer."
(interactive)
(switch-to-buffer (generate-new-buffer "*scratch*"))
(lisp-mode)))
I feel that Emacs is missing some extensions for server-based functions and added a warning when attempting to close Emacs. Also, if you want to update your packages or kill Emacs without saving in a quicker fashion you may appreciate the additional functions.
(use-package server
:demand 't
:bind ("C-x C-c" . baemacs/server-stop)
:commands (baemacs/server-kill baemacs/server-stop)
:config
(unless (and (fboundp 'server-running-p)
(server-running-p))
(server-start))
:init
(defun baemacs/server-kill()
"Delete current Emacs server, then kill Emacs"
(interactive)
(if (y-or-n-p "Kill Emacs without saving? ")
(kill-emacs)))
(defun baemacs/server-stop()
"Prompt to save buffers, then kill Emacs."
(interactive)
(if (y-or-n-p "Quit Emacs? ")
(save-buffers-kill-emacs))))
(use-package smartparens
:config
(setq sp-highlight-pair-overlay nil
sp-highlight-wrap-overlay nil
sp-highlight-wrap-tag-overlay nil)
:hook ((eshell-mode org-mode prog-mode text-mode) . turn-on-smartparens-mode))
(use-package swiper
:after (counsel ivy))
(use-package undo-tree
:commands (global-undo-tree-mode)
:init (global-undo-tree-mode))
(use-package cc-mode
:config
(setq-local c-basic-offset 8
c-default-style "linux"
indent-tabs-mode 't
tab-width 8)
:hook
((c-mode . tree-sitter-mode)
(c-mode . tree-sitter-hl-mode))
:mode
(("\\.c$" . c-mode)
("\\.h$" . c-mode)))
(use-package cc-mode
:config
(setq-local c-basic-offset 4
c-default-style "ellemtel"
indent-tabs-mode 't
tab-width 4)
:mode
(("\\.cc$" . c++-mode)
("\\.cpp$" . c++-mode)
("\\.cxx$" . c++-mode)
("\\.hh$" . c++-mode)
("\\.hpp$" . c++-mode)))