10 KiB
Init.El Literate
Basics
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
(defun display-startup-echo-area-message ()
(message (format "Emacs %s loaded from %s"
emacs-version user-emacs-directory)))
(global-set-key (kbd "C-c C-r") 'eval-region)
(setq initial-scratch-message (concat ";; *SCRATCH*\n"
";; C-c C-b (eval-buffer) C-c C-r (eval-region)\n"
";; C-x C-s will let you choose where to save\n\n; "))
;; Display
;; Setting this in early-init doesn't seem to work
(set-frame-position (selected-frame) 100 10)
(set-face-attribute 'default nil :height 160)
(add-to-list 'bdf-directory-list "~/Library/Fonts")
(custom-theme-set-faces
'user
'(variable-pitch ((t (:foundry "apple" :family "IBM Plex Sans" :weight normal :height 170))))
'(fixed-pitch ((t (:foundry "apple" :family "Fira Code" :height 160)))))
(set-face-attribute 'default nil :foundry "apple" :family "Fira Code" :height 160)
(set-face-attribute 'variable-pitch nil :foundry "apple" :family "IBM Plex Sans" :height 170)
;;(global-display-line-numbers-mode 1)
(add-hook 'prog-mode-hook (lambda () (display-line-numbers-mode 1)))
(add-hook 'text-mode-hook (lambda () (display-line-numbers-mode 1)))
;; I think this saves the last cursor pos or something
(require 'saveplace)
(setq-default save-place t)
(setq save-place-file (expand-file-name ".places" user-emacs-directory))
;; Some better defaults?
(setq make-backup-files nil)
(setq auto-save-default nil)
(setq-default major-mode 'text-mode)
(setq sentence-end-double-space nil)
;; Always tabs except for *.go?
;; TODO: set up language mode packages
(setq-default c-basic-offset 4
tab-width 4
indent-tabs-mode nil)
;; Some modes
(recentf-mode 1)
(show-paren-mode 1)
(setq electric-pair-inhibit-predicate 'electric-pair-conservative-inhibit)
(electric-pair-mode 1)
(winner-mode 1)
;; IDK
(add-hook 'prog-mode-hook #'subword-mode)
(add-hook 'minibuffer-setup-hook #'subword-mode)
;; elisp
(add-hook 'emacs-lisp-mode-hook
(lambda ()
(local-set-key (kbd "C-c C-x") #'ielm)
(local-set-key (kbd "C-c C-c") #'eval-defun)
(local-set-key (kbd "C-c C-b") #'eval-buffer)))
Helper functions
Hopefully I'll be consistent with the convention of using ./
for all self-defined functions.
To search for these in completion systems, use \./
(\o/ :D). ./
stands for DOTSLASH
The function below is adapted from a blog post (link lost, sorry) which describes how you can define a function to quickly insert a src code block.
I've adapted it to automatically use emacs-lisp :tangle yes
if the file currently being edited is in the user-emacs-directory
, since I use a literate emacs configuration and the only time I'll use this function when I'm in the user emacs directory is when I'm editing my literate org configuration.
Otherwise (editing any other files) it will read input from the minibuffer for text to insert after the #+BEGIN_SRC
. The original function used ido completing read with a list of known code types and I've nuked it and just let the user append what ever they want after #+BEGIN_SRC
: this could be useful for adding :stuff like this
after the code-type.
(defun ./org-insert-src ()
"Insert SRC Block with prompted code type.
Uses 'emacs-lisp :tangle yes' if currently in user-emacs-directory."
(interactive)
(let ((code-type (if (string=
(file-truename user-emacs-directory)
(file-name-directory (buffer-file-name)))
"emacs-lisp :tangle yes"
(read-from-minibuffer "#+BEGIN_SRC "))))
(progn
(newline)
(insert (format "#+BEGIN_SRC %s\n" code-type))
(newline)
(insert "#+END_SRC\n")
(previous-line 2)
(org-edit-src-code))))
This is also another helper function for editing my literate configuration. It uses the #+BEGIN_SRC
content from the current code block (that the cursor is in) and splits the block into two by inserting #+END_SRC
and copying whatever #+BEGIN_SRC <...>
that was used in the current code block.
save-excursion
allows execution of some expressions then move the point back to where it was (before the save-excursion call).- Note that the
re-search-backward
seems to be case-insensitive, surprisingly, so bothBEGIN_SRC
andbegin_src
could be matched.
(defun ./org-split-src ()
"Split current src block into two blocks at point.
Retains src properties."
(interactive)
(insert "#+END_SRC\n\n")
(save-excursion
(re-search-backward "^\\s-*#\\+begin_src")
(defvar beginsrc (buffer-substring-no-properties (line-beginning-position) (line-end-position))))
(insert beginsrc)
(previous-line))
Load file and directory
https://www.emacswiki.org/emacs/LoadingLispFiles#h5o-2 – Thanks!
This is used for loading my modules/
dir in packages.el
.
(defun ./load-directory (dir)
"Load *.el files in a given directory"
(let ((load-it (lambda (f)
(load-file (concat (file-name-as-directory dir) f)))))
(mapc load-it (directory-files dir nil "\\.el$"))))
TBH this is such a small function but like, does save some parens y'know.
(defun ./load-file-if-exists (file)
"Same as load-file but NOP if file does not exist"
(if (file-exists-p file)
(load-file file)))
Toggle window split
https://www.emacswiki.org/emacs/ToggleWindowSplit
(defun toggle-window-split ()
(interactive)
(if (= (count-windows) 2)
(let* ((this-win-buffer (window-buffer))
(next-win-buffer (window-buffer (next-window)))
(this-win-edges (window-edges (selected-window)))
(next-win-edges (window-edges (next-window)))
(this-win-2nd (not (and (<= (car this-win-edges)
(car next-win-edges))
(<= (cadr this-win-edges)
(cadr next-win-edges)))))
(splitter
(if (= (car this-win-edges)
(car (window-edges (next-window))))
'split-window-horizontally
'split-window-vertically)))
(delete-other-windows)
(let ((first-win (selected-window)))
(funcall splitter)
(if this-win-2nd (other-window 1))
(set-window-buffer (selected-window) this-win-buffer)
(set-window-buffer (next-window) next-win-buffer)
(select-window first-win)
(if this-win-2nd (other-window 1))))))
Packages - Elpaca
Bootstrap installation of Elpaca
(defvar elpaca-installer-version 0.5)
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
:ref nil
:files (:defaults (:exclude "extensions"))
:build (:not elpaca--activate-package)))
(let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory))
(build (expand-file-name "elpaca/" elpaca-builds-directory))
(order (cdr elpaca-order))
(default-directory repo))
(add-to-list 'load-path (if (file-exists-p build) build repo))
(unless (file-exists-p repo)
(make-directory repo t)
(when (< emacs-major-version 28) (require 'subr-x))
(condition-case-unless-debug err
(if-let ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
((zerop (call-process "git" nil buffer t "clone"
(plist-get order :repo) repo)))
((zerop (call-process "git" nil buffer t "checkout"
(or (plist-get order :ref) "--"))))
(emacs (concat invocation-directory invocation-name))
((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
"--eval" "(byte-recompile-directory \".\" 0 'force)")))
((require 'elpaca))
((elpaca-generate-autoloads "elpaca" repo)))
(progn (message "%s" (buffer-string)) (kill-buffer buffer))
(error "%s" (with-current-buffer buffer (buffer-string))))
((error) (warn "%s" err) (delete-directory repo 'recursive))))
(unless (require 'elpaca-autoloads nil t)
(require 'elpaca)
(elpaca-generate-autoloads "elpaca" repo)
(load "./elpaca-autoloads")))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))
Note that disabling the built-in package.el
is in early-init.el
, which also includes setting of frame size and others.
Enable use-package
for elpaca and load my package definitions in packages.org
;; Install use-package support
(elpaca elpaca-use-package
;; Enable :elpaca use-package keyword.
(elpaca-use-package-mode)
;; Assume :elpaca t unless otherwise specified.
(setq elpaca-use-package-by-default t))
;; Block until current queue processed.
(elpaca-wait)
;;When installing a package which modifies a form used at the top-level
;;(e.g. a package which adds a use-package key word),
;;use `elpaca-wait' to block until that package has been installed/configured.
;;For example:
;;(use-package general :demand t)
;;(elpaca-wait)
(load (expand-file-name "packages.el" user-emacs-directory))
Below is useful when elpaca installs a package for the first time, and I passed my org literate config files from calling emacs, which would have already been opened, this prevents the right hooks from packages to be loaded; hence I should source my packages config again.
TODO: doesn't seem to work if called interactively, but if I'm here and use C-x C-e
on the ( load ...)
call it works – doesn't trigger elpaca?
(defun ./reload-packages.el ()
"Source packages.el again"
(interactive)
(load (expand-file-name "packages.el" user-emacs-directory)))