├── .gitignore ├── README.md └── init.el /.gitignore: -------------------------------------------------------------------------------- 1 | /after-init.el 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A new way to manage Emacs 2 | 3 | I have been managing my Emacs config with packages for a few 4 | years. But I am finding 3 problems with it: 5 | 6 | 1. there is quite a lot of overhead in managing packages 7 | 2. I am sick of the complexity involved in moving my emacs around machines 8 | 3. I am worried about the security of packages that get updated and I don't review the updates 9 | 10 | This repository is my way of dealing with these problems. 11 | 12 | ## Solving the problems 13 | 14 | I don't aim to solve problem #1 particularly. There will always be overhead. 15 | 16 | But problem #2 and #3 seem related. 17 | 18 | I think the answer to packaging systems is really what golang has 19 | done. Source code repository based packaging. In brief this has the 20 | following properties: 21 | 22 | * one namespace is used for all packages, there is no per-project package namespace 23 | * packages are version controlled source repositories 24 | 25 | This has the following advantages: 26 | 27 | * it homogenizes into the VCS all the version control requirements 28 | * need two different versions of the same library for two different projects? they should be represented as two different branches in the same "package" 29 | * want to make a change to a package to faciltate something in a dependency? just change the source code and recompile 30 | * security can be handled by using VCS commits 31 | * you can approve the state of a project at a particular version and be confident that won't change 32 | * you can potentially share your trust of a particular commit 33 | 34 | This approach does not work well with Java, or other partially 35 | compiled lanaguages. But for both native compilation and dynamically 36 | compiled languages (like Python or EmacsLisp) it works well. 37 | 38 | -------------------------------------------------------------------------------- /init.el: -------------------------------------------------------------------------------- 1 | ;;; Nic's init file 2 | 3 | ;;; An attempt to make something that doesn't need so much work moving 4 | ;;; between machines 5 | 6 | (defconst emacs-repos "~/emacs-packages") 7 | 8 | (defmacro save-in-file (filename &rest body) 9 | "Save the Lisp BODY in the FILENAME." 10 | (declare (indent defun)) 11 | (let ((buffer (make-symbol "buf"))) 12 | `(let ((,buffer (find-file-noselect ,filename))) 13 | (with-current-buffer ,buffer 14 | (erase-buffer) 15 | (mapcar (lambda (f) 16 | (princ f (current-buffer)) 17 | (newline)) 18 | (quote ,body)) 19 | (save-buffer))))) 20 | 21 | ;; This is the stuff that will be executed after the loading. 22 | ;; Put stuff in here to get it to happen after packages and all that 23 | (save-in-file "after-init.el" 24 | ;; after the other stuff has been done this can be called 25 | (add-to-list 'auto-mode-alist '("Dockerfile" . shell-script-mode)) 26 | 27 | (require 'dired-x) 28 | (setq dired-omit-mode t) 29 | (setq dired-omit-files "^\\.?#\\|^\\.$\\|^\\.\\.$\\|^\\..*$") 30 | 31 | (setq shell-switcher-mode t) 32 | (define-key 33 | shell-switcher-mode-map 34 | (kbd "C-#") 'shell-switcher-switch-buffer) 35 | (define-key 36 | shell-switcher-mode-map 37 | (kbd "C-x 4 #") 'shell-switcher-switch-buffer-other-window) 38 | (define-key 39 | shell-switcher-mode-map 40 | (kbd "C-M-#") 'shell-switcher-new-shell) 41 | 42 | (setenv "GIT_PAGER" "cat") 43 | (setenv "PAGER" "cat") 44 | 45 | ;; Maybe this needs to go in JS mode hook 46 | (modify-syntax-entry ?` "\"" js-mode-syntax-table) 47 | 48 | (add-hook 'after-init-hook 'frame-font-keychord-init)) 49 | 50 | ;; Add the hook 51 | (add-hook 52 | 'after-init-hook 53 | (lambda () 54 | (condition-case err 55 | (load-file "~/.emacs.d/after-init.el") 56 | (error (message "errors during init"))))) 57 | 58 | 59 | (defconst emacs-load-paths '() 60 | "Alist of load-paths keyed by repo-name. 61 | 62 | The load-path before the repo was loaded.") 63 | 64 | (defun list-copy (l) (mapcar 'identity l)) 65 | 66 | (defun pp-list (l) 67 | "Pretty print the symbol that you supply." 68 | (interactive "S") 69 | (with-current-buffer (get-buffer-create "*pp-lisp*") 70 | (erase-buffer) 71 | (pp (eval l) (current-buffer)) 72 | (switch-to-buffer-other-window (current-buffer)))) 73 | 74 | (defun load-repo (repo-name) 75 | "Load the specified repo. 76 | Argument REPO-NAME the name of the repository to add." 77 | (let* ((dir (expand-file-name repo-name emacs-repos)) 78 | (entries (directory-files dir t ".*\\.el$"))) 79 | (mapc (lambda (entry) 80 | (let* ((plain-name (file-name-sans-extension entry)) 81 | (elc-name (expand-file-name (concat plain-name ".elc")))) 82 | (when (and 83 | (file-exists-p elc-name) 84 | (file-newer-than-file-p entry elc-name)) 85 | (byte-compile-file entry)) 86 | ;; backup the load-path 87 | (unless (assoc repo-name emacs-load-paths) 88 | (add-to-list 89 | 'emacs-load-paths 90 | (cons repo-name (list-copy load-path)))) 91 | ;; update the load-path 92 | (unless (memq dir load-path) 93 | (add-to-list 'load-path dir)) 94 | ;; Finally load the file 95 | (condition-case err 96 | (when (eq nil (string-match-p ".*/test[s]*.el[c]*$" plain-name)) 97 | ;;(update-file-autoloads entry) 98 | (load-file entry)) 99 | (error (message 100 | "init load-repo failed loading %s in %s with %s" 101 | (file-name-base entry) 102 | dir 103 | err))))) 104 | entries))) 105 | 106 | 107 | ;; Now load a bunch of packages 108 | 109 | (load-repo "paredit") 110 | (load-repo "go-mode.el") 111 | ;;(load-repo "goflymake") 112 | (load-repo "emacs-crystal-mode") 113 | (load-repo "yaml-mode") 114 | (load-repo "markdown-mode") 115 | (load-repo "sql-postgres") 116 | (load-repo "shell-switcher") 117 | (load-repo "nics-crystal") 118 | (load-repo "key-chord") 119 | (load-repo "emacs-framesize") 120 | 121 | (custom-set-variables 122 | ;; custom-set-variables was added by Custom. 123 | ;; If you edit it by hand, you could mess it up, so be careful. 124 | ;; Your init file should contain only one such instance. 125 | ;; If there is more than one, they won't work right. 126 | '(emacs-lisp-mode-hook 127 | (quote 128 | (eldoc-mode checkdoc-minor-mode paredit-mode show-paren-mode))) 129 | '(indent-tabs-mode nil) 130 | '(menu-bar-mode nil) 131 | '(tool-bar-mode nil) 132 | '(truncate-lines t)) 133 | (custom-set-faces 134 | ;; custom-set-faces was added by Custom. 135 | ;; If you edit it by hand, you could mess it up, so be careful. 136 | ;; Your init file should contain only one such instance. 137 | ;; If there is more than one, they won't work right. 138 | ) 139 | 140 | ;; end init.el 141 | --------------------------------------------------------------------------------