libkookie: emacs: build a configuration harness for elisp modules

wip/yesman
Katharina Fey 3 years ago
parent 43fa5a76e2
commit aefe49ed88
  1. 121
      infra/libkookie/overlays/kookie/emacs/base/default.el
  2. 3
      infra/libkookie/overlays/kookie/emacs/base/default.nix
  3. 70
      infra/libkookie/overlays/kookie/emacs/builder.nix
  4. 85
      infra/libkookie/overlays/kookie/emacs/default.nix
  5. 38
      infra/libkookie/overlays/kookie/emacs/init.el
  6. 93
      infra/libkookie/overlays/kookie/emacs/move-lines/default.el
  7. 2
      infra/libkookie/overlays/kookie/emacs/move-lines/default.nix
  8. 9
      infra/libkookie/overlays/kookie/emacs/theme/default.el
  9. 6
      infra/libkookie/overlays/kookie/emacs/theme/default.nix

@ -0,0 +1,121 @@
;; base.el
;; Configure emacs-builtins and core key bindings
;;
;; Emacs has a lot of things built-in that are disabled by default.
;; This module enables these settings, to create an editor experience
;; that I find more pleasing. If you want to get a taste of what it
;; is to use "kookie emacs", start by including this file.
;;
;;
;; This file is part of LIBKOOKIE, a collection of nix expressions.
;; LIBKOOKIE is licensed under the GPL-3.0 (or later) -- see LICENSE
(provide 'base)
;;; Setup consistent line numbering
(setq display-line-numbers-grow-only t)
(setq display-line-numbers-width-start t)
(global-display-line-numbers-mode t)
;;; Use spaces instead of tabs
(setq tab-width 2)
(setq-default indent-tabs-mode nil)
(defvaralias 'c-basic-offset 'tab-width)
(defvaralias 'cperl-indent-level 'tab-width)
;;; Hide startup splash
;; FIXME: this doesn't currently work...
(setq inhibit-startup-screen t)
(setq inhibit-splash-screen t)
(setq initial-scratch-message nil)
;;; Delete selections
(delete-selection-mode t)
;;; Display and create symbol pairs
(show-paren-mode t)
(electric-pair-mode t)
;;; Don't soft-wrap lines
(setq-default truncate-lines t)
;;; Hide default UI elements
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
;;; Display column in the mode line
(column-number-mode t)
;;; Enable ido mode
(ido-mode t)
(setq ido-enable-flex-matching t)
(setq ido-everywhere t)
;;; Enable ruler-mode in all buffers
(add-hook 'find-file-hook (lambda () (ruler-mode 1)))
;;; Setup mitosis buffer splitting
(setq emacs-anchor default-directory)
(defun mitosis () (interactive) (make-frame))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Function definitions
;;;
;;; A set of functions to compliment emacs' builtin functionality, to
;;; create and navigate buffers.
(defun new-empty-buffer ()
"Opens a new empty buffer."
(interactive)
(let ((buf (generate-new-buffer "untitled")))
(switch-to-buffer buf)
(funcall (and initial-major-mode))
(setq buffer-offer-save t)))
(defun user-buffer-q ()
"Check if a buffer is a user buffer"
(interactive)
(if (string-equal "*" (substring (buffer-name) 0 1))
nil
(if (string-equal major-mode "dired-mode")
nil
t
)))
(defun next-user-buffer ()
"Switch to the next user buffer."
(interactive)
(next-buffer)
(let ((i 0))
(while (< i 20)
(if (not (user-buffer-q))
(progn (next-buffer)
(setq i (1+ i)))
(progn (setq i 100))))))
(defun previous-user-buffer ()
"Switch to the previous user buffer."
(interactive)
(previous-buffer)
(let ((i 0))
(while (< i 20)
(if (not (user-buffer-q))
(progn (previous-buffer)
(setq i (1+ i)))
(progn (setq i 100))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Key bindings
;;;
;;; Custom set of key bindings to augment emacs' builtins
(global-set-key (kbd "C-x C-k") 'kill-current-buffer)
(global-set-key (kbd "C-x n") 'new-empty-buffer)
(global-set-key (kbd "C-<next>") 'next-user-buffer)
(global-set-key (kbd "C-<prior>") 'previous-user-buffer)
(global-set-key (kbd "M-s M-s") 'save-buffer)
(global-set-key (kbd "C-t") 'smex)

@ -0,0 +1,3 @@
{ buildModule, pkgs, epkgs }:
with epkgs;
(buildModule "base" ./. [ smex ])

@ -0,0 +1,70 @@
/** Build a meta-module that includes sub-modules
*
* Because of the way that the emacsWithPackages function works, it
* can only load a single "default.el" as an entry point.
*
*/
{ pkgs, lib, ... }:
rec {
/**
* Create a new elisp module with a set of package dependencies.
*
* {
* name = "base";
* lisp = ./default.el;
* deps = [ pkgs.hello ];
* }
*
* The lisp path is the main file contained in the nix store, and deps
* contains a set of emacsPackages, and base packages that the module
* depends on to function.
*/
buildModule = with pkgs; (name: path: pkgs: {
inherit name pkgs;
path = runCommand "${name}.el" {} ''
mkdir -p $out/share/emacs/site-lisp
cp -r ${path}/default.el $out/share/emacs/site-lisp/${name}.el
'';
});
/**
* Build a bootstrap module which includes submodules
*
*
*/
bootstrap =
modules: let
# Take a module and unfold the paths into a list
unfold = { path, pkgs, ... }: [ path ] ++ pkgs;
# Create an elisp require statement
mkInclude = modules: lib.concatMapStringsSep "\n" (name: "(require '${name})") modules;
# Build the list of module paths
mkModPaths = modules: builtins.foldl' (acc: mod: acc ++ (unfold mod)) [] modules;
# Build the list of module names
mkModList = modules: map (m: m.name) modules;
### Function invocations
modList = mkModList modules;
modPaths = mkModPaths modules;
loader = pkgs.writeTextFile {
name = "default.el";
text = ''
;;; THIS FILE IS AUTOMATICALLY GENERATED
${(mkInclude modList)}
'';
};
loaderWrap = pkgs.runCommand "default.el" {} ''
mkdir -p $out/share/emacs/site-lisp/
cp ${loader} $out/share/emacs/site-lisp/default.el
'';
paths = modPaths ++ [ loaderWrap ];
in
with pkgs;
symlinkJoin {
name = "libkookie-emacs-packages";
inherit paths;
};
}

@ -1,43 +1,50 @@
{ stdenv, pkgs, ... }:
{ stdenv, lib, pkgs, ... } @ args:
with pkgs; emacsWithPackages (epkgs:
(with epkgs; [
(runCommand "init.el" {} ''
mkdir -p $out/share/emacs/site-lisp
cp ${./init.el} $out/share/emacs/site-lisp/default.el
'')
with (import ./builder.nix args);
pkgs.emacsWithPackages (epkgs:
let
include = path: (import path { inherit buildModule pkgs epkgs; });
modules = [ ./base ./move-lines ./theme ];
kookie-config = bootstrap (map (p: include p) modules);
in [
kookie-config
])
# Language support
fish-mode
lsp-mode
# markdown-mode
nim-mode
nix-mode
protobuf-mode
python-mode
rust-mode
color-identifiers-mode
color-theme-sanityinc-tomorrow
company
company-lsp
# Language support
# fish-mode
# lsp-mode
# markdown-mode
# nim-mode
# nix-mode
# protobuf-mode
# python-mode
# rust-mode
# color-identifiers-mode
# color-theme-sanityinc-tomorrow
# company
# company-lsp
# direnv
fzf
ido-vertical-mode
ledger-mode
lsp-ui
magit
monokai-theme
multiple-cursors
notmuch
org
protobuf-mode
scad-mode
smex
sublimity
treemacs
undo-tree
visual-fill-column
which-key
yasnippet
]))
# fzf
# ido-vertical-mode
# ledger-mode
# lsp-ui
# magit
# monokai-theme
# multiple-cursors
# notmuch
# org
# protobuf-mode
# scad-mode
# smex
# sublimity
# treemacs
# undo-tree
# visual-fill-column
# which-key
# yasnippet
# ]))

@ -22,20 +22,6 @@
))
(org-open-at-point)))
;; More sane line-number behaviour
(setq display-line-numbers-grow-only 1)
(setq display-line-numbers-width-start 1)
(global-display-line-numbers-mode 1)
;; I just need my personal space
(setq tab-width 2)
(setq-default indent-tabs-mode nil)
(defvaralias 'c-basic-offset 'tab-width)
(defvaralias 'cperl-indent-level 'tab-width)
;; disable splash screen and startup message
(setq inhibit-startup-message 1)
(setq initial-scratch-message nil)
(autoload 'notmuch "notmuch" "notmuch mail" t)
(setq notmuch-search-oldest-first nil)
@ -75,12 +61,6 @@
(setq backup-directory-alist (list (cons "." backup-dir)))
(setq message-auto-save-directory backup-dir))
;; Some editing niceties
(delete-selection-mode 1)
(show-paren-mode 1)
(setq-default truncate-lines t)
(electric-pair-mode)
;; Explicitly enable lsp-mode for certain languages
(add-hook 'rust-mode-hook #'lsp)
(add-hook 'c-mode-hook #'lsp)
@ -92,17 +72,6 @@
;; Capn Proto mode
(add-to-list 'auto-mode-alist '("\\.capnp$" . protobuf-mode))
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(column-number-mode 1)
(setq ido-enable-flex-matching t)
(setq ido-everywhere t)
(ido-mode 1)
(add-hook 'find-file-hook (lambda () (ruler-mode 1)))
(require 'color-theme-sanityinc-tomorrow)
(load-theme 'sanityinc-tomorrow-eighties)
@ -267,13 +236,6 @@
setq offset 1)
(move--section offset))
;;; Some stolen bindings from ergo-emacs
(global-set-key (kbd "C-x C-k") 'kill-current-buffer)
(global-set-key (kbd "C-x n") 'new-empty-buffer)
(global-set-key (kbd "C-<next>") 'next-user-buffer)
(global-set-key (kbd "C-<prior>") 'previous-user-buffer)
(global-set-key (kbd "M-s M-s") 'save-buffer)
(global-set-key (kbd "C-t") 'smex)
(global-set-key (kbd "C-M-<up>") 'move-section-up)
(global-set-key (kbd "C-M-<down>") 'move-section-down)

@ -0,0 +1,93 @@
;; move-lines.el
;; Provide a mechanism to move line selections
;;
;; By default, moving lines up and down in a buffer is very annoying,
;; so this set of functions creates a way to do this, and binds it to
;; easily accessible key bindings. This mirrors functionality from
;; other GUI text editors such as sublime text or vs code.
;;
;;
;; This file is part of LIBKOOKIE, a collection of nix expressions.
;; LIBKOOKIE is licensed under the GPL-3.0 (or later) -- see LICENSE
(provide 'move-lines)
(defun move--section (offset)
"Move a line or reg up or down by on offset."
;; We'll have to track 4 text points in this function
;; Future me: the * is important....
(let* (txt-start
txt-end
(reg-start (point))
(reg-end reg-start)
;; De we delete a trailing \n
del-nl-trail)
;; Find the text borders
(when (region-active-p)
(if (> (point) (mark))
(setq reg-start (mark))
(exchange-point-and-mark)
(setq reg-end (point))))
(end-of-line)
;; If point > point-max there is no trailing \n
(if (< (point) (point-max))
(forward-char 1)
(setq del-nl-trail t)
(insert-char ?\n))
(setq txt-end (point)
reg-end (- reg-end txt-end))
;; text/region start points
(goto-char reg-start)
(beginning-of-line)
(setq txt-start (point)
reg-start (- reg-start txt-end))
;; Fake the txt move
(let ((text (delete-and-extract-region txt-start txt-end)))
(forward-line offset)
(when (not (= (current-column) 0))
(insert-char ?\n)
(setq del-nl-trail t))
(insert text))
;; Restore point position
(forward-char reg-start)
;; Clean that annoying \n at the end
(when del-nl-trail
(save-excursion
(goto-char (point-max))
(delete-char -1)))
;; If we operated on a region we need to fix the selection
(when (region-active-p)
(setq deactivate-mark nil)
(set-mark (+ (point) (- (- reg-start reg-end)))))))
(defun move-section-up (offset)
"Move a line or reg upwards"
(interactive "p")
(if (eq offset nil)
setq offset 1)
(move--section (- offset)))
(defun move-section-down (offset)
"Move a line or region dawnwards"
(interactive "p")
(if (eq offset nil)
setq offset 1)
(move--section offset))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Key bindings
;;;
;;; Custom set of key bindings to augment emacs' builtins
(global-set-key (kbd "C-M-<up>") 'move-section-up)
(global-set-key (kbd "C-M-<down>") 'move-section-down)

@ -0,0 +1,2 @@
{ buildModule, pkgs, epkgs }:
(buildModule "move-lines" ./. [])

@ -0,0 +1,9 @@
(provide 'theme)
(custom-set-variables
'(custom-safe-themes
'("628278136f88aa1a151bb2d6c8a86bf2b7631fbea5f0f76cba2a0079cd910f7d" default))
'(send-mail-function 'sendmail-send-it))
(custom-set-faces)

@ -0,0 +1,6 @@
{ buildModule, pkgs, epkgs }:
with epkgs;
(buildModule "theme" ./. [
color-theme-sanityinc-tomorrow
color-identifiers-mode
])
Loading…
Cancel
Save