diff --git a/infra/libkookie/overlays/kookie/emacs/base/default.el b/infra/libkookie/overlays/kookie/emacs/base/default.el new file mode 100644 index 00000000000..3efaf47088b --- /dev/null +++ b/infra/libkookie/overlays/kookie/emacs/base/default.el @@ -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-user-buffer) +(global-set-key (kbd "C-") 'previous-user-buffer) +(global-set-key (kbd "M-s M-s") 'save-buffer) +(global-set-key (kbd "C-t") 'smex) + diff --git a/infra/libkookie/overlays/kookie/emacs/base/default.nix b/infra/libkookie/overlays/kookie/emacs/base/default.nix new file mode 100644 index 00000000000..570cc2c62a3 --- /dev/null +++ b/infra/libkookie/overlays/kookie/emacs/base/default.nix @@ -0,0 +1,3 @@ +{ buildModule, pkgs, epkgs }: +with epkgs; +(buildModule "base" ./. [ smex ]) diff --git a/infra/libkookie/overlays/kookie/emacs/builder.nix b/infra/libkookie/overlays/kookie/emacs/builder.nix new file mode 100644 index 00000000000..45a02e3eced --- /dev/null +++ b/infra/libkookie/overlays/kookie/emacs/builder.nix @@ -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; + }; +} diff --git a/infra/libkookie/overlays/kookie/emacs/default.nix b/infra/libkookie/overlays/kookie/emacs/default.nix index e6f1e511525..ab61ec45054 100644 --- a/infra/libkookie/overlays/kookie/emacs/default.nix +++ b/infra/libkookie/overlays/kookie/emacs/default.nix @@ -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 + # ])) diff --git a/infra/libkookie/overlays/kookie/emacs/init.el b/infra/libkookie/overlays/kookie/emacs/init.el index 422cbce2d30..560e53df082 100644 --- a/infra/libkookie/overlays/kookie/emacs/init.el +++ b/infra/libkookie/overlays/kookie/emacs/init.el @@ -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-user-buffer) -(global-set-key (kbd "C-") '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-") 'move-section-up) (global-set-key (kbd "C-M-") 'move-section-down) diff --git a/infra/libkookie/overlays/kookie/emacs/move-lines/default.el b/infra/libkookie/overlays/kookie/emacs/move-lines/default.el new file mode 100644 index 00000000000..553ee7789b9 --- /dev/null +++ b/infra/libkookie/overlays/kookie/emacs/move-lines/default.el @@ -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-") 'move-section-up) +(global-set-key (kbd "C-M-") 'move-section-down) diff --git a/infra/libkookie/overlays/kookie/emacs/move-lines/default.nix b/infra/libkookie/overlays/kookie/emacs/move-lines/default.nix new file mode 100644 index 00000000000..f7f51e75c14 --- /dev/null +++ b/infra/libkookie/overlays/kookie/emacs/move-lines/default.nix @@ -0,0 +1,2 @@ +{ buildModule, pkgs, epkgs }: +(buildModule "move-lines" ./. []) diff --git a/infra/libkookie/overlays/kookie/emacs/theme/default.el b/infra/libkookie/overlays/kookie/emacs/theme/default.el new file mode 100644 index 00000000000..2057b13b619 --- /dev/null +++ b/infra/libkookie/overlays/kookie/emacs/theme/default.el @@ -0,0 +1,9 @@ + +(provide 'theme) + +(custom-set-variables + '(custom-safe-themes + '("628278136f88aa1a151bb2d6c8a86bf2b7631fbea5f0f76cba2a0079cd910f7d" default)) + '(send-mail-function 'sendmail-send-it)) +(custom-set-faces) + diff --git a/infra/libkookie/overlays/kookie/emacs/theme/default.nix b/infra/libkookie/overlays/kookie/emacs/theme/default.nix new file mode 100644 index 00000000000..a80dc020367 --- /dev/null +++ b/infra/libkookie/overlays/kookie/emacs/theme/default.nix @@ -0,0 +1,6 @@ +{ buildModule, pkgs, epkgs }: +with epkgs; +(buildModule "theme" ./. [ + color-theme-sanityinc-tomorrow + color-identifiers-mode +])