254 lines
10 KiB
Org Mode
254 lines
10 KiB
Org Mode
|
#+title: Init.El Literate
|
||
|
:PROPERTIES:
|
||
|
:tangle: ~/.config/emacsd/init.el
|
||
|
:END:
|
||
|
#+auto_tangle: t
|
||
|
|
||
|
* Basics
|
||
|
#+BEGIN_SRC emacs-lisp :tangle yes
|
||
|
(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)))
|
||
|
#+END_SRC
|
||
|
|
||
|
* 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.
|
||
|
|
||
|
#+begin_src emacs-lisp :tangle yes
|
||
|
(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))))
|
||
|
#+END_SRC
|
||
|
|
||
|
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 both =BEGIN_SRC= and =begin_src= could be matched.
|
||
|
|
||
|
#+begin_src emacs-lisp :tangle yes
|
||
|
(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))
|
||
|
#+end_src
|
||
|
|
||
|
** Load file and directory
|
||
|
|
||
|
https://www.emacswiki.org/emacs/LoadingLispFiles#h5o-2 -- Thanks!
|
||
|
|
||
|
This is used for loading my =modules/= dir in =packages.el=.
|
||
|
|
||
|
#+BEGIN_SRC emacs-lisp :tangle yes
|
||
|
(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$"))))
|
||
|
#+END_SRC
|
||
|
|
||
|
TBH this is such a small function but like, does save some parens y'know.
|
||
|
|
||
|
#+BEGIN_SRC emacs-lisp :tangle yes
|
||
|
(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)))
|
||
|
#+END_SRC
|
||
|
|
||
|
** Toggle window split
|
||
|
|
||
|
https://www.emacswiki.org/emacs/ToggleWindowSplit
|
||
|
|
||
|
#+BEGIN_SRC emacs-lisp :tangle yes
|
||
|
(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))))))
|
||
|
#+END_SRC
|
||
|
|
||
|
|
||
|
|
||
|
* Packages - Elpaca
|
||
|
|
||
|
Bootstrap installation of Elpaca
|
||
|
#+BEGIN_SRC emacs-lisp :tangle yes
|
||
|
(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))
|
||
|
#+END_SRC
|
||
|
|
||
|
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
|
||
|
#+BEGIN_SRC emacs-lisp :tangle yes
|
||
|
;; 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))
|
||
|
#+END_SRC
|
||
|
|
||
|
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?
|
||
|
|
||
|
#+BEGIN_SRC emacs-lisp :tangle yes
|
||
|
(defun ./reload-packages.el ()
|
||
|
"Source packages.el again"
|
||
|
(interactive)
|
||
|
(load (expand-file-name "packages.el" user-emacs-directory)))
|
||
|
#+END_SRC
|
||
|
|