Compare commits
54 Commits
e2464c646b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a6ca502aa7 | |||
| d8f4d9138c | |||
| 30472f6567 | |||
| 685743ec83 | |||
|
|
28d44b4fe7 | ||
|
|
f08b02eadc | ||
|
|
ce8a2e3f00 | ||
|
|
00908de3b9 | ||
|
|
5cabe62116 | ||
|
|
df22269c99 | ||
|
|
314b8a1850 | ||
|
|
2fdc134822 | ||
| 34b25f2352 | |||
| 0f5a63df6d | |||
| ca9db9525f | |||
| 6f2f3b6bcd | |||
| cb26403326 | |||
| e4ad515ee6 | |||
| 5fd2116943 | |||
| 1c6858634d | |||
| 7c234b6a6e | |||
| cbd72df6af | |||
| e32b87f921 | |||
| 2b65287a62 | |||
| 672d44014f | |||
| 7a7b2c2c8b | |||
| f99504e8f0 | |||
| b8d1ff5f0d | |||
| 0e1507668e | |||
| 26913bece6 | |||
| 9cd88d6be9 | |||
| e6d295c1c2 | |||
| 6331f5b391 | |||
| 79a92571f8 | |||
| 24e47ff783 | |||
| 991a67a19b | |||
| 42484af1ec | |||
| 7526429b00 | |||
| b34f9ba071 | |||
| 02a86ef9b0 | |||
| 2d42287f34 | |||
| a556aca1f9 | |||
| c34b7252e4 | |||
| ca577acb05 | |||
| 96b3a0c66c | |||
| ad20935123 | |||
| 25a624f074 | |||
| 76150ffbb5 | |||
| f4eb08b0e6 | |||
| c0a6d46af8 | |||
| 997e583f84 | |||
| 2bb33dfc55 | |||
| a2f15991b6 | |||
| 935ce54376 |
33
.config.d/00-preserve-between-restarts.el
Normal file
33
.config.d/00-preserve-between-restarts.el
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
;;; 00-preserve-between-restarts.el --- -*- no-byte-compile: t; lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;;; Description:
|
||||||
|
;; This file contains some modes that allow the user to preserve their
|
||||||
|
;; session between restarts, such as recentf, savehist and save-place
|
||||||
|
;; modes. This file also includes global-auto-revert mode, which
|
||||||
|
;; automatically updates the contents of a buffer to reflect changes
|
||||||
|
;; made to the underlying file on disk.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
;; Auto-revert in Emacs is a feature that automatically updates the
|
||||||
|
;; contents of a buffer to reflect changes made to the underlying file
|
||||||
|
;; on disk.
|
||||||
|
(add-hook 'after-init-hook #'global-auto-revert-mode)
|
||||||
|
|
||||||
|
;; recentf is an Emacs package that maintains a list of recently
|
||||||
|
;; accessed files, making it easier to reopen files you have worked on
|
||||||
|
;; recently.
|
||||||
|
(add-hook 'after-init-hook #'recentf-mode)
|
||||||
|
|
||||||
|
;; savehist is an Emacs feature that preserves the minibuffer history between
|
||||||
|
;; sessions. It saves the history of inputs in the minibuffer, such as commands,
|
||||||
|
;; search strings, and other prompts, to a file. This allows users to retain
|
||||||
|
;; their minibuffer history across Emacs restarts.
|
||||||
|
(add-hook 'after-init-hook #'savehist-mode)
|
||||||
|
|
||||||
|
;; save-place-mode enables Emacs to remember the last location within a file
|
||||||
|
;; upon reopening. This feature is particularly beneficial for resuming work at
|
||||||
|
;; the precise point where you previously left off.
|
||||||
|
(add-hook 'after-init-hook #'save-place-mode)
|
||||||
|
|
||||||
|
;;; 00-preserve-between-restarts.el ends here
|
||||||
78
.config.d/05-basic.el
Normal file
78
.config.d/05-basic.el
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
;;; 05-basic.el --- Setup some basics. -*- no-byte-compile: t; lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;; This package provides a complete git integration
|
||||||
|
(use-package magit
|
||||||
|
:ensure t
|
||||||
|
:defer t
|
||||||
|
:commands (magit))
|
||||||
|
|
||||||
|
;; A must have for any NixOS user
|
||||||
|
(use-package direnv
|
||||||
|
:ensure t
|
||||||
|
:defer nil
|
||||||
|
:config (direnv-mode))
|
||||||
|
|
||||||
|
;; Sometimes, one must use multiple terminals.
|
||||||
|
(use-package multi-vterm
|
||||||
|
:ensure t
|
||||||
|
:defer t)
|
||||||
|
|
||||||
|
;; Setting this to true makes it so that Emacs saves existing clipboard text
|
||||||
|
;; into kill ring before replacing it.
|
||||||
|
(setq save-interprogram-paste-before-kill t)
|
||||||
|
|
||||||
|
;; Compile command allows to easily run noninteractive commands, among other
|
||||||
|
;; things, like, you know, compiling stuff.
|
||||||
|
(keymap-global-set "C-c l" 'compile)
|
||||||
|
(keymap-global-set "C-c C-l" 'recompile)
|
||||||
|
|
||||||
|
;; When set to true, dired will try to guess the target directory. Use this by
|
||||||
|
;; first splitting the window in two, selecting the destination in a new buffer,
|
||||||
|
;; and use 'C' to copy the file/directory.
|
||||||
|
(setq dired-dwim-target t)
|
||||||
|
|
||||||
|
;; As vterm requires a compiled part, on NixOS its installation is handled by
|
||||||
|
;; the system configuration. However, for some reason, after some update emacs
|
||||||
|
;; stopped loading it automatically. So, to remedy that, we load it if it was
|
||||||
|
;; not already loaded.
|
||||||
|
(unless (memq 'vterm features)
|
||||||
|
(load "vterm" t)
|
||||||
|
(unless (memq 'vterm features)
|
||||||
|
(message "Failed to load vterm. It is probably not installed.")))
|
||||||
|
|
||||||
|
;; This folder contains some custom libraries I wrote that could be loaded.
|
||||||
|
(add-to-list
|
||||||
|
'load-path
|
||||||
|
(expand-file-name
|
||||||
|
(concat minimal-emacs-user-directory "load")))
|
||||||
|
|
||||||
|
;; Add my input method to allow reverse-im to work properly with my keyboard
|
||||||
|
;; setup. It is defined in a library in the load directory, see above.
|
||||||
|
(register-input-method
|
||||||
|
"cyrillic-workman" "Russian" 'quail-use-package
|
||||||
|
"RUW@" "Russian (ЙЦУКЕН) input method simulating Workman keyboard"
|
||||||
|
"cyrillic-workman-input-method")
|
||||||
|
|
||||||
|
;; Reverse-IM creates additional bindings that allow usage of different input
|
||||||
|
;; methods without changing the keyboard layout (most of the time ,for example:
|
||||||
|
;; keybinds on russian layout will work with this package).
|
||||||
|
(use-package reverse-im
|
||||||
|
:ensure t
|
||||||
|
:defer nil)
|
||||||
|
|
||||||
|
(setq reverse-im-char-fold t) ; use lax matching
|
||||||
|
(setq reverse-im-read-char-advice-function #'reverse-im-read-char-include)
|
||||||
|
(setq reverse-im-input-methods '("cyrillic-workman")) ; translate these methods
|
||||||
|
|
||||||
|
(reverse-im-mode t)
|
||||||
|
|
||||||
|
;; Windmove family of commands allow easy navigation when there is more than two
|
||||||
|
;; buffers on screen. The bindings are the Vim movement commands with the
|
||||||
|
;; Control+Shift modifiers, adjusted for the workman layout and shifted a bit
|
||||||
|
;; down and to the left.
|
||||||
|
(keymap-global-set "C-S-k" #'windmove-left)
|
||||||
|
(keymap-global-set "C-S-l" #'windmove-down)
|
||||||
|
(keymap-global-set "C-<" #'windmove-up)
|
||||||
|
(keymap-global-set "C->" #'windmove-right)
|
||||||
|
|
||||||
|
;;; 05-basic.el ends here
|
||||||
81
.config.d/07-org.el
Normal file
81
.config.d/07-org.el
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
;;; 07-org.el --- Setup org-mode. -*- no-byte-compile: t; lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;;; Description:
|
||||||
|
;; This file contains the configuration for org mode and related packages.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
;; Org Mode the almighty
|
||||||
|
(use-package org
|
||||||
|
:ensure nil
|
||||||
|
:defer nil
|
||||||
|
:commands (org-mode)
|
||||||
|
:bind (:map org-mode-map
|
||||||
|
("C-c c" . org-fc-cloze-dwim)))
|
||||||
|
|
||||||
|
;; By default, LaTeX rendered in org is too small. This makes is 2 times bigger.
|
||||||
|
(setq org-format-latex-options (plist-put org-format-latex-options ':scale 2.0))
|
||||||
|
|
||||||
|
;; This is a package that helps use org to manage knowledge. As the name
|
||||||
|
;; suggests, it mimics the behavior of Roam Research.
|
||||||
|
(use-package org-roam
|
||||||
|
:ensure t
|
||||||
|
:defer t
|
||||||
|
:after org-roam
|
||||||
|
:commands (org-roam-node-insert
|
||||||
|
org-roam-node-find
|
||||||
|
org-roam-capture))
|
||||||
|
|
||||||
|
;; This package provides us with a *very* nice graph of our knowledge base in
|
||||||
|
;; our browser.
|
||||||
|
(use-package org-roam-ui
|
||||||
|
:ensure t
|
||||||
|
:defer t
|
||||||
|
:diminish (org-roam-ui-mode . "ORUI")
|
||||||
|
:diminish org-roam-ui-follow-mode
|
||||||
|
:commands (org-roam-ui-mode))
|
||||||
|
|
||||||
|
;; Auto Fill all org files.
|
||||||
|
(add-hook 'org-mode-hook 'auto-fill-mode)
|
||||||
|
|
||||||
|
;; Sometimes you gotta cite some sources, and that is where the bibliography
|
||||||
|
;; comes in.
|
||||||
|
(setq org-cite-global-bibliography
|
||||||
|
'("/home/dizzar/data2/Notes/references/bibliography.bib"))
|
||||||
|
|
||||||
|
;; This variable controls where org-roam will search for notes, and I store mine
|
||||||
|
;; here.
|
||||||
|
(setq org-roam-directory (file-truename "~/data2/Notes"))
|
||||||
|
|
||||||
|
;; This tells org-roam to sync notes with its index in the background.
|
||||||
|
(if (file-directory-p org-roam-directory)
|
||||||
|
(org-roam-db-autosync-mode)
|
||||||
|
(message "Org Roam directory (%s) does not exist. Autosync disabled." org-roam-directory))
|
||||||
|
|
||||||
|
(setq global-roam-map (make-sparse-keymap "Roam Keys"))
|
||||||
|
(global-set-key "\C-cr" global-roam-map)
|
||||||
|
(define-key global-roam-map "i" 'org-roam-node-insert)
|
||||||
|
(define-key global-roam-map "f" 'org-roam-node-find)
|
||||||
|
(define-key global-roam-map "c" 'org-roam-capture)
|
||||||
|
|
||||||
|
(setq global-org-map (make-sparse-keymap "Org Keys"))
|
||||||
|
(global-set-key "\C-co" global-org-map)
|
||||||
|
(define-key global-org-map "c" 'org-capture)
|
||||||
|
(define-key global-org-map "\C-c" 'org-capture)
|
||||||
|
|
||||||
|
(setq org-capture-templates
|
||||||
|
;; other capture templates
|
||||||
|
`(("s"
|
||||||
|
"Slipbox"
|
||||||
|
entry
|
||||||
|
(file
|
||||||
|
"~/data2/Notes/inbox.org")
|
||||||
|
"* %?\n")
|
||||||
|
("w"
|
||||||
|
"Sentence list"
|
||||||
|
plain
|
||||||
|
(file+headline
|
||||||
|
"~/data2/Notes/inbox.org" "Words")
|
||||||
|
#'tatoeba-get-capture-template)))
|
||||||
|
|
||||||
|
;;; 07-org.el ends here
|
||||||
182
.config.d/10-completion.el
Normal file
182
.config.d/10-completion.el
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
;;; 10-completion.el --- Setup completion. -*- no-byte-compile: t; lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;;; Description:
|
||||||
|
;; This file contains code setting up all the completion packages,
|
||||||
|
;; such as corfu, vertico, marginalia, orderless, etc.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
;; This package provides marginalia-mode which adds marginalia to the
|
||||||
|
;; minibuffer completions. Marginalia are marks or annotations placed
|
||||||
|
;; at the margin of the page of a book or in this case helpful
|
||||||
|
;; colorful annotations placed at the margin of the minibuffer for
|
||||||
|
;; your completion candidates.
|
||||||
|
(use-package marginalia
|
||||||
|
;; Marginalia allows Embark to offer you preconfigured actions in more contexts.
|
||||||
|
;; In addition to that, Marginalia also enhances Vertico by adding rich
|
||||||
|
;; annotations to the completion candidates displayed in Vertico's interface.
|
||||||
|
:ensure t
|
||||||
|
:defer t
|
||||||
|
:commands (marginalia-mode marginalia-cycle)
|
||||||
|
:hook (after-init . marginalia-mode)
|
||||||
|
:init
|
||||||
|
(define-key minibuffer-local-map "\M-A" 'marginalia-cycle))
|
||||||
|
|
||||||
|
;; Emacs Mini-Buffer Actions Rooted in Keymaps. Embark makes it easy
|
||||||
|
;; to choose a command to run based on what is near point, both during
|
||||||
|
;; a minibuffer completion session (in a way familiar to Helm or
|
||||||
|
;; Counsel users) and in normal buffers.
|
||||||
|
(use-package embark
|
||||||
|
;; Embark is an Emacs package that acts like a context menu, allowing
|
||||||
|
;; users to perform context-sensitive actions on selected items
|
||||||
|
;; directly from the completion interface.
|
||||||
|
:ensure t
|
||||||
|
:defer t
|
||||||
|
:commands (embark-act
|
||||||
|
embark-dwim
|
||||||
|
embark-export
|
||||||
|
embark-collect
|
||||||
|
embark-bindings
|
||||||
|
embark-prefix-help-command)
|
||||||
|
:bind
|
||||||
|
(("C-." . embark-act) ;; pick some comfortable binding
|
||||||
|
("C-;" . embark-dwim) ;; good alternative: M-.
|
||||||
|
("C-h B" . embark-bindings) ;; alternative for `describe-bindings'
|
||||||
|
:map embark-flymake-map
|
||||||
|
("a" . eglot-code-actions))
|
||||||
|
|
||||||
|
:init
|
||||||
|
(setq prefix-help-command #'embark-prefix-help-command)
|
||||||
|
|
||||||
|
:config
|
||||||
|
;; Hide the mode line of the Embark live/completions buffers
|
||||||
|
(add-to-list 'display-buffer-alist
|
||||||
|
'("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
|
||||||
|
nil
|
||||||
|
(window-parameters (mode-line-format . none))))
|
||||||
|
(push 'embark--allow-edit
|
||||||
|
(alist-get 'eglot-code-actions embark-target-injection-hooks))
|
||||||
|
(push 'embark--ignore-target
|
||||||
|
(alist-get 'eglot-code-actions embark-target-injection-hooks)))
|
||||||
|
|
||||||
|
;; This package provides some integrations between the emabrk and
|
||||||
|
;; consult packages.
|
||||||
|
(use-package embark-consult
|
||||||
|
:ensure t
|
||||||
|
:hook
|
||||||
|
(embark-collect-mode . consult-preview-at-point-mode))
|
||||||
|
|
||||||
|
;; Consulting completing-read. Consult provides search and navigation
|
||||||
|
;; commands based on the Emacs completion function
|
||||||
|
;; completing-read. Completion allows you to quickly select an item
|
||||||
|
;; from a list of candidates.
|
||||||
|
(use-package consult
|
||||||
|
:ensure t
|
||||||
|
:bind (;; C-c bindings in `mode-specific-map'
|
||||||
|
("C-c M-x" . consult-mode-command)
|
||||||
|
("C-c C-h" . consult-history)
|
||||||
|
("C-c k" . consult-kmacro)
|
||||||
|
("C-c m" . consult-man)
|
||||||
|
("C-c i" . consult-info)
|
||||||
|
([remap Info-search] . consult-info)
|
||||||
|
;; C-x bindings in `ctl-x-map'
|
||||||
|
("C-x M-:" . consult-complex-command)
|
||||||
|
("C-x b" . consult-buffer)
|
||||||
|
("C-x 4 b" . consult-buffer-other-window)
|
||||||
|
("C-x 5 b" . consult-buffer-other-frame)
|
||||||
|
("C-x t b" . consult-buffer-other-tab)
|
||||||
|
("C-x r b" . consult-bookmark)
|
||||||
|
("C-x p b" . consult-project-buffer)
|
||||||
|
;; Custom M-# bindings for fast register access
|
||||||
|
("M-#" . consult-register-load)
|
||||||
|
("M-'" . consult-register-store)
|
||||||
|
("C-M-#" . consult-register)
|
||||||
|
;; Other custom bindings
|
||||||
|
("M-y" . consult-yank-pop)
|
||||||
|
;; M-g bindings in `goto-map'
|
||||||
|
("M-g e" . consult-compile-error)
|
||||||
|
("M-g f" . consult-flymake)
|
||||||
|
("M-g g" . consult-goto-line)
|
||||||
|
("M-g M-g" . consult-goto-line)
|
||||||
|
("M-g o" . consult-outline)
|
||||||
|
("M-g m" . consult-mark)
|
||||||
|
("M-g k" . consult-global-mark)
|
||||||
|
("M-g i" . consult-imenu)
|
||||||
|
("M-g I" . consult-imenu-multi)
|
||||||
|
;; M-s bindings in `search-map'
|
||||||
|
("M-s d" . consult-find)
|
||||||
|
("M-s c" . consult-locate)
|
||||||
|
("M-s g" . consult-grep)
|
||||||
|
("M-s G" . consult-git-grep)
|
||||||
|
("M-s r" . consult-ripgrep)
|
||||||
|
("M-s l" . consult-line)
|
||||||
|
("M-s L" . consult-line-multi)
|
||||||
|
("M-s k" . consult-keep-lines)
|
||||||
|
("M-s u" . consult-focus-lines)
|
||||||
|
;; Isearch integration
|
||||||
|
("M-s e" . consult-isearch-history)
|
||||||
|
:map isearch-mode-map
|
||||||
|
("M-e" . consult-isearch-history)
|
||||||
|
("M-s e" . consult-isearch-history)
|
||||||
|
("M-s l" . consult-line)
|
||||||
|
("M-s L" . consult-line-multi)
|
||||||
|
;; Minibuffer history
|
||||||
|
:map minibuffer-local-map
|
||||||
|
("M-s" . consult-history)
|
||||||
|
("M-r" . consult-history))
|
||||||
|
|
||||||
|
;; Enable automatic preview at point in the *Completions* buffer.
|
||||||
|
:hook (completion-list-mode . consult-preview-at-point-mode)
|
||||||
|
|
||||||
|
:init
|
||||||
|
;; Optionally configure the register formatting. This improves the register
|
||||||
|
(setq register-preview-delay 0.5
|
||||||
|
register-preview-function #'consult-register-format)
|
||||||
|
|
||||||
|
;; Optionally tweak the register preview window.
|
||||||
|
(advice-add #'register-preview :override #'consult-register-window)
|
||||||
|
|
||||||
|
;; Use Consult to select xref locations with preview
|
||||||
|
(setq xref-show-xrefs-function #'consult-xref
|
||||||
|
xref-show-definitions-function #'consult-xref)
|
||||||
|
|
||||||
|
:config
|
||||||
|
(consult-customize
|
||||||
|
consult-theme :preview-key '(:debounce 0.2 any)
|
||||||
|
consult-ripgrep consult-git-grep consult-grep
|
||||||
|
consult-bookmark consult-recent-file consult-xref
|
||||||
|
consult-source-bookmark consult-source-file-register
|
||||||
|
consult-source-recent-file consult-source-project-recent-file
|
||||||
|
;; :preview-key "M-."
|
||||||
|
:preview-key '(:debounce 0.4 any))
|
||||||
|
(setq consult-narrow-key "<"))
|
||||||
|
|
||||||
|
(setq tab-always-indent 'complete) ;; Starts completion with TAB
|
||||||
|
|
||||||
|
(fido-mode -1)
|
||||||
|
(icomplete-mode)
|
||||||
|
(icomplete-vertical-mode)
|
||||||
|
|
||||||
|
(setq icomplete-delay-completions-threshold 0)
|
||||||
|
(setq icomplete-compute-delay 0)
|
||||||
|
(setq icomplete-show-matches-on-no-input t)
|
||||||
|
(setq icomplete-hide-common-prefix nil)
|
||||||
|
(setq icomplete-prospects-height 10)
|
||||||
|
(setq icomplete-separator " . ")
|
||||||
|
(setq icomplete-with-completion-tables t)
|
||||||
|
(setq icomplete-max-delay-chars 0)
|
||||||
|
(setq icomplete-scroll t)
|
||||||
|
|
||||||
|
(keymap-set icomplete-minibuffer-map "TAB" 'icomplete-force-complete)
|
||||||
|
(keymap-set icomplete-minibuffer-map "RET" 'icomplete-force-complete-and-exit)
|
||||||
|
(keymap-set icomplete-minibuffer-map "C-<return>" 'icomplete-fido-exit)
|
||||||
|
|
||||||
|
(setq completion-styles '(basic partial-completion initials flex emacs22))
|
||||||
|
(setq completion-auto-select t) ;; Show completion on first call
|
||||||
|
(setq completion-auto-help 'visible) ;; Display *Completions* upon first request
|
||||||
|
(setq completions-format 'one-column) ;; Use only one column
|
||||||
|
(setq completions-sort 'historical) ;; Order based on minibuffer history
|
||||||
|
(setq completions-max-height 15) ;; Limit completions to 10 (completions start at line 5)
|
||||||
|
(setq completion-ignore-case t)
|
||||||
|
|
||||||
|
;;; 10-completion.el ends here
|
||||||
52
.config.d/90-experimental.el
Normal file
52
.config.d/90-experimental.el
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
;;; 90-experimental.el --- Experimental packages -*- no-byte-compile: t; lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Author: iamtoaster
|
||||||
|
|
||||||
|
;; This file is not part of GNU Emacs
|
||||||
|
|
||||||
|
;; This program is free software: you can redistribute it and/or modify
|
||||||
|
;; it under the terms of the GNU General Public License as published by
|
||||||
|
;; the Free Software Foundation, either version 3 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; This program is distributed in the hope that it will be useful,
|
||||||
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
;; GNU General Public License for more details.
|
||||||
|
|
||||||
|
;; You should have received a copy of the GNU General Public License
|
||||||
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
;; This file contains experimental packages that may or may not make it to the
|
||||||
|
;; main configuration eventually.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
; Whisper should be available in path, so we overwrite the search function so
|
||||||
|
; that it takes the executable from there instead of the install directory.
|
||||||
|
(defun my-whisper--find-whispercpp-server ()
|
||||||
|
(executable-find "whisper-server"))
|
||||||
|
|
||||||
|
(use-package whisper
|
||||||
|
:defer t
|
||||||
|
:straight (whisper :type git
|
||||||
|
:host github
|
||||||
|
:repo "natrys/whisper.el"
|
||||||
|
:branch "master")
|
||||||
|
:init
|
||||||
|
(setq whisper-install-whispercpp nil)
|
||||||
|
:config
|
||||||
|
(setq whisper-quantize "q8_0"
|
||||||
|
whisper-model "large-v3-turbo"
|
||||||
|
whisper-language "auto"
|
||||||
|
whisper-server-mode 'local
|
||||||
|
whisper-server-baseurl "http://127.0.0.1:8642"
|
||||||
|
whisper-translate nil
|
||||||
|
whisper-use-threads (/ (num-processors) 2))
|
||||||
|
|
||||||
|
(advice-add 'whisper--find-whispercpp-server :override #'my-whisper--find-whispercpp-server))
|
||||||
|
|
||||||
|
(keymap-global-set "<f9>" #'whisper-run)
|
||||||
|
|
||||||
|
;;; 90-experimental.el ends here
|
||||||
48
.config.d/99-misc.el
Normal file
48
.config.d/99-misc.el
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
;;; 99-misc.el --- My miscellaneous functions. -*- no-byte-compile: t; lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;;; Description:
|
||||||
|
;; This file contains my miscellaneous functions and their key binding code.
|
||||||
|
;; Some of those functions were written by me, some of them are taken from the
|
||||||
|
;; internet.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(defun my-preview-macro-expansion (arg)
|
||||||
|
"Previews the expansion of a macro in a temporary window.
|
||||||
|
|
||||||
|
If the prefix argument ARG is non-nil, a full recursive
|
||||||
|
macroexpansion (`macroexpand-all') will we performed, otherwise only one
|
||||||
|
macroexpansion step (`macroexpand-1') will be done.
|
||||||
|
|
||||||
|
If there is an active region selected, only its contents will be read
|
||||||
|
for the expansion. See also `pp-macroexpand-expression'."
|
||||||
|
(interactive "P")
|
||||||
|
(let ((obj))
|
||||||
|
(if (use-region-p)
|
||||||
|
(setq obj
|
||||||
|
(with-demoted-errors
|
||||||
|
"Failed to read form: %S"
|
||||||
|
(read (buffer-substring (region-beginning) (region-end)))))
|
||||||
|
(save-excursion
|
||||||
|
(setq obj (with-demoted-errors
|
||||||
|
"Failed to read form: %S"
|
||||||
|
(read (current-buffer))))))
|
||||||
|
(if obj
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(with-current-buffer-window "*Macro Expansion*" nil nil
|
||||||
|
(if arg
|
||||||
|
(pp (macroexpand-all obj))
|
||||||
|
(pp (macroexpand-1 obj)))
|
||||||
|
(emacs-lisp-mode)
|
||||||
|
(keymap-local-set (kbd "q") #'quit-window))
|
||||||
|
(select-window (get-buffer-window "*Macro Expansion*"))))))
|
||||||
|
|
||||||
|
(with-eval-after-load 'embark
|
||||||
|
(setq embark-pre-action-hooks
|
||||||
|
(add-to-list 'embark-pre-action-hooks '(my-preview-macro-expansion embark--beginning-of-target)))
|
||||||
|
(keymap-set embark-expression-map "m" 'my-preview-macro-expansion)
|
||||||
|
(keymap-set embark-expression-map "M" 'pp-macroexpand-expression)
|
||||||
|
(keymap-set embark-defun-map "m" 'my-preview-macro-expansion)
|
||||||
|
(keymap-set embark-defun-map "M" 'pp-macroexpand-expression))
|
||||||
|
|
||||||
|
;;; 99-misc.el ends here
|
||||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -4,3 +4,12 @@
|
|||||||
!init.el
|
!init.el
|
||||||
!.github/
|
!.github/
|
||||||
!.LICENSE
|
!.LICENSE
|
||||||
|
!custom.el
|
||||||
|
!pre-early-init.el
|
||||||
|
!post-init.el
|
||||||
|
!.config.d/
|
||||||
|
!.config.d/*.el
|
||||||
|
!templates
|
||||||
|
!load/
|
||||||
|
!load/*.el
|
||||||
|
*.elc
|
||||||
|
|||||||
BIN
.images/screenshot.png
Normal file
BIN
.images/screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
82
README.md
82
README.md
@@ -1,21 +1,15 @@
|
|||||||
|
# iamtoaster Emacs dotfiles
|
||||||
|
|
||||||
# *minimal-emacs.d* - A Customizable Emacs `init.el` and `early-init.el` for Better Defaults and Optimized Startup
|
# *minimal-emacs.d* - A Customizable Emacs `init.el` and `early-init.el` for Better Defaults and Optimized Startup
|
||||||

|

|
||||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||||

|

|
||||||
|
|
||||||
## Introduction
|
My dotfiles are based on the [minimal-emacs.d](https://github.com/jamescherti/minimal-emacs.d) project. The changes to the source repository will sometimes be synced to this repository, with my own changes being rebased on top.
|
||||||
|
|
||||||
The **minimal-emacs.d** project is a **fast and lightweight** minimal Emacs starter kit (`init.el` and `early-init.el`) that **gives you full control over your configuration**. It provides better defaults, an optimized startup, and a clean foundation for building your own vanilla Emacs setup.
|

|
||||||
|
|
||||||
Each setting in minimal-emacs.d is carefully chosen to answer this question: does it provide a better default that modernizes Emacs while keeping it lightweight, fast and stable?
|
The original repository contains a lot of useful info, so do check it out.
|
||||||
|
|
||||||
In just a few minutes of applying what's in this README.md file, you will have a fully functional, high-performance Emacs configuration ready for work. You will bypass hours of configuration and the heavy overhead of frameworks like Doom or Spacemacs, gaining access to optimized garbage collection, sensible defaults, and a fast startup.
|
|
||||||
|
|
||||||
If this helps your workflow, please show your support by **⭐ starring minimal-emacs.d on GitHub** to help more Emacs users discover its benefits.
|
|
||||||
|
|
||||||
**Ready to start? [Install minimal-emacs.d](#install-minimal-emacsd)**
|
|
||||||
|
|
||||||
Building the *minimal-emacs.d* `init.el` and `early-init.el` was the result of **extensive research and testing** to fine-tune the best parameters and optimizations for an Emacs configuration. *(More information about the *minimal-emacs.d* features can be found here: [Features](#features).)*
|
|
||||||
|
|
||||||
### Looking for the ideal starter kit to customize Emacs?
|
### Looking for the ideal starter kit to customize Emacs?
|
||||||
|
|
||||||
@@ -46,7 +40,10 @@ Excluding empty lines, comments, and docstrings, the minimal-emacs.d configurati
|
|||||||
|
|
||||||
The author uses *minimal-emacs.d* as his `early-init.el` and `init.el`, alongside **146 packages** ([See the packages that the author is using here](https://www.jamescherti.com/essential-emacs-packages/)). Yet, thanks to its efficient design, Emacs still **starts in just 0.22 seconds**:
|
The author uses *minimal-emacs.d* as his `early-init.el` and `init.el`, alongside **146 packages** ([See the packages that the author is using here](https://www.jamescherti.com/essential-emacs-packages/)). Yet, thanks to its efficient design, Emacs still **starts in just 0.22 seconds**:
|
||||||
|
|
||||||

|
Author of [minimal-emacs.d](https://github.com/jamescherti/minimal-emacs.d) suggests putting (almost) everything into the post-init.el file, which I simply do not agree with. I am used to using plug-in files, with the main one only having the bare minimum of content.
|
||||||
|
|
||||||
|
As such, post-init.el file only contains the minimal setup code, and at the end loads the files in the `.config.d` folder, in alphanumeric order. In those plug-in files the real magic happens. All the files are heavily documented, with mostly self-explanatory names, so I think it will be redundant to list them here. See the files in `config.d` directory for more.
|
||||||
|
|
||||||
|
|
||||||
Startup speed depends on hardware and disk speed. For consistent comparisons, test on the same computer and Emacs version. While startup time is significant, factors like native compilation are also important for long-term performance.
|
Startup speed depends on hardware and disk speed. For consistent comparisons, test on the same computer and Emacs version. While startup time is significant, factors like native compilation are also important for long-term performance.
|
||||||
|
|
||||||
@@ -69,6 +66,8 @@ Startup speed depends on hardware and disk speed. For consistent comparisons, te
|
|||||||
- [jeenajeena on Reddit](https://www.reddit.com/r/emacs/comments/1p9y8h4/comment/nrfk13i/): "Thank you. Plenty of inspiring settings. Worth to be read line by line."
|
- [jeenajeena on Reddit](https://www.reddit.com/r/emacs/comments/1p9y8h4/comment/nrfk13i/): "Thank you. Plenty of inspiring settings. Worth to be read line by line."
|
||||||
- [uutangohotel on Reddit](https://www.reddit.com/r/emacs/comments/1p9y8h4/comment/nrg5kja/): "I get a lot out of minimal-emacs.d — thank you! I use stow to manage my dotfiles in a git repo. I created a submodule in one dir for minimal-emacs.d and another for my “overrides”, e.g. post-init.el. Easy and works great."
|
- [uutangohotel on Reddit](https://www.reddit.com/r/emacs/comments/1p9y8h4/comment/nrg5kja/): "I get a lot out of minimal-emacs.d — thank you! I use stow to manage my dotfiles in a git repo. I created a submodule in one dir for minimal-emacs.d and another for my “overrides”, e.g. post-init.el. Easy and works great."
|
||||||
- [sunng on Reddit](https://www.reddit.com/r/emacs/comments/1p9y8h4/comment/ns1nehi/): "Nice work! I just created a nix flake to using it on my dev servers"
|
- [sunng on Reddit](https://www.reddit.com/r/emacs/comments/1p9y8h4/comment/ns1nehi/): "Nice work! I just created a nix flake to using it on my dev servers"
|
||||||
|
- [zackattackz287 on Reddit](https://www.reddit.com/r/emacs/comments/1rsmaut/comment/oa8okca/): "Congrats and thank you (and the community around minimal.d) for your work! I've been using it for quite a while now and I've not ever had any breakages when merging changes from main..."
|
||||||
|
- [utility on Reddit](https://www.reddit.com/r/emacs/comments/1rsmaut/comment/oa8wrap/): "Excellent. I use this and I'm very happy with it!"
|
||||||
|
|
||||||
Please share your configuration. It could serve as inspiration for other users.
|
Please share your configuration. It could serve as inspiration for other users.
|
||||||
|
|
||||||
@@ -290,7 +289,6 @@ Native compilation enhances Emacs performance by converting Elisp code into nati
|
|||||||
;; Ensure adding the following compile-angel code at the very beginning
|
;; Ensure adding the following compile-angel code at the very beginning
|
||||||
;; of your `~/.emacs.d/post-init.el` file, before all other packages.
|
;; of your `~/.emacs.d/post-init.el` file, before all other packages.
|
||||||
(use-package compile-angel
|
(use-package compile-angel
|
||||||
:ensure t
|
|
||||||
:demand t
|
:demand t
|
||||||
:config
|
:config
|
||||||
;; The following disables compilation of packages during installation;
|
;; The following disables compilation of packages during installation;
|
||||||
@@ -334,7 +332,6 @@ To fix this, add **exec-path-from-shell** to `~/.emacs.d/post-init.el`:
|
|||||||
(use-package exec-path-from-shell
|
(use-package exec-path-from-shell
|
||||||
:if (and (or (display-graphic-p) (daemonp))
|
:if (and (or (display-graphic-p) (daemonp))
|
||||||
(eq system-type 'darwin)) ; macOS only
|
(eq system-type 'darwin)) ; macOS only
|
||||||
:ensure t
|
|
||||||
:demand t
|
:demand t
|
||||||
:functions exec-path-from-shell-initialize
|
:functions exec-path-from-shell-initialize
|
||||||
:config
|
:config
|
||||||
@@ -365,11 +362,11 @@ The recentf, savehist, saveplace, and auto-revert built-in packages are already
|
|||||||
:hook
|
:hook
|
||||||
(after-init . global-auto-revert-mode)
|
(after-init . global-auto-revert-mode)
|
||||||
:init
|
:init
|
||||||
|
;; (setq auto-revert-verbose t)
|
||||||
(setq auto-revert-interval 3)
|
(setq auto-revert-interval 3)
|
||||||
(setq auto-revert-remote-files nil)
|
(setq auto-revert-remote-files nil)
|
||||||
(setq auto-revert-use-notify t)
|
(setq auto-revert-use-notify t)
|
||||||
(setq auto-revert-avoid-polling nil)
|
(setq auto-revert-avoid-polling nil))
|
||||||
(setq auto-revert-verbose t))
|
|
||||||
|
|
||||||
;; Recentf is an Emacs package that maintains a list of recently
|
;; Recentf is an Emacs package that maintains a list of recently
|
||||||
;; accessed files, making it easier to reopen files you have worked on
|
;; accessed files, making it easier to reopen files you have worked on
|
||||||
@@ -476,7 +473,6 @@ To configure `corfu` and `cape`, add the following to `~/.emacs.d/post-init.el`:
|
|||||||
;; current candidates, positioned either below or above the point. Candidates
|
;; current candidates, positioned either below or above the point. Candidates
|
||||||
;; can be selected by navigating up or down.
|
;; can be selected by navigating up or down.
|
||||||
(use-package corfu
|
(use-package corfu
|
||||||
:ensure t
|
|
||||||
:commands (corfu-mode global-corfu-mode)
|
:commands (corfu-mode global-corfu-mode)
|
||||||
|
|
||||||
:hook ((prog-mode . corfu-mode)
|
:hook ((prog-mode . corfu-mode)
|
||||||
@@ -498,7 +494,6 @@ To configure `corfu` and `cape`, add the following to `~/.emacs.d/post-init.el`:
|
|||||||
;; in-buffer completion. It integrates with Corfu or the default completion UI,
|
;; in-buffer completion. It integrates with Corfu or the default completion UI,
|
||||||
;; by providing additional backends through completion-at-point-functions.
|
;; by providing additional backends through completion-at-point-functions.
|
||||||
(use-package cape
|
(use-package cape
|
||||||
:ensure t
|
|
||||||
:commands (cape-dabbrev cape-file cape-elisp-block)
|
:commands (cape-dabbrev cape-file cape-elisp-block)
|
||||||
:bind ("C-c p" . cape-prefix-map)
|
:bind ("C-c p" . cape-prefix-map)
|
||||||
:init
|
:init
|
||||||
@@ -527,7 +522,6 @@ Add the following to `~/.emacs.d/post-init.el` to set up Vertico, Consult, and E
|
|||||||
;; navigate and select from completion candidates (e.g., when `M-x` is pressed).
|
;; navigate and select from completion candidates (e.g., when `M-x` is pressed).
|
||||||
(use-package vertico
|
(use-package vertico
|
||||||
;; (Note: It is recommended to also enable the savehist package.)
|
;; (Note: It is recommended to also enable the savehist package.)
|
||||||
:ensure t
|
|
||||||
:config
|
:config
|
||||||
(vertico-mode))
|
(vertico-mode))
|
||||||
|
|
||||||
@@ -535,7 +529,6 @@ Add the following to `~/.emacs.d/post-init.el` to set up Vertico, Consult, and E
|
|||||||
;; to input multiple patterns separated by spaces, which Orderless then
|
;; to input multiple patterns separated by spaces, which Orderless then
|
||||||
;; matches in any order against the candidates.
|
;; matches in any order against the candidates.
|
||||||
(use-package orderless
|
(use-package orderless
|
||||||
:ensure t
|
|
||||||
:custom
|
:custom
|
||||||
(completion-styles '(orderless basic))
|
(completion-styles '(orderless basic))
|
||||||
(completion-category-defaults nil)
|
(completion-category-defaults nil)
|
||||||
@@ -545,7 +538,6 @@ Add the following to `~/.emacs.d/post-init.el` to set up Vertico, Consult, and E
|
|||||||
;; In addition to that, Marginalia also enhances Vertico by adding rich
|
;; In addition to that, Marginalia also enhances Vertico by adding rich
|
||||||
;; annotations to the completion candidates displayed in Vertico's interface.
|
;; annotations to the completion candidates displayed in Vertico's interface.
|
||||||
(use-package marginalia
|
(use-package marginalia
|
||||||
:ensure t
|
|
||||||
:commands (marginalia-mode marginalia-cycle)
|
:commands (marginalia-mode marginalia-cycle)
|
||||||
:hook (after-init . marginalia-mode))
|
:hook (after-init . marginalia-mode))
|
||||||
|
|
||||||
@@ -557,7 +549,6 @@ Add the following to `~/.emacs.d/post-init.el` to set up Vertico, Consult, and E
|
|||||||
;; Embark is an Emacs package that acts like a context menu, allowing
|
;; Embark is an Emacs package that acts like a context menu, allowing
|
||||||
;; users to perform context-sensitive actions on selected items
|
;; users to perform context-sensitive actions on selected items
|
||||||
;; directly from the completion interface.
|
;; directly from the completion interface.
|
||||||
:ensure t
|
|
||||||
:commands (embark-act
|
:commands (embark-act
|
||||||
embark-dwim
|
embark-dwim
|
||||||
embark-export
|
embark-export
|
||||||
@@ -580,14 +571,12 @@ Add the following to `~/.emacs.d/post-init.el` to set up Vertico, Consult, and E
|
|||||||
(window-parameters (mode-line-format . none)))))
|
(window-parameters (mode-line-format . none)))))
|
||||||
|
|
||||||
(use-package embark-consult
|
(use-package embark-consult
|
||||||
:ensure t
|
|
||||||
:hook
|
:hook
|
||||||
(embark-collect-mode . consult-preview-at-point-mode))
|
(embark-collect-mode . consult-preview-at-point-mode))
|
||||||
|
|
||||||
;; Consult offers a suite of commands for efficient searching, previewing, and
|
;; Consult offers a suite of commands for efficient searching, previewing, and
|
||||||
;; interacting with buffers, file contents, and more, improving various tasks.
|
;; interacting with buffers, file contents, and more, improving various tasks.
|
||||||
(use-package consult
|
(use-package consult
|
||||||
:ensure t
|
|
||||||
:bind (;; C-c bindings in `mode-specific-map'
|
:bind (;; C-c bindings in `mode-specific-map'
|
||||||
("C-c M-x" . consult-mode-command)
|
("C-c M-x" . consult-mode-command)
|
||||||
("C-c h" . consult-history)
|
("C-c h" . consult-history)
|
||||||
@@ -693,7 +682,6 @@ To install and configure these packages, add the following to `~/.emacs.d/post-i
|
|||||||
;; The undo-fu package is a lightweight wrapper around Emacs' built-in undo
|
;; The undo-fu package is a lightweight wrapper around Emacs' built-in undo
|
||||||
;; system, providing more convenient undo/redo functionality.
|
;; system, providing more convenient undo/redo functionality.
|
||||||
(use-package undo-fu
|
(use-package undo-fu
|
||||||
:ensure t
|
|
||||||
:commands (undo-fu-only-undo
|
:commands (undo-fu-only-undo
|
||||||
undo-fu-only-redo
|
undo-fu-only-redo
|
||||||
undo-fu-only-redo-all
|
undo-fu-only-redo-all
|
||||||
@@ -706,7 +694,6 @@ To install and configure these packages, add the following to `~/.emacs.d/post-i
|
|||||||
;; The undo-fu-session package complements undo-fu by enabling the saving
|
;; The undo-fu-session package complements undo-fu by enabling the saving
|
||||||
;; and restoration of undo history across Emacs sessions, even after restarting.
|
;; and restoration of undo history across Emacs sessions, even after restarting.
|
||||||
(use-package undo-fu-session
|
(use-package undo-fu-session
|
||||||
:ensure t
|
|
||||||
:commands undo-fu-session-global-mode
|
:commands undo-fu-session-global-mode
|
||||||
:hook (after-init . undo-fu-session-global-mode))
|
:hook (after-init . undo-fu-session-global-mode))
|
||||||
```
|
```
|
||||||
@@ -768,7 +755,6 @@ Configuring Vim keybindings in Emacs can greatly enhance your editing efficiency
|
|||||||
|
|
||||||
;; Vim emulation
|
;; Vim emulation
|
||||||
(use-package evil
|
(use-package evil
|
||||||
:ensure t
|
|
||||||
:commands (evil-mode evil-define-key)
|
:commands (evil-mode evil-define-key)
|
||||||
:hook (after-init . evil-mode)
|
:hook (after-init . evil-mode)
|
||||||
|
|
||||||
@@ -809,7 +795,6 @@ Configuring Vim keybindings in Emacs can greatly enhance your editing efficiency
|
|||||||
|
|
||||||
(use-package evil-collection
|
(use-package evil-collection
|
||||||
:after evil
|
:after evil
|
||||||
:ensure t
|
|
||||||
:init
|
:init
|
||||||
;; It has to be defined before evil-colllection
|
;; It has to be defined before evil-colllection
|
||||||
(setq evil-collection-setup-minibuffer t)
|
(setq evil-collection-setup-minibuffer t)
|
||||||
@@ -830,7 +815,6 @@ You can also install the [vim-tab-bar](https://github.com/jamescherti/vim-tab-ba
|
|||||||
``` emacs-lisp
|
``` emacs-lisp
|
||||||
;; Give Emacs tab-bar a style similar to Vim's
|
;; Give Emacs tab-bar a style similar to Vim's
|
||||||
(use-package vim-tab-bar
|
(use-package vim-tab-bar
|
||||||
:ensure t
|
|
||||||
:commands vim-tab-bar-mode
|
:commands vim-tab-bar-mode
|
||||||
:hook (after-init . vim-tab-bar-mode))
|
:hook (after-init . vim-tab-bar-mode))
|
||||||
```
|
```
|
||||||
@@ -848,7 +832,6 @@ The `evil-surround` package simplifies handling surrounding characters, such as
|
|||||||
;; using S" or gS".
|
;; using S" or gS".
|
||||||
(use-package evil-surround
|
(use-package evil-surround
|
||||||
:after evil
|
:after evil
|
||||||
:ensure t
|
|
||||||
:commands global-evil-surround-mode
|
:commands global-evil-surround-mode
|
||||||
:custom
|
:custom
|
||||||
(evil-surround-pairs-alist
|
(evil-surround-pairs-alist
|
||||||
@@ -894,7 +877,6 @@ To configure **easysession**, add the following to `~/.emacs.d/post-init.el`:
|
|||||||
;; manage Emacs editing sessions and utilizes built-in Emacs functions to
|
;; manage Emacs editing sessions and utilizes built-in Emacs functions to
|
||||||
;; persist and restore frames.
|
;; persist and restore frames.
|
||||||
(use-package easysession
|
(use-package easysession
|
||||||
:ensure t
|
|
||||||
:commands (easysession-switch-to
|
:commands (easysession-switch-to
|
||||||
easysession-save-as
|
easysession-save-as
|
||||||
easysession-save-mode
|
easysession-save-mode
|
||||||
@@ -959,7 +941,6 @@ This configuration sets up `markdown-mode` with deferred loading to improve star
|
|||||||
```elisp
|
```elisp
|
||||||
;; Automatically generate a table of contents when editing Markdown files
|
;; Automatically generate a table of contents when editing Markdown files
|
||||||
(use-package markdown-toc
|
(use-package markdown-toc
|
||||||
:ensure t
|
|
||||||
:commands (markdown-toc-generate-toc
|
:commands (markdown-toc-generate-toc
|
||||||
markdown-toc-generate-or-refresh-toc
|
markdown-toc-generate-or-refresh-toc
|
||||||
markdown-toc-delete-toc
|
markdown-toc-delete-toc
|
||||||
@@ -1075,7 +1056,6 @@ For folding based on indentation levels, the **[outline-indent](https://github.c
|
|||||||
;; - Move backward/forward to the indentation level of the current line
|
;; - Move backward/forward to the indentation level of the current line
|
||||||
;; - and other features.
|
;; - and other features.
|
||||||
(use-package outline-indent
|
(use-package outline-indent
|
||||||
:ensure t
|
|
||||||
:commands outline-indent-minor-mode
|
:commands outline-indent-minor-mode
|
||||||
|
|
||||||
:custom
|
:custom
|
||||||
@@ -1144,7 +1124,6 @@ To configure **apheleia**, add the following to `~/.emacs.d/post-init.el`:
|
|||||||
;; Apheleia is an Emacs package designed to run code formatters (e.g., Shfmt,
|
;; Apheleia is an Emacs package designed to run code formatters (e.g., Shfmt,
|
||||||
;; Black and Prettier) asynchronously without disrupting the cursor position.
|
;; Black and Prettier) asynchronously without disrupting the cursor position.
|
||||||
(use-package apheleia
|
(use-package apheleia
|
||||||
:ensure t
|
|
||||||
:commands (apheleia-mode
|
:commands (apheleia-mode
|
||||||
apheleia-global-mode)
|
apheleia-global-mode)
|
||||||
:hook ((prog-mode . apheleia-mode)))
|
:hook ((prog-mode . apheleia-mode)))
|
||||||
@@ -1199,7 +1178,6 @@ The [yasnippet-snippets](https://github.com/AndreaCrotti/yasnippet-snippets) pac
|
|||||||
```elisp
|
```elisp
|
||||||
;; The official collection of snippets for yasnippet.
|
;; The official collection of snippets for yasnippet.
|
||||||
(use-package yasnippet-snippets
|
(use-package yasnippet-snippets
|
||||||
:ensure t
|
|
||||||
:after yasnippet)
|
:after yasnippet)
|
||||||
|
|
||||||
;; YASnippet is a template system designed that enhances text editing by
|
;; YASnippet is a template system designed that enhances text editing by
|
||||||
@@ -1207,7 +1185,6 @@ The [yasnippet-snippets](https://github.com/AndreaCrotti/yasnippet-snippets) pac
|
|||||||
;; abbreviation, YASnippet automatically expands it into a full template, which
|
;; abbreviation, YASnippet automatically expands it into a full template, which
|
||||||
;; can include placeholders, fields, and dynamic content.
|
;; can include placeholders, fields, and dynamic content.
|
||||||
(use-package yasnippet
|
(use-package yasnippet
|
||||||
:ensure t
|
|
||||||
:commands (yas-minor-mode
|
:commands (yas-minor-mode
|
||||||
yas-global-mode)
|
yas-global-mode)
|
||||||
|
|
||||||
@@ -1307,7 +1284,6 @@ To enable **stripspace** and automatically delete trailing whitespace, add the f
|
|||||||
;; that automatically removes trailing whitespace and blank lines at the end of
|
;; that automatically removes trailing whitespace and blank lines at the end of
|
||||||
;; the buffer when saving.
|
;; the buffer when saving.
|
||||||
(use-package stripspace
|
(use-package stripspace
|
||||||
:ensure t
|
|
||||||
:commands stripspace-local-mode
|
:commands stripspace-local-mode
|
||||||
|
|
||||||
;; Enable for prog-mode-hook, text-mode-hook, conf-mode-hook
|
;; Enable for prog-mode-hook, text-mode-hook, conf-mode-hook
|
||||||
@@ -1362,7 +1338,6 @@ To configure **org-mode**, add the following to `~/.emacs.d/post-init.el`:
|
|||||||
;; scheduling, deadlines, time tracking, and exporting to multiple formats
|
;; scheduling, deadlines, time tracking, and exporting to multiple formats
|
||||||
;; including HTML, LaTeX, PDF, and Markdown.
|
;; including HTML, LaTeX, PDF, and Markdown.
|
||||||
(use-package org
|
(use-package org
|
||||||
:ensure t
|
|
||||||
:commands (org-mode org-version)
|
:commands (org-mode org-version)
|
||||||
:mode
|
:mode
|
||||||
("\\.org\\'" . org-mode)
|
("\\.org\\'" . org-mode)
|
||||||
@@ -1432,7 +1407,6 @@ To configure **auto-package-update**, add the following to `~/.emacs.d/post-init
|
|||||||
```elisp
|
```elisp
|
||||||
;; This automates the process of updating installed packages
|
;; This automates the process of updating installed packages
|
||||||
(use-package auto-package-update
|
(use-package auto-package-update
|
||||||
:ensure t
|
|
||||||
:custom
|
:custom
|
||||||
;; Set the number of days between automatic updates.
|
;; Set the number of days between automatic updates.
|
||||||
;; Here, packages will only be updated if at least 7 days have passed
|
;; Here, packages will only be updated if at least 7 days have passed
|
||||||
@@ -1477,7 +1451,6 @@ To configure **buffer-terminator**, add the following to `~/.emacs.d/post-init.e
|
|||||||
|
|
||||||
```emacs-lisp
|
```emacs-lisp
|
||||||
(use-package buffer-terminator
|
(use-package buffer-terminator
|
||||||
:ensure t
|
|
||||||
:custom
|
:custom
|
||||||
;; Enable/Disable verbose mode to log buffer cleanup events
|
;; Enable/Disable verbose mode to log buffer cleanup events
|
||||||
(buffer-terminator-verbose nil)
|
(buffer-terminator-verbose nil)
|
||||||
@@ -1509,7 +1482,6 @@ To configure **treemacs**, add the following to `~/.emacs.d/post-init.el`:
|
|||||||
;; in the left window, providing a persistent view of files, projects, and
|
;; in the left window, providing a persistent view of files, projects, and
|
||||||
;; other elements.
|
;; other elements.
|
||||||
(use-package treemacs
|
(use-package treemacs
|
||||||
:ensure t
|
|
||||||
:commands (treemacs
|
:commands (treemacs
|
||||||
treemacs-select-window
|
treemacs-select-window
|
||||||
treemacs-delete-other-windows
|
treemacs-delete-other-windows
|
||||||
@@ -1609,15 +1581,12 @@ To configure **treemacs**, add the following to `~/.emacs.d/post-init.el`:
|
|||||||
|
|
||||||
;; (use-package treemacs-evil
|
;; (use-package treemacs-evil
|
||||||
;; :after (treemacs evil)
|
;; :after (treemacs evil)
|
||||||
;; :ensure t)
|
|
||||||
;;
|
;;
|
||||||
;; (use-package treemacs-icons-dired
|
;; (use-package treemacs-icons-dired
|
||||||
;; :hook (dired-mode . treemacs-icons-dired-enable-once)
|
;; :hook (dired-mode . treemacs-icons-dired-enable-once)
|
||||||
;; :ensure t)
|
|
||||||
;;
|
;;
|
||||||
;; (use-package treemacs-tab-bar ; treemacs-tab-bar if you use tab-bar-mode
|
;; (use-package treemacs-tab-bar ; treemacs-tab-bar if you use tab-bar-mode
|
||||||
;; :after (treemacs)
|
;; :after (treemacs)
|
||||||
;; :ensure t
|
|
||||||
;; :config (treemacs-set-scope-type 'Tabs))
|
;; :config (treemacs-set-scope-type 'Tabs))
|
||||||
;;
|
;;
|
||||||
;; (treemacs-start-on-boot)
|
;; (treemacs-start-on-boot)
|
||||||
@@ -1632,7 +1601,6 @@ To configure **helpful**, add the following to `~/.emacs.d/post-init.el`:
|
|||||||
;; Helpful is an alternative to the built-in Emacs help that provides much more
|
;; Helpful is an alternative to the built-in Emacs help that provides much more
|
||||||
;; contextual information.
|
;; contextual information.
|
||||||
(use-package helpful
|
(use-package helpful
|
||||||
:ensure t
|
|
||||||
:commands (helpful-callable
|
:commands (helpful-callable
|
||||||
helpful-variable
|
helpful-variable
|
||||||
helpful-key
|
helpful-key
|
||||||
@@ -1658,7 +1626,6 @@ It operates by generating a dynamic, temporary mapping: upon invocation, such as
|
|||||||
To configure **avy**, add the following to `~/.emacs.d/post-init.el`:
|
To configure **avy**, add the following to `~/.emacs.d/post-init.el`:
|
||||||
```elisp
|
```elisp
|
||||||
(use-package avy
|
(use-package avy
|
||||||
:ensure t
|
|
||||||
:commands (avy-goto-char
|
:commands (avy-goto-char
|
||||||
avy-goto-char-2
|
avy-goto-char-2
|
||||||
avy-next)
|
avy-next)
|
||||||
@@ -1680,7 +1647,6 @@ The functions above also ensures that any modified buffers are saved prior to ex
|
|||||||
To configure **bufferfile**, add the following to `~/.emacs.d/post-init.el`:
|
To configure **bufferfile**, add the following to `~/.emacs.d/post-init.el`:
|
||||||
```elisp
|
```elisp
|
||||||
(use-package bufferfile
|
(use-package bufferfile
|
||||||
:ensure t
|
|
||||||
:commands (bufferfile-copy
|
:commands (bufferfile-copy
|
||||||
bufferfile-rename
|
bufferfile-rename
|
||||||
bufferfile-delete)
|
bufferfile-delete)
|
||||||
@@ -1708,14 +1674,12 @@ To enhance the Elisp development experience, add the following to `~/.emacs.d/po
|
|||||||
```emacs-lisp
|
```emacs-lisp
|
||||||
;; Enables automatic indentation of code while typing
|
;; Enables automatic indentation of code while typing
|
||||||
(use-package aggressive-indent
|
(use-package aggressive-indent
|
||||||
:ensure t
|
|
||||||
:commands aggressive-indent-mode
|
:commands aggressive-indent-mode
|
||||||
:hook
|
:hook
|
||||||
(emacs-lisp-mode . aggressive-indent-mode))
|
(emacs-lisp-mode . aggressive-indent-mode))
|
||||||
|
|
||||||
;; Highlights function and variable definitions in Emacs Lisp mode
|
;; Highlights function and variable definitions in Emacs Lisp mode
|
||||||
(use-package highlight-defined
|
(use-package highlight-defined
|
||||||
:ensure t
|
|
||||||
:commands highlight-defined-mode
|
:commands highlight-defined-mode
|
||||||
:hook
|
:hook
|
||||||
(emacs-lisp-mode . highlight-defined-mode))
|
(emacs-lisp-mode . highlight-defined-mode))
|
||||||
@@ -1725,7 +1689,6 @@ Other optional packages that may be useful include:
|
|||||||
```emacs-lisp
|
```emacs-lisp
|
||||||
;; Prevent parenthesis imbalance
|
;; Prevent parenthesis imbalance
|
||||||
(use-package paredit
|
(use-package paredit
|
||||||
:ensure t
|
|
||||||
:commands paredit-mode
|
:commands paredit-mode
|
||||||
:hook
|
:hook
|
||||||
(emacs-lisp-mode . paredit-mode)
|
(emacs-lisp-mode . paredit-mode)
|
||||||
@@ -1735,14 +1698,12 @@ Other optional packages that may be useful include:
|
|||||||
;; For paredit+Evil mode users: enhances paredit with Evil mode compatibility
|
;; For paredit+Evil mode users: enhances paredit with Evil mode compatibility
|
||||||
;; --------------------------------------------------------------------------
|
;; --------------------------------------------------------------------------
|
||||||
;; (use-package enhanced-evil-paredit
|
;; (use-package enhanced-evil-paredit
|
||||||
;; :ensure t
|
|
||||||
;; :commands enhanced-evil-paredit-mode
|
;; :commands enhanced-evil-paredit-mode
|
||||||
;; :hook
|
;; :hook
|
||||||
;; (paredit-mode . enhanced-evil-paredit-mode))
|
;; (paredit-mode . enhanced-evil-paredit-mode))
|
||||||
|
|
||||||
;; Displays visible indicators for page breaks
|
;; Displays visible indicators for page breaks
|
||||||
(use-package page-break-lines
|
(use-package page-break-lines
|
||||||
:ensure t
|
|
||||||
:commands (page-break-lines-mode
|
:commands (page-break-lines-mode
|
||||||
global-page-break-lines-mode)
|
global-page-break-lines-mode)
|
||||||
:hook
|
:hook
|
||||||
@@ -1751,7 +1712,6 @@ Other optional packages that may be useful include:
|
|||||||
;; Provides functions to find references to functions, macros, variables,
|
;; Provides functions to find references to functions, macros, variables,
|
||||||
;; special forms, and symbols in Emacs Lisp
|
;; special forms, and symbols in Emacs Lisp
|
||||||
(use-package elisp-refs
|
(use-package elisp-refs
|
||||||
:ensure t
|
|
||||||
:commands (elisp-refs-function
|
:commands (elisp-refs-function
|
||||||
elisp-refs-macro
|
elisp-refs-macro
|
||||||
elisp-refs-variable
|
elisp-refs-variable
|
||||||
@@ -1775,7 +1735,6 @@ To configure **inhibit-mouse**, add the following to `~/.emacs.d/post-init.el`:
|
|||||||
;; - Reinforce a keyboard-centric workflow by discouraging reliance on the mouse
|
;; - Reinforce a keyboard-centric workflow by discouraging reliance on the mouse
|
||||||
;; for navigation.
|
;; for navigation.
|
||||||
(use-package inhibit-mouse
|
(use-package inhibit-mouse
|
||||||
:ensure t
|
|
||||||
:config
|
:config
|
||||||
(if (daemonp)
|
(if (daemonp)
|
||||||
(add-hook 'server-after-make-frame-hook #'inhibit-mouse-mode)
|
(add-hook 'server-after-make-frame-hook #'inhibit-mouse-mode)
|
||||||
@@ -1803,7 +1762,6 @@ To enable *quick-sdcv*, add the following to your `~/.emacs.d/post-init.el`:
|
|||||||
|
|
||||||
```emacs-lisp
|
```emacs-lisp
|
||||||
(use-package quick-sdcv
|
(use-package quick-sdcv
|
||||||
:ensure t
|
|
||||||
:custom
|
:custom
|
||||||
(quick-sdcv-unique-buffers t)
|
(quick-sdcv-unique-buffers t)
|
||||||
(quick-sdcv-dictionary-prefix-symbol "►")
|
(quick-sdcv-dictionary-prefix-symbol "►")
|
||||||
@@ -2263,6 +2221,8 @@ The `straight.el` package is a declarative package manager for Emacs that aims t
|
|||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
(eval-print-last-sexp)))
|
(eval-print-last-sexp)))
|
||||||
(load bootstrap-file nil 'nomessage))
|
(load bootstrap-file nil 'nomessage))
|
||||||
|
|
||||||
|
(setq straight-use-package-by-default t)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Configuring Elpaca (package manager)
|
### Configuring Elpaca (package manager)
|
||||||
@@ -2321,9 +2281,15 @@ And [add the Elpaca bootstrap code](https://github.com/progfolio/elpaca?tab=read
|
|||||||
(add-hook 'after-init-hook #'elpaca-process-queues)
|
(add-hook 'after-init-hook #'elpaca-process-queues)
|
||||||
(elpaca `(,@elpaca-order))
|
(elpaca `(,@elpaca-order))
|
||||||
|
|
||||||
;; Optional: Install use-package support
|
;; Enable 'elpaca-no-symlink-mode' on Windows, as symlink creation
|
||||||
;; (elpaca elpaca-use-package
|
;; often fails without Administrator privileges or Developer Mode.
|
||||||
;; (elpaca-use-package-mode))
|
(when (eq system-type 'windows-nt)
|
||||||
|
(elpaca-no-symlink-mode 1))
|
||||||
|
|
||||||
|
;; Install use-package support
|
||||||
|
(elpaca elpaca-use-package
|
||||||
|
;; Enable use-package :ensure support for Elpaca.
|
||||||
|
(elpaca-use-package-mode))
|
||||||
```
|
```
|
||||||
|
|
||||||
## Frequently asked questions
|
## Frequently asked questions
|
||||||
|
|||||||
15
custom.el
Normal file
15
custom.el
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
(custom-set-variables
|
||||||
|
;; custom-set-variables was added by Custom.
|
||||||
|
;; If you edit it by hand, you could mess it up, so be careful.
|
||||||
|
;; Your init file should contain only one such instance.
|
||||||
|
;; If there is more than one, they won't work right.
|
||||||
|
'(safe-local-variable-values
|
||||||
|
'((eval add-to-list 'imenu-generic-expression
|
||||||
|
'("Variables"
|
||||||
|
"^\\s-*(\\(defvar-zpg\\)\\s-+\\(\\(?:\\w\\|\\s_\\|\\\\.\\)+\\)" 2)))))
|
||||||
|
(custom-set-faces
|
||||||
|
;; custom-set-faces was added by Custom.
|
||||||
|
;; If you edit it by hand, you could mess it up, so be careful.
|
||||||
|
;; Your init file should contain only one such instance.
|
||||||
|
;; If there is more than one, they won't work right.
|
||||||
|
)
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
;; URL: https://github.com/jamescherti/minimal-emacs.d
|
;; URL: https://github.com/jamescherti/minimal-emacs.d
|
||||||
;; Package-Requires: ((emacs "29.1"))
|
;; Package-Requires: ((emacs "29.1"))
|
||||||
;; Keywords: maint
|
;; Keywords: maint
|
||||||
;; Version: 1.4.0
|
;; Version: 1.4.1
|
||||||
;; SPDX-License-Identifier: GPL-3.0-or-later
|
;; SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
@@ -76,7 +76,7 @@ lookups during Emacs startup.")
|
|||||||
This reduces visual clutter and slightly enhances startup performance. The
|
This reduces visual clutter and slightly enhances startup performance. The
|
||||||
tradeoff is that the mode line is hidden during the startup phase.")
|
tradeoff is that the mode line is hidden during the startup phase.")
|
||||||
|
|
||||||
(defvar minimal-emacs-package-initialize-and-refresh t
|
(defvar minimal-emacs-package-initialize-and-refresh nil
|
||||||
"Whether to automatically initialize and refresh packages.
|
"Whether to automatically initialize and refresh packages.
|
||||||
When set to non-nil, Emacs will automatically call `package-initialize' and
|
When set to non-nil, Emacs will automatically call `package-initialize' and
|
||||||
`package-refresh-contents' to set up and update the package system.")
|
`package-refresh-contents' to set up and update the package system.")
|
||||||
@@ -124,8 +124,10 @@ Note that this should end with a directory separator.")
|
|||||||
(error "Emacs ignored loading 'init.el'. Please ensure that files such as ~/.emacs or ~/.emacs.el do not exist, as they may be preventing Emacs from loading the 'init.el' file"))
|
(error "Emacs ignored loading 'init.el'. Please ensure that files such as ~/.emacs or ~/.emacs.el do not exist, as they may be preventing Emacs from loading the 'init.el' file"))
|
||||||
|
|
||||||
(t
|
(t
|
||||||
(error "Configuration error. Debug by starting Emacs with: emacs --debug-init")))))
|
(error "Configuration error. Debug by starting Emacs with: --debug-init")))))
|
||||||
(add-hook 'emacs-startup-hook #'minimal-emacs--check-success 102)
|
|
||||||
|
(unless noninteractive
|
||||||
|
(add-hook 'emacs-startup-hook #'minimal-emacs--check-success 102))
|
||||||
|
|
||||||
(defvar minimal-emacs-load-compiled-init-files nil
|
(defvar minimal-emacs-load-compiled-init-files nil
|
||||||
"If non-nil, attempt to load byte-compiled .elc for init files.
|
"If non-nil, attempt to load byte-compiled .elc for init files.
|
||||||
@@ -174,7 +176,9 @@ pre-early-init.el, and post-early-init.el.")
|
|||||||
|
|
||||||
(defun minimal-emacs--restore-gc ()
|
(defun minimal-emacs--restore-gc ()
|
||||||
"Restore garbage collection settings."
|
"Restore garbage collection settings."
|
||||||
(if (bound-and-true-p minimal-emacs-gc-cons-threshold-restore-delay)
|
(if (and (bound-and-true-p minimal-emacs-gc-cons-threshold-restore-delay)
|
||||||
|
;; In noninteractive mode, the event loop does not run
|
||||||
|
(not noninteractive))
|
||||||
;; Defer garbage collection during initialization to avoid 2 collections.
|
;; Defer garbage collection during initialization to avoid 2 collections.
|
||||||
(run-with-timer minimal-emacs-gc-cons-threshold-restore-delay nil
|
(run-with-timer minimal-emacs-gc-cons-threshold-restore-delay nil
|
||||||
#'minimal-emacs--restore-gc-values)
|
#'minimal-emacs--restore-gc-values)
|
||||||
@@ -355,6 +359,9 @@ this stage of initialization."
|
|||||||
|
|
||||||
;;; Performance: Disable mode-line during startup
|
;;; Performance: Disable mode-line during startup
|
||||||
|
|
||||||
|
(defvar-local minimal-emacs--hidden-mode-line nil
|
||||||
|
"Store the buffer-local value of `mode-line-format' during startup.")
|
||||||
|
|
||||||
(when (and minimal-emacs-disable-mode-line-during-startup
|
(when (and minimal-emacs-disable-mode-line-during-startup
|
||||||
(not noninteractive)
|
(not noninteractive)
|
||||||
(not minimal-emacs-debug))
|
(not minimal-emacs-debug))
|
||||||
@@ -363,7 +370,9 @@ this stage of initialization."
|
|||||||
(setq-default mode-line-format nil)
|
(setq-default mode-line-format nil)
|
||||||
(dolist (buf (buffer-list))
|
(dolist (buf (buffer-list))
|
||||||
(with-current-buffer buf
|
(with-current-buffer buf
|
||||||
(setq mode-line-format nil))))
|
(when (local-variable-p 'mode-line-format)
|
||||||
|
(setq minimal-emacs--hidden-mode-line mode-line-format)
|
||||||
|
(setq mode-line-format nil)))))
|
||||||
|
|
||||||
;;; Restore values
|
;;; Restore values
|
||||||
|
|
||||||
@@ -382,7 +391,12 @@ this stage of initialization."
|
|||||||
(when minimal-emacs-disable-mode-line-during-startup
|
(when minimal-emacs-disable-mode-line-during-startup
|
||||||
(unless (default-toplevel-value 'mode-line-format)
|
(unless (default-toplevel-value 'mode-line-format)
|
||||||
(setq-default mode-line-format (get 'mode-line-format
|
(setq-default mode-line-format (get 'mode-line-format
|
||||||
'initial-value))))))
|
'initial-value)))
|
||||||
|
(dolist (buf (buffer-list))
|
||||||
|
(with-current-buffer buf
|
||||||
|
(when (local-variable-p 'minimal-emacs--hidden-mode-line)
|
||||||
|
(setq mode-line-format minimal-emacs--hidden-mode-line)
|
||||||
|
(kill-local-variable 'minimal-emacs--hidden-mode-line)))))))
|
||||||
|
|
||||||
(advice-add 'startup--load-user-init-file :around
|
(advice-add 'startup--load-user-init-file :around
|
||||||
#'minimal-emacs--startup-load-user-init-file)
|
#'minimal-emacs--startup-load-user-init-file)
|
||||||
|
|||||||
26
init.el
26
init.el
@@ -4,7 +4,7 @@
|
|||||||
;; URL: https://github.com/jamescherti/minimal-emacs.d
|
;; URL: https://github.com/jamescherti/minimal-emacs.d
|
||||||
;; Package-Requires: ((emacs "29.1"))
|
;; Package-Requires: ((emacs "29.1"))
|
||||||
;; Keywords: maint
|
;; Keywords: maint
|
||||||
;; Version: 1.4.0
|
;; Version: 1.4.1
|
||||||
;; SPDX-License-Identifier: GPL-3.0-or-later
|
;; SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
@@ -161,7 +161,6 @@
|
|||||||
;;; Tramp
|
;;; Tramp
|
||||||
|
|
||||||
(setq tramp-verbose 1)
|
(setq tramp-verbose 1)
|
||||||
(setq tramp-completion-reread-directory-timeout 50)
|
|
||||||
|
|
||||||
;;; Files
|
;;; Files
|
||||||
|
|
||||||
@@ -212,7 +211,7 @@
|
|||||||
(setq make-backup-files nil)
|
(setq make-backup-files nil)
|
||||||
|
|
||||||
(setq backup-directory-alist
|
(setq backup-directory-alist
|
||||||
`(("." . ,(expand-file-name "backup" user-emacs-directory))))
|
`((".*" . ,(expand-file-name "backup" user-emacs-directory))))
|
||||||
(setq tramp-backup-directory-alist backup-directory-alist)
|
(setq tramp-backup-directory-alist backup-directory-alist)
|
||||||
(setq backup-by-copying-when-linked t)
|
(setq backup-by-copying-when-linked t)
|
||||||
(setq backup-by-copying t) ; Backup by copying rather renaming
|
(setq backup-by-copying t) ; Backup by copying rather renaming
|
||||||
@@ -300,10 +299,6 @@
|
|||||||
|
|
||||||
;;; Frames and windows
|
;;; Frames and windows
|
||||||
|
|
||||||
;; However, do not resize windows pixelwise, as this can cause crashes in some
|
|
||||||
;; cases when resizing too many windows at once or rapidly.
|
|
||||||
(setq window-resize-pixelwise nil)
|
|
||||||
|
|
||||||
(setq resize-mini-windows 'grow-only)
|
(setq resize-mini-windows 'grow-only)
|
||||||
|
|
||||||
;; The native border "uses" a pixel of the fringe on the rightmost
|
;; The native border "uses" a pixel of the fringe on the rightmost
|
||||||
@@ -333,20 +328,10 @@
|
|||||||
;; 2. Resolving the issue of random half-screen jumps during scrolling.
|
;; 2. Resolving the issue of random half-screen jumps during scrolling.
|
||||||
(setq auto-window-vscroll nil)
|
(setq auto-window-vscroll nil)
|
||||||
|
|
||||||
;; Number of lines of margin at the top and bottom of a window.
|
|
||||||
(setq scroll-margin 0)
|
|
||||||
|
|
||||||
;; Number of lines of continuity when scrolling by screenfuls.
|
|
||||||
(setq next-screen-context-lines 0)
|
|
||||||
|
|
||||||
;; Horizontal scrolling
|
;; Horizontal scrolling
|
||||||
(setq hscroll-margin 2
|
(setq hscroll-margin 2
|
||||||
hscroll-step 1)
|
hscroll-step 1)
|
||||||
|
|
||||||
;;; Mouse
|
|
||||||
|
|
||||||
(setq mouse-yank-at-point nil)
|
|
||||||
|
|
||||||
;; Emacs 29
|
;; Emacs 29
|
||||||
(when (memq 'context-menu minimal-emacs-ui-features)
|
(when (memq 'context-menu minimal-emacs-ui-features)
|
||||||
(when (and (display-graphic-p) (fboundp 'context-menu-mode))
|
(when (and (display-graphic-p) (fboundp 'context-menu-mode))
|
||||||
@@ -362,9 +347,6 @@
|
|||||||
;; Don't blink the paren matching the one at point, it's too distracting.
|
;; Don't blink the paren matching the one at point, it's too distracting.
|
||||||
(setq blink-matching-paren nil)
|
(setq blink-matching-paren nil)
|
||||||
|
|
||||||
;; Do not extend the cursor to fit wide characters
|
|
||||||
(setq x-stretch-cursor nil)
|
|
||||||
|
|
||||||
;; Reduce rendering/line scan work by not rendering cursors or regions in
|
;; Reduce rendering/line scan work by not rendering cursors or regions in
|
||||||
;; non-focused windows.
|
;; non-focused windows.
|
||||||
(setq highlight-nonselected-windows nil)
|
(setq highlight-nonselected-windows nil)
|
||||||
@@ -378,10 +360,6 @@
|
|||||||
;; deletion, disrupting the flow of editing.
|
;; deletion, disrupting the flow of editing.
|
||||||
(setq delete-pair-blink-delay 0.03)
|
(setq delete-pair-blink-delay 0.03)
|
||||||
|
|
||||||
;; Disable visual indicators in the fringe for buffer boundaries and empty lines
|
|
||||||
(setq-default indicate-buffer-boundaries nil)
|
|
||||||
(setq-default indicate-empty-lines nil)
|
|
||||||
|
|
||||||
;; Continue wrapped lines at whitespace rather than breaking in the
|
;; Continue wrapped lines at whitespace rather than breaking in the
|
||||||
;; middle of a word.
|
;; middle of a word.
|
||||||
(setq-default word-wrap t)
|
(setq-default word-wrap t)
|
||||||
|
|||||||
119
load/cyrillic-workman-input-method.el
Normal file
119
load/cyrillic-workman-input-method.el
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
;;; cyrillic-workman-input-method.el --- Workman but cyrillic. -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(require 'quail)
|
||||||
|
|
||||||
|
(quail-define-package
|
||||||
|
"cyrillic-workman" "Russian" "RUW" t
|
||||||
|
"Russian (ЙЦУКЕН) input method simulating Workman keyboard"
|
||||||
|
nil t t t t nil nil nil nil nil t)
|
||||||
|
|
||||||
|
;; 1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ += `~
|
||||||
|
;; qQ dD rR wW bB jJ fF uU pP ;: [{ ]}
|
||||||
|
;; aA sS hH tT gG yY nN eE oO iI '" \|
|
||||||
|
;; zZ xX mM cC vV kK lL ,< .> /?
|
||||||
|
|
||||||
|
;; 1! 2" 3№ 4; 5% 6: 7? 8* 9( 0) -_ =+ \/ ёЁ
|
||||||
|
;; Й Ц У К Е Н Г Ш Щ З Х Ъ
|
||||||
|
;; Ф Ы В А П Р О Л Д Ж Э
|
||||||
|
;; Я Ч С М И Т Ь Б Ю .,
|
||||||
|
|
||||||
|
(quail-define-rules
|
||||||
|
("1" ?1)
|
||||||
|
("2" ?2)
|
||||||
|
("3" ?3)
|
||||||
|
("4" ?4)
|
||||||
|
("5" ?5)
|
||||||
|
("6" ?6)
|
||||||
|
("7" ?7)
|
||||||
|
("8" ?8)
|
||||||
|
("9" ?9)
|
||||||
|
("0" ?0)
|
||||||
|
("-" ?-)
|
||||||
|
("=" ?=)
|
||||||
|
("|" ?/)
|
||||||
|
("`" ?ё)
|
||||||
|
("q" ?й)
|
||||||
|
("d" ?ц)
|
||||||
|
("r" ?у)
|
||||||
|
("w" ?к)
|
||||||
|
("b" ?е)
|
||||||
|
("j" ?н)
|
||||||
|
("f" ?г)
|
||||||
|
("u" ?ш)
|
||||||
|
("p" ?щ)
|
||||||
|
(";" ?з)
|
||||||
|
("[" ?х)
|
||||||
|
("]" ?ъ)
|
||||||
|
("a" ?ф)
|
||||||
|
("s" ?ы)
|
||||||
|
("h" ?в)
|
||||||
|
("t" ?а)
|
||||||
|
("g" ?п)
|
||||||
|
("y" ?р)
|
||||||
|
("n" ?о)
|
||||||
|
("e" ?л)
|
||||||
|
("o" ?д)
|
||||||
|
("i" ?ж)
|
||||||
|
("'" ?э)
|
||||||
|
("\\" ?\\)
|
||||||
|
("z" ?я)
|
||||||
|
("x" ?ч)
|
||||||
|
("m" ?с)
|
||||||
|
("c" ?м)
|
||||||
|
("v" ?и)
|
||||||
|
("k" ?т)
|
||||||
|
("l" ?ь)
|
||||||
|
("," ?б)
|
||||||
|
("." ?ю)
|
||||||
|
("/" ?.)
|
||||||
|
("!" ?!)
|
||||||
|
("@" ?\")
|
||||||
|
("#" ?№)
|
||||||
|
("$" ?\;)
|
||||||
|
("%" ?%)
|
||||||
|
("^" ?:)
|
||||||
|
("&" ??)
|
||||||
|
("*" ?*)
|
||||||
|
("(" ?\()
|
||||||
|
(")" ?\))
|
||||||
|
("_" ?_)
|
||||||
|
("+" ?+)
|
||||||
|
("~" ?Ё)
|
||||||
|
("Q" ?Й)
|
||||||
|
("D" ?Ц)
|
||||||
|
("R" ?У)
|
||||||
|
("W" ?К)
|
||||||
|
("B" ?Е)
|
||||||
|
("J" ?Н)
|
||||||
|
("F" ?Г)
|
||||||
|
("U" ?Ш)
|
||||||
|
("P" ?Щ)
|
||||||
|
(":" ?З)
|
||||||
|
("{" ?Х)
|
||||||
|
("}" ?Ъ)
|
||||||
|
("A" ?Ф)
|
||||||
|
("S" ?Ы)
|
||||||
|
("H" ?В)
|
||||||
|
("T" ?А)
|
||||||
|
("G" ?П)
|
||||||
|
("Y" ?Р)
|
||||||
|
("N" ?О)
|
||||||
|
("E" ?Л)
|
||||||
|
("O" ?Д)
|
||||||
|
("I" ?Ж)
|
||||||
|
("\"" ?Э)
|
||||||
|
("|" ?|)
|
||||||
|
("Z" ?Я)
|
||||||
|
("X" ?Ч)
|
||||||
|
("M" ?С)
|
||||||
|
("C" ?М)
|
||||||
|
("V" ?И)
|
||||||
|
("K" ?Т)
|
||||||
|
("L" ?Ь)
|
||||||
|
("<" ?Б)
|
||||||
|
(">" ?Ю)
|
||||||
|
("?" ?,))
|
||||||
|
|
||||||
|
(provide 'cyrillic-workman-input-method)
|
||||||
|
|
||||||
|
;;; cyrillic-workman-input-method.el ends here
|
||||||
93
load/myfeed.el
Normal file
93
load/myfeed.el
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
;;; myfeed.el --- My RSS reader -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;; Author: iamtoaster
|
||||||
|
;; Version: 0.0.0
|
||||||
|
;; Package-Requires: ()
|
||||||
|
;; Homepage:
|
||||||
|
;; Keywords: rss, url
|
||||||
|
|
||||||
|
;; This file is not part of GNU Emacs
|
||||||
|
|
||||||
|
;; This program is free software: you can redistribute it and/or modify
|
||||||
|
;; it under the terms of the GNU General Public License as published by
|
||||||
|
;; the Free Software Foundation, either version 3 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; This program is distributed in the hope that it will be useful,
|
||||||
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
;; GNU General Public License for more details.
|
||||||
|
|
||||||
|
;; You should have received a copy of the GNU General Public License
|
||||||
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; An RSS feed reader inspired by elfeed. Very early WIP.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(defvar myreader-feeds '()
|
||||||
|
"Alist of the form (NAME . LINK) of RSS feeds.")
|
||||||
|
|
||||||
|
(defvar myreader--feed-buffers '()
|
||||||
|
"Alist of buffers in which the asynchronously retrieved pages are
|
||||||
|
written.")
|
||||||
|
|
||||||
|
(defvar myreader--feed-cache '()
|
||||||
|
"A list of retrieved entries.")
|
||||||
|
|
||||||
|
;; (defun myreader--eww-render-buffer ()
|
||||||
|
;; "Render the current buffer in EWW."
|
||||||
|
;; (interactive)
|
||||||
|
;; (let* ((html (buffer-substring-no-properties (point-min) (point-max)))
|
||||||
|
;; (source (buffer-name))
|
||||||
|
;; (buf (generate-new-buffer (concat "RSS: " source))))
|
||||||
|
;; (with-current-buffer buf
|
||||||
|
;; (insert html)
|
||||||
|
;; (goto-char (point-min))
|
||||||
|
;; (eww-display-html 'utf-8 source nil nil buf))
|
||||||
|
;; (switch-to-buffer buf)))
|
||||||
|
|
||||||
|
(defun myreader--render-entry ()
|
||||||
|
(with-current-buffer retr-buf
|
||||||
|
(message "%s" (buffer-substring (point-min) (point-max)))))
|
||||||
|
|
||||||
|
(defun myreader--update-feed (name)
|
||||||
|
(let ((buf (alist-get name myreader--feed-buffers)))
|
||||||
|
;; TODO figure out a good way to put the thing in cache and then use it
|
||||||
|
(message "Feed %s; Parsed %s" name (libxml-parse-html-region (point)))))
|
||||||
|
|
||||||
|
(setq myreader-feeds '((scour . "https://scour.ing/@DiToast/rss.xml")))
|
||||||
|
|
||||||
|
(defun myreader-update-feeds (&optional force)
|
||||||
|
"Goes through all the feeds defined in `myreader-feeds' and updates them
|
||||||
|
if necessary. If FORCE is non-nil, updates them unconditionally."
|
||||||
|
(dolist (entry myreader-feeds)
|
||||||
|
(let ((name (car entry))
|
||||||
|
(link (cdr entry)))
|
||||||
|
(let ((cache-entry (alist-get name myreader--feed-cache)))
|
||||||
|
;; TODO check if entry exists in cache -> check if ttl expired
|
||||||
|
;; (if (and cache-entry (alist-get ))
|
||||||
|
;; TODO if updating async retrieve the LINK through myreader--feed-buffers
|
||||||
|
(setq myreader--feed-buffers
|
||||||
|
(cons
|
||||||
|
(cons
|
||||||
|
name
|
||||||
|
(url-retrieve link (lambda (&rest keys) (myreader--update-feed name))))
|
||||||
|
myreader--feed-buffers))))))
|
||||||
|
|
||||||
|
(defun myreader-revert-item-buffer ()
|
||||||
|
"Reverts the buffer containing the list of RSS entry items from
|
||||||
|
`myreader--feed-cache'."
|
||||||
|
(interactive)
|
||||||
|
;; TODO go through cache -> check ttl -> update feed if necessary
|
||||||
|
;; TODO add the items to the tabulated list
|
||||||
|
())
|
||||||
|
|
||||||
|
;; (setq retr-buf (url-retrieve "https://scour.ing/@DiToast/rss.xml"
|
||||||
|
;; (lambda (&rest keys) (render-buff))))
|
||||||
|
|
||||||
|
(provide 'myfeed)
|
||||||
|
|
||||||
|
;;; myfeed.el ends here
|
||||||
219
load/simple-state-machines.el
Normal file
219
load/simple-state-machines.el
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
;;; simple-state-machines.el --- My simple state machine macro. -*- lexical-binding: t -*-
|
||||||
|
|
||||||
|
;; Author: iamtoaster
|
||||||
|
;; Version: 0.1
|
||||||
|
;; Package-Requires: (cl-lib)
|
||||||
|
;; Homepage:
|
||||||
|
;; Keywords: FSM, Macro
|
||||||
|
|
||||||
|
;; This file is not part of GNU Emacs
|
||||||
|
|
||||||
|
;; This program is free software: you can redistribute it and/or modify
|
||||||
|
;; it under the terms of the GNU General Public License as published by
|
||||||
|
;; the Free Software Foundation, either version 3 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; This program is distributed in the hope that it will be useful,
|
||||||
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
;; GNU General Public License for more details.
|
||||||
|
|
||||||
|
;; You should have received a copy of the GNU General Public License
|
||||||
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; This is my implementation of simple finite state machines. This package
|
||||||
|
;; provides a defstate-machine macro and an update-state function. They can be
|
||||||
|
;; combined to create a simple FSM with three states like so:
|
||||||
|
;;
|
||||||
|
;; (ssm-defstate-machine test
|
||||||
|
;; :states (one two three)
|
||||||
|
;; :initial-state three
|
||||||
|
;; :transitions ((one . two)
|
||||||
|
;; (two . three)
|
||||||
|
;; (three . one))
|
||||||
|
;; :handlers ((two . (lambda (name) (ssm-update-state name 'three)))
|
||||||
|
;; (three . (lambda (name) (ssm-update-state name 'one)))
|
||||||
|
;; (one . (lambda (name) (ssm-update-state name 'two)))))
|
||||||
|
;;
|
||||||
|
;; The code above will create a state machine with three states, appropriately
|
||||||
|
;; named 'one', 'two' and 'three', by specifying them after the :states key. The
|
||||||
|
;; initial state will be set to state 'three'. If no initial state is provided,
|
||||||
|
;; the first state in the list will be used automatically.
|
||||||
|
;;
|
||||||
|
;; Then, we define valid transitions between states using the :transitions key.
|
||||||
|
;; If we try to change the state in a way that is not defined in this alist,
|
||||||
|
;; `update-state' will signal an error.
|
||||||
|
;;
|
||||||
|
;; Finally, we specify handlers for states using the :handlers key. See
|
||||||
|
;; `defstate-machine' for information.
|
||||||
|
;;
|
||||||
|
;; This macro call will provide us with the following variables:
|
||||||
|
;; 'test-state-table' -- Stores the state list, verbatim.
|
||||||
|
;; 'test-transition-table' -- Stores the valid transitions, verbatim.
|
||||||
|
;; 'test-current-state' -- Stores the current state.
|
||||||
|
;; 'test-state-data' -- Optional data for the current state, initialized to nil.
|
||||||
|
;; 'test-state-handlers' -- Stores the mapping from the states to their handlers,
|
||||||
|
;; verbatim.
|
||||||
|
;;
|
||||||
|
;; As well as the following functions:
|
||||||
|
;; 'test-step' -- Calls the handler for the current state.
|
||||||
|
;; 'test-set-state' -- Tries to set the current state to the provided one, and
|
||||||
|
;; signals an error if the transition is invalid.
|
||||||
|
;;
|
||||||
|
;; Here is the recreation of the counter example from
|
||||||
|
;; https://www.emacswiki.org/emacs/StateMachine
|
||||||
|
;;
|
||||||
|
;; (ssm-defstate-machine counter
|
||||||
|
;; :states (start count end)
|
||||||
|
;; :transitions ((start . count)
|
||||||
|
;; (count . end)
|
||||||
|
;; (count . count))
|
||||||
|
;; :handlers ((start . (lambda (name)
|
||||||
|
;; (princ "Starting...")
|
||||||
|
;; (terpri)
|
||||||
|
;; (ssm-update-state name 'count 0)))
|
||||||
|
;; (count . (lambda (name)
|
||||||
|
;; (cond ((<= (ssm-get-state-data name) 10)
|
||||||
|
;; (princ (ssm-get-state-data name))
|
||||||
|
;; (ssm-update-state
|
||||||
|
;; name
|
||||||
|
;; 'count
|
||||||
|
;; (1+ (ssm-get-state-data name))))
|
||||||
|
;; (t (terpri) (ssm-update-state name 'end nil)))))))
|
||||||
|
;;
|
||||||
|
;; (ssm-run-until-state 'counter 'end)
|
||||||
|
;;
|
||||||
|
;; As you can see, ssm-update-state definitely needs some love. It is unwieldy.
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(require 'cl-lib)
|
||||||
|
|
||||||
|
(defmacro ssm-defstate-machine (name &rest args)
|
||||||
|
"Defines a state machine with name NAME, STATES and TRANSITIONS between
|
||||||
|
them. If INITIAL-STATE is nil, the first state will be used.
|
||||||
|
|
||||||
|
Arguments are specified as keyword/argument pairs. The following
|
||||||
|
arguments are defined:
|
||||||
|
|
||||||
|
:states LIST -- LIST should be a list of symbols each representing a
|
||||||
|
state. LIST will not be evaluated.
|
||||||
|
|
||||||
|
:transitions ALIST -- ALIST should be an alist of the form (FROM . TO)
|
||||||
|
where both FROM and TO are names of states available in the :states LIST.
|
||||||
|
|
||||||
|
:handlers ALIST -- ALIST should be an alist of the form (STATE .
|
||||||
|
HANDLER) where STATE is one of the states in the :states LIST and
|
||||||
|
HANDLER is a function that can be called by funcall. It is advised to
|
||||||
|
provide a handler for all of the state, because an error will be
|
||||||
|
signalled if you try to step on a state with no handler.
|
||||||
|
|
||||||
|
The following optional arguments are defined:
|
||||||
|
|
||||||
|
:initial-state SYMBOL -- If SYMBOL is non-nil and present in the :states
|
||||||
|
LIST, it will be set as the initial state of this state machine.
|
||||||
|
Otherwise, the first state in the :states LIST will be used.
|
||||||
|
|
||||||
|
(fn NAME &key INITIAL-STATE STATES TRANSITIONS HANDLERS)"
|
||||||
|
(declare (indent defun))
|
||||||
|
(let ((machine-name (symbol-name name))
|
||||||
|
(states (plist-get args :states))
|
||||||
|
(transitions (plist-get args :transitions))
|
||||||
|
(handlers (plist-get args :handlers))
|
||||||
|
(initial-state (plist-get args :initial-state)))
|
||||||
|
(if (not initial-state)
|
||||||
|
(setq initial-state (car states)))
|
||||||
|
(cl-assert (cl-find initial-state states) t
|
||||||
|
"Cannot find the initial state in the state list.")
|
||||||
|
(dolist (entry handlers)
|
||||||
|
(cl-assert (cl-find (car entry) states)) t)
|
||||||
|
(dolist (entry transitions)
|
||||||
|
(cl-assert (and (cl-find (car entry) states)
|
||||||
|
(cl-find (cdr entry) states))
|
||||||
|
nil "Invalid transition: Either the source or the target state does not exist."))
|
||||||
|
(let ((state-table (intern (concat machine-name "-state-table")))
|
||||||
|
(transition-table (intern (concat machine-name "-transition-table")))
|
||||||
|
(current-state (intern (concat machine-name "-current-state")))
|
||||||
|
(state-data (intern (concat machine-name "-state-data")))
|
||||||
|
(step-fn (intern (concat machine-name "-step")))
|
||||||
|
(state-set-fn (intern (concat machine-name "-set-state")))
|
||||||
|
(handlers-table (intern (concat machine-name "-state-handlers"))))
|
||||||
|
`(progn
|
||||||
|
(defvar ,state-table ',states
|
||||||
|
,(concat "The state table of the " machine-name " state machine."))
|
||||||
|
(defvar ,transition-table ',transitions
|
||||||
|
,(concat "The transitions table of the " machine-name " state machine.\n
|
||||||
|
Each entry of this alist has the form (FROM . TO)."))
|
||||||
|
(defvar ,current-state ',initial-state
|
||||||
|
,(concat "The current state of the " machine-name " state machine."))
|
||||||
|
(defvar ,state-data nil
|
||||||
|
,(concat "The data of the current state of the " machine-name " state machine."))
|
||||||
|
(defvar ,handlers-table ',handlers
|
||||||
|
,(concat "An alist mapping states of the "
|
||||||
|
machine-name
|
||||||
|
" state machine to their respective handlers."))
|
||||||
|
,@(let ((handler (make-symbol "handler"))
|
||||||
|
(prev-state (make-symbol "prev-state")))
|
||||||
|
`((defun ,step-fn ()
|
||||||
|
,(concat "The stepping function of the "
|
||||||
|
machine-name
|
||||||
|
" state machine.\n\nIt tries to find a handler for the current state (see `"
|
||||||
|
(symbol-name current-state)
|
||||||
|
"' and\n`"
|
||||||
|
(symbol-name handlers-table)
|
||||||
|
"'),and then call it with the name of this state machine\nas its only argument.")
|
||||||
|
(let ((,handler (alist-get ,current-state ,handlers-table))
|
||||||
|
(,prev-state ,current-state))
|
||||||
|
(cl-assert ,handler nil "There is no handler for the current state")
|
||||||
|
(funcall ,handler ',name)
|
||||||
|
(cl-assert
|
||||||
|
(cl-find
|
||||||
|
(cons ,prev-state ,current-state)
|
||||||
|
,transition-table
|
||||||
|
:test 'equal)
|
||||||
|
"Invalid state transition. State machine is now in inconsistent state.")))
|
||||||
|
(defun ,state-set-fn (state &optional new-data)
|
||||||
|
,(concat
|
||||||
|
"Sets the state of "
|
||||||
|
machine-name
|
||||||
|
" state machine. Signals an error if the state transition\nis invalid, see `"
|
||||||
|
(symbol-name transition-table)
|
||||||
|
"' for a list of valid transitions.")
|
||||||
|
(cl-assert
|
||||||
|
(cl-find
|
||||||
|
(cons ,current-state state)
|
||||||
|
,transition-table
|
||||||
|
:test 'equal) t
|
||||||
|
"Invalid state transition.")
|
||||||
|
(setq ,current-state state
|
||||||
|
,state-data new-data))))))))
|
||||||
|
|
||||||
|
(defun ssm-update-state (machine new-state new-data)
|
||||||
|
"Updates the state of the state machine MACHINE. Signals an error if the
|
||||||
|
state transition is invalid."
|
||||||
|
(let ((state-fn
|
||||||
|
(intern-soft (concat (symbol-name machine) "-set-state"))))
|
||||||
|
(funcall state-fn new-state new-data)))
|
||||||
|
|
||||||
|
(defun ssm-get-state (machine)
|
||||||
|
"Returns the state of the specified machine."
|
||||||
|
(let ((state
|
||||||
|
(intern-soft (concat (symbol-name machine) "-current-state"))))
|
||||||
|
(symbol-value state)))
|
||||||
|
|
||||||
|
(defun ssm-get-state-data (machine)
|
||||||
|
"Returns the state data of the specified machine."
|
||||||
|
(let ((state-data
|
||||||
|
(intern-soft (concat (symbol-name machine) "-state-data"))))
|
||||||
|
(symbol-value state-data)))
|
||||||
|
|
||||||
|
(defun ssm-run-until-state (machine state)
|
||||||
|
"Steps the specified MACHINE until it enters state STATE."
|
||||||
|
(let ((step-fn
|
||||||
|
(intern-soft (concat (symbol-name machine) "-step"))))
|
||||||
|
(while (not (equal (ssm-get-state machine) state))
|
||||||
|
(funcall step-fn))))
|
||||||
|
|
||||||
|
(provide 'simple-state-machines)
|
||||||
|
;;; simple-state-machines.el ends here
|
||||||
754
load/zpg.el
Normal file
754
load/zpg.el
Normal file
@@ -0,0 +1,754 @@
|
|||||||
|
;;; zpg.el --- A zero player game -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;; Author: iamtoaster
|
||||||
|
;; Version: 0.0.0
|
||||||
|
;; Package-Requires: ()
|
||||||
|
;; Homepage:
|
||||||
|
;; Keywords: game
|
||||||
|
|
||||||
|
;; This file is not part of GNU Emacs
|
||||||
|
|
||||||
|
;; This program is free software: you can redistribute it and/or modify
|
||||||
|
;; it under the terms of the GNU General Public License as published by
|
||||||
|
;; the Free Software Foundation, either version 3 of the License, or
|
||||||
|
;; (at your option) any later version.
|
||||||
|
|
||||||
|
;; This program is distributed in the hope that it will be useful,
|
||||||
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
;; GNU General Public License for more details.
|
||||||
|
|
||||||
|
;; You should have received a copy of the GNU General Public License
|
||||||
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
;;; Commentary:
|
||||||
|
|
||||||
|
;; A zero player game inspired by Godville.
|
||||||
|
|
||||||
|
;;; Code:
|
||||||
|
|
||||||
|
(defvar zpg-loadables '()
|
||||||
|
"Alist containing the keys and symbols whose values will we saved and
|
||||||
|
loaded. See `defvar-zpg'.")
|
||||||
|
|
||||||
|
(defmacro defvar-zpg (symbol &optional initvalue docstring &rest props)
|
||||||
|
"Acts exactly like the normal `defvar', but accepts additional properties
|
||||||
|
that may influence how the variable is defined. Currently supported
|
||||||
|
properties are:
|
||||||
|
|
||||||
|
:save - the variable will be added to `zpg-loadables' and thus, will be
|
||||||
|
saved and loaded."
|
||||||
|
(declare (indent defun) (doc-string 3))
|
||||||
|
(let ((new-symbol (make-symbol "new-symbol"))
|
||||||
|
(exps '()))
|
||||||
|
(if (plist-get props :save)
|
||||||
|
(setq exps (cons `(let ((,new-symbol (intern ,(concat ":" (symbol-name symbol)))))
|
||||||
|
(add-to-list 'zpg-loadables (cons ,new-symbol ',symbol)))
|
||||||
|
exps)))
|
||||||
|
(setq exps (cons `(defvar ,symbol ,initvalue ,docstring) exps))
|
||||||
|
(macroexp-progn exps)))
|
||||||
|
|
||||||
|
(defvar zpg-step-timeout 5
|
||||||
|
"Once active, zpg mode will do a step once every zpg-step-timeout
|
||||||
|
seconds.")
|
||||||
|
|
||||||
|
(defvar zpg--step-timer nil
|
||||||
|
"The timer object that does the stepping.")
|
||||||
|
|
||||||
|
(defvar zpg-log-size 10
|
||||||
|
"How many log messages are kept.")
|
||||||
|
|
||||||
|
(defvar-zpg zpg-player-health 100
|
||||||
|
"Current health of the players character. Cannot exceed tho Maximum
|
||||||
|
health defined in `zpg-player-max-health'." :save t)
|
||||||
|
|
||||||
|
(defvar-zpg zpg-player-max-health 100
|
||||||
|
"Maximum health of the players character. See `zpg-player-health' for the
|
||||||
|
current health." :save t)
|
||||||
|
|
||||||
|
(defvar zpg-save-location (concat user-emacs-directory "zpg-save.eld")
|
||||||
|
"Location in which to store the save data of the mode.")
|
||||||
|
|
||||||
|
(defvar-zpg zpg-statistics-kills 0
|
||||||
|
"How many enemies were killed." :save t)
|
||||||
|
|
||||||
|
(defvar-zpg zpg-statistics-death 0
|
||||||
|
"How many times you died." :save t)
|
||||||
|
|
||||||
|
(defvar-zpg zpg-statistics-steps 0
|
||||||
|
"How many steps were done." :save t)
|
||||||
|
|
||||||
|
(defvar-zpg zpg-player-position 0
|
||||||
|
"Current position of the player in distance from the capital. Yes, the
|
||||||
|
world is one dimensional. Deal with it." :save t)
|
||||||
|
|
||||||
|
(defvar-zpg zpg-player-gold 0
|
||||||
|
"The amount of gold the player has in their inventory." :save t)
|
||||||
|
|
||||||
|
(defvar-zpg zpg-player-exp 0
|
||||||
|
"The amount of experience the player has. See `zpg-player-level' and
|
||||||
|
`zpg-level-up-xp' for details on how the amount of experience needed for a
|
||||||
|
level-up is calculated." :save t)
|
||||||
|
|
||||||
|
(defvar-zpg zpg-player-level 1
|
||||||
|
"The current level of the player. There is no variable that holds how
|
||||||
|
much experience is needed to level up, instead, see `zpg-level-up-xp'." :save t)
|
||||||
|
|
||||||
|
(defvar-zpg zpg-player-inventory '()
|
||||||
|
"An alist representing the players inventory in the form of (NAME .
|
||||||
|
PROPS). NAME should be a string.
|
||||||
|
|
||||||
|
PROPS is a property list that, currently, only supports one key:
|
||||||
|
|
||||||
|
:rarity - The rarity of the item. Should be one of ('normal 'rare)." :save t)
|
||||||
|
|
||||||
|
(defvar-zpg zpg-player-inventory-size 20
|
||||||
|
"Defines how many items can the players inventory contain." :save t)
|
||||||
|
|
||||||
|
(defvar-zpg zpg-log '()
|
||||||
|
"Stores the log history that is rendered." :save t)
|
||||||
|
|
||||||
|
(defun zpg-add-log (entry &rest args)
|
||||||
|
"Formats the ENTRY using `format', passing ARGS to it, and adds the
|
||||||
|
result to the log."
|
||||||
|
(if (not (stringp entry))
|
||||||
|
(error "Expected string, got: %s" entry)
|
||||||
|
(setq zpg-log
|
||||||
|
(take
|
||||||
|
zpg-log-size
|
||||||
|
(cons
|
||||||
|
(apply 'format entry args)
|
||||||
|
zpg-log)))))
|
||||||
|
|
||||||
|
(defvar zpg-cities
|
||||||
|
'(("Capital" . (:pos 0 :modifiers ()))
|
||||||
|
("El Citiano" . (:pos 13))
|
||||||
|
("Los Citios" . (:pos 25))
|
||||||
|
("New City" . (:pos 31))
|
||||||
|
("Town Town" . (:pos 48))
|
||||||
|
("New Town Town" . (:pos 65))
|
||||||
|
("City of Peoples" . (:pos 71))
|
||||||
|
("Town of Rivers" . (:pos 87))
|
||||||
|
("Chinatown" . (:pos 100))
|
||||||
|
("Fartown" . (:pos 148))
|
||||||
|
("Peoples respite" . (:pos 201))
|
||||||
|
("Winlace city" . (:pos 242))
|
||||||
|
("Solace" . (:pos 297)))
|
||||||
|
"An alist containing all the cities in the game in the form of (NAME .
|
||||||
|
PROPS). PROPS is a plist containing the properties of the city. It
|
||||||
|
supports the following keys:
|
||||||
|
:pos - The position of the city, an integer.
|
||||||
|
:modifiers - A list of modifiers for the city behaviour, each
|
||||||
|
represented by an atom. See below for supported modifiers.
|
||||||
|
|
||||||
|
The following modifiers are supported:
|
||||||
|
()")
|
||||||
|
|
||||||
|
(defvar-zpg zpg-current-task '(none)
|
||||||
|
"A list representing the current task and its state, in the form (TASK .
|
||||||
|
STATE).
|
||||||
|
|
||||||
|
STATE is a plist that supports the following keys:
|
||||||
|
|
||||||
|
:progress - current progress.
|
||||||
|
:finish-progress - how much progress to finish the task.
|
||||||
|
:progress-point - indicates a point, upon reaching which the player will
|
||||||
|
get 10% of quest progress." :save t)
|
||||||
|
|
||||||
|
(defvar-zpg zpg-game-state (cons 'in-town ())
|
||||||
|
"Represents the current state of the game world using a cons cell of the
|
||||||
|
form (STATE . VALUES). STATE is an atom representing the name of the
|
||||||
|
current state. VALUES is a list representing the current states information, which is
|
||||||
|
dependent on the current state.
|
||||||
|
|
||||||
|
Depending on STATE, a handler defined in `zpg-state-handlers' is called
|
||||||
|
each game step (see `zpg-do-game-step')." :save t)
|
||||||
|
|
||||||
|
(defmacro zpg-random-clause (&rest clauses)
|
||||||
|
"Randomly select a clause based on its weight.
|
||||||
|
|
||||||
|
Each clause looks like (WEIGHT BODY...). WEIGHT must be either an
|
||||||
|
integer, or a form that evaluates to one. If two clauses have equal
|
||||||
|
WEIGHT, they are equally likely to be ran. The higher the WEIGHT is, the
|
||||||
|
more likely it is that this clause will be ran.
|
||||||
|
|
||||||
|
The probability of each clause being selected is dependent on both its
|
||||||
|
own WEIGHT and the total sum of all weights of all clauses. The simplest
|
||||||
|
way to think about this is when your weights add up to 100. In this
|
||||||
|
case, the WEIGHT of each clause is equal to the percentage chance of it
|
||||||
|
being ran.
|
||||||
|
|
||||||
|
For example, if we have three clauses with weights 10, 40 and 50 (which
|
||||||
|
add up to 100), the first clause has a 10% chance of being selected,
|
||||||
|
second 40%, and the third is 50%.
|
||||||
|
|
||||||
|
More generally, to get the probability of a clause being ran, you need
|
||||||
|
to divide its WEIGHT by the total weight of all clauses. Applying this
|
||||||
|
to the previous example:
|
||||||
|
First clause with WEIGHT of 10: 10/100 = 0.1 (= 10%)
|
||||||
|
Second clause with WEIGHT of 40: 40/100 = 0.4 (= 40%)
|
||||||
|
Third clause with WEIGHT of 50: 50/100 = 0.5 (= 50%)"
|
||||||
|
(let ((random-value (gensym "rnd"))
|
||||||
|
(weight-bindings '()))
|
||||||
|
|
||||||
|
;; For each weighted clause, we define a symbol and assign to it a value
|
||||||
|
;; of WEIGHT + previous symbol, except for the first clause, which just
|
||||||
|
;; gets its WEIGHT assigned directly.
|
||||||
|
`(let* (,@(dotimes (idx (length clauses) (reverse weight-bindings))
|
||||||
|
(let* ((el (car (nthcdr idx clauses)))
|
||||||
|
(prev-el (caar weight-bindings)))
|
||||||
|
(setq weight-bindings
|
||||||
|
(cons `(,(gensym "w")
|
||||||
|
,(if prev-el
|
||||||
|
`(+ ,(car el) ,prev-el)
|
||||||
|
(car el)))
|
||||||
|
weight-bindings))))
|
||||||
|
(,random-value (random ,(caar weight-bindings))))
|
||||||
|
(cond ,@(let ((result '())
|
||||||
|
(prev-weight '()))
|
||||||
|
(dotimes (idx (length weight-bindings) result)
|
||||||
|
(setq result
|
||||||
|
(cons
|
||||||
|
`((< ,random-value
|
||||||
|
,(caar (nthcdr idx weight-bindings)))
|
||||||
|
,(macroexp-progn
|
||||||
|
(cdr
|
||||||
|
(nth (- (1- (length clauses)) idx)
|
||||||
|
clauses))))
|
||||||
|
result))))))))
|
||||||
|
|
||||||
|
(defmacro zpg-with-state (list &rest body)
|
||||||
|
"Symbol binds VALUE to the states value and evaluates the BODY. Creates a
|
||||||
|
check that verifies that the current state is equal to NAME.
|
||||||
|
|
||||||
|
(fn (NAME VALUE) BODY)"
|
||||||
|
`(if (equal (car zpg-game-state) ',(car list))
|
||||||
|
(cl-symbol-macrolet ((,(cadr list) (cdr zpg-game-state)))
|
||||||
|
,(macroexp-progn body))
|
||||||
|
(error "Expected state %s, found: %s" ',(car list) (car zpg-game-state))))
|
||||||
|
|
||||||
|
(defun zpg-roll-player-damage ()
|
||||||
|
"Returns the amount of damage the player will deal."
|
||||||
|
(round (+ 20
|
||||||
|
(round
|
||||||
|
(*
|
||||||
|
(+
|
||||||
|
(log zpg-player-level)
|
||||||
|
1)
|
||||||
|
8)))))
|
||||||
|
|
||||||
|
(defun zpg-roll-enemy-damage (level)
|
||||||
|
"Returns the amount of damage the enemy will deal."
|
||||||
|
(round (+ (* (log level) 3)
|
||||||
|
5
|
||||||
|
(random (ceiling (+ (log level) 1))))))
|
||||||
|
|
||||||
|
(defun zpg-town-positions ()
|
||||||
|
"Returns the alist of form ((POSITION . TOWN)..)"
|
||||||
|
(mapcar (lambda (el)
|
||||||
|
(cons (plist-get (cdr el) :pos) (car el)))
|
||||||
|
zpg-cities))
|
||||||
|
|
||||||
|
(defun zpg-generate-enemy (level &rest args)
|
||||||
|
"Creates an enemy of the specified LEVEL and returns it. An enemy is
|
||||||
|
currently represented as a plist with the following properties:
|
||||||
|
|
||||||
|
:name - The name of the enemy;
|
||||||
|
:health - Their health;
|
||||||
|
:level - Their level;
|
||||||
|
:turn - Whose turn it is.
|
||||||
|
|
||||||
|
(fn LEVEL &key NAME TURN)"
|
||||||
|
(let ((health (+ 100 (* level 2)))
|
||||||
|
(name (plist-get args :name))
|
||||||
|
(turn (plist-get args :turn)))
|
||||||
|
(list
|
||||||
|
:name (if name name "Enemy")
|
||||||
|
:health health
|
||||||
|
:level level
|
||||||
|
:turn (if turn turn 'player))))
|
||||||
|
|
||||||
|
(defun zpg-add-quest-progress (amount)
|
||||||
|
"Adds the AMOUNT of progress to the current quest, and updates the states
|
||||||
|
as needed."
|
||||||
|
(if (equal (car zpg-current-task) 'none)
|
||||||
|
(error "Attempting to add progress to a task, but there is no current task."))
|
||||||
|
(cl-symbol-macrolet ((progress (plist-get (cdr zpg-current-task) :progress)))
|
||||||
|
(setf progress (+ amount progress))
|
||||||
|
(if (>= progress (plist-get (cdr zpg-current-task) :finish-progress))
|
||||||
|
(setq zpg-game-state (cons 'retreat (list :target (car zpg-cities)))))))
|
||||||
|
|
||||||
|
(defun zpg-handle-travel ()
|
||||||
|
"Handles the 'traveling' state. See `zpg-game-state'.
|
||||||
|
|
||||||
|
In this state, the players hero moves forward on the map, with a chance
|
||||||
|
of starting a fight instead."
|
||||||
|
(zpg-with-state
|
||||||
|
(traveling sval)
|
||||||
|
|
||||||
|
(cond
|
||||||
|
;; Retreat if we feeling bad, aka less than half health left.
|
||||||
|
((<= zpg-player-health (/ zpg-player-max-health 2))
|
||||||
|
(setq zpg-game-state (cons 'retreat nil))
|
||||||
|
(zpg-add-log "Health too low, retreating to the closest town."))
|
||||||
|
((and
|
||||||
|
(plist-get (cdr zpg-current-task) :progress)
|
||||||
|
(>= (plist-get (cdr zpg-current-task) :progress)
|
||||||
|
(plist-get (cdr zpg-current-task) :finish-progress)))
|
||||||
|
(setq zpg-game-state (cons 'retreat (list :target (car zpg-cities))))
|
||||||
|
(zpg-add-log "Continuing to %s" (caar zpg-cities)))
|
||||||
|
(t (zpg-random-clause
|
||||||
|
;; Add quest progress
|
||||||
|
(5
|
||||||
|
(zpg-add-quest-progress (+ 1 (random 2)))
|
||||||
|
(zpg-add-log "You are one step closer to completing your quest." ))
|
||||||
|
;; We fight
|
||||||
|
(20
|
||||||
|
(zpg-add-log "Entering a fight.")
|
||||||
|
(setq
|
||||||
|
zpg-game-state
|
||||||
|
(cons 'fighting
|
||||||
|
(zpg-generate-enemy (+ zpg-player-level (random 5))))))
|
||||||
|
;; We move forward one space
|
||||||
|
(75
|
||||||
|
(setq zpg-player-position (1+ zpg-player-position))))))))
|
||||||
|
|
||||||
|
(defun zpg-award-exp (amount)
|
||||||
|
"Adds the specified amount of exp to the experience pool and levels up if
|
||||||
|
needed."
|
||||||
|
(cond ((>= (+ amount zpg-player-exp) (zpg-level-up-xp))
|
||||||
|
(setq zpg-player-level (1+ zpg-player-level)
|
||||||
|
zpg-player-exp 0
|
||||||
|
zpg-player-max-health (+ 100 (* zpg-player-level 3)))
|
||||||
|
(zpg-add-log "You leveled up to level %s!" zpg-player-level))
|
||||||
|
(t (setq zpg-player-exp (+ amount zpg-player-exp)))))
|
||||||
|
|
||||||
|
(defun zpg-fight-win-reward ()
|
||||||
|
"This function must be called after you win a fight. It gives a reward,
|
||||||
|
awards EXP, gold and items for this fight, and updates statistics."
|
||||||
|
(let ((exp-awarded (+ 15 (random 100))))
|
||||||
|
(zpg-random-clause
|
||||||
|
;; 40% no reward
|
||||||
|
(40
|
||||||
|
(zpg-add-log "Normal fight won, earned %s xp." exp-awarded))
|
||||||
|
;; 30% gold reward
|
||||||
|
(30
|
||||||
|
(let ((reward (+ (random 95) 5)))
|
||||||
|
(setq zpg-player-gold (+ zpg-player-gold reward))
|
||||||
|
(zpg-add-log "Normal fight won, earned gold: %s, and xp: %s." reward exp-awarded)))
|
||||||
|
;; 30% item reward ('normal 'rare)
|
||||||
|
(30
|
||||||
|
(let ((rarity (zpg-random-clause (10 'normal) (1 'rare))))
|
||||||
|
(if (< (length zpg-player-inventory) zpg-player-inventory-size)
|
||||||
|
(progn
|
||||||
|
(setq zpg-player-inventory
|
||||||
|
(cons
|
||||||
|
(cons (format "%s item" rarity) (list :rarity rarity))
|
||||||
|
zpg-player-inventory))
|
||||||
|
(zpg-add-log
|
||||||
|
"Normal fight won, earned %s exp and a %s item."
|
||||||
|
exp-awarded rarity))
|
||||||
|
(zpg-add-log
|
||||||
|
"Normal fight won, earned %s exp but lost an item due to full inventory."
|
||||||
|
exp-awarded))
|
||||||
|
)))
|
||||||
|
(zpg-award-exp exp-awarded)
|
||||||
|
(setq zpg-statistics-kills (1+ zpg-statistics-kills))))
|
||||||
|
|
||||||
|
(defun zpg-handle-fight ()
|
||||||
|
"Handles the 'fighting' state. See `zpg-game-state'.
|
||||||
|
|
||||||
|
In this state, the hero is fighting an enemy."
|
||||||
|
(zpg-with-state
|
||||||
|
(fighting state)
|
||||||
|
(let ((turn (plist-get state :turn))
|
||||||
|
(enemy-health (plist-get state :health)))
|
||||||
|
|
||||||
|
;; Deal damage
|
||||||
|
(cond ((equal turn 'player)
|
||||||
|
(let ((damage (zpg-roll-player-damage)))
|
||||||
|
(setq state
|
||||||
|
(plist-put state :health
|
||||||
|
(- enemy-health damage)))
|
||||||
|
(setq state
|
||||||
|
(plist-put state :turn 'enemy))
|
||||||
|
;; TODO: incorporate into the status string somehow?
|
||||||
|
;; same for the next thing
|
||||||
|
;; (zpg-add-log
|
||||||
|
;; "Dealt %s damage to enemy. They have %s health left."
|
||||||
|
;; damage
|
||||||
|
;; (plist-get state :health))
|
||||||
|
))
|
||||||
|
((equal turn 'enemy)
|
||||||
|
(let ((damage (zpg-roll-enemy-damage (plist-get state :level))))
|
||||||
|
(setq zpg-player-health (- zpg-player-health damage))
|
||||||
|
(setq state
|
||||||
|
(plist-put state :turn 'player))
|
||||||
|
;; (zpg-add-log
|
||||||
|
;; "Enemy dealt you %s damage. %s health remaining."
|
||||||
|
;; damage
|
||||||
|
;; zpg-player-health)
|
||||||
|
))
|
||||||
|
(t (error "Invalid turn %s" turn)))
|
||||||
|
|
||||||
|
;; Check death conditions
|
||||||
|
(cond ((<= zpg-player-health 0)
|
||||||
|
(setq zpg-game-state (cons 'dead nil)
|
||||||
|
zpg-statistics-death (1+ zpg-statistics-death))
|
||||||
|
(zpg-add-log "You died."))
|
||||||
|
((<= (plist-get state :health) 0)
|
||||||
|
(zpg-fight-win-reward)
|
||||||
|
(setq zpg-game-state (cons 'traveling nil)))))))
|
||||||
|
|
||||||
|
(defun zpg-handle-retreat ()
|
||||||
|
"Handles the 'retreat' state. See `zpg-game-state'.
|
||||||
|
|
||||||
|
This state is entered when the hero has low health, it is very much like
|
||||||
|
the 'traveling' state, except the chances of a fight are low and the
|
||||||
|
movement is backwards."
|
||||||
|
(zpg-with-state
|
||||||
|
(retreat state)
|
||||||
|
;; If we now in town
|
||||||
|
(let* ((towns (sort (zpg-town-positions) :key 'car))
|
||||||
|
(town (alist-get (max zpg-player-position (caar towns)) towns))
|
||||||
|
(target (plist-get state :target)))
|
||||||
|
(if (or
|
||||||
|
(and town (not target))
|
||||||
|
(and town target (equal town target))
|
||||||
|
(equal town (caar zpg-cities)))
|
||||||
|
(progn
|
||||||
|
(setq
|
||||||
|
zpg-game-state
|
||||||
|
(cons 'healing (list :town town)))
|
||||||
|
(zpg-add-log "Entering the town of %s to heal." town))
|
||||||
|
|
||||||
|
(zpg-random-clause
|
||||||
|
(95
|
||||||
|
(setq zpg-player-position (1- zpg-player-position)))
|
||||||
|
(5
|
||||||
|
(zpg-add-log "Entering a fight during a retreat.")
|
||||||
|
(setq
|
||||||
|
zpg-game-state
|
||||||
|
(cons 'fighting
|
||||||
|
(list :name "Enemy" :health 100 :level 1 :turn 'enemy)))))))))
|
||||||
|
|
||||||
|
(defun zpg-handle-healing ()
|
||||||
|
"Handles the 'healing' state. See `zpg-game-state'.
|
||||||
|
|
||||||
|
This state means the players hero is in a town and is slowly healing."
|
||||||
|
(zpg-with-state
|
||||||
|
(healing state)
|
||||||
|
(let ((healing (+ 10 (random 20))))
|
||||||
|
(if (>= (+ zpg-player-health healing) zpg-player-max-health)
|
||||||
|
(progn
|
||||||
|
(setq zpg-player-health zpg-player-max-health)
|
||||||
|
(setq zpg-game-state (cons 'in-town nil))
|
||||||
|
(zpg-add-log "Fully healed up."))
|
||||||
|
(progn
|
||||||
|
(setq zpg-player-health (+ zpg-player-health healing)))))))
|
||||||
|
|
||||||
|
(defun zpg-handle-xp-donation ()
|
||||||
|
"Handles the 'xp-donation' state. See `zpg-game-state'.
|
||||||
|
|
||||||
|
This state is entered when the hero has 20000 gold by the end of
|
||||||
|
healing, and so the hero sacrifices them for 5% of level-up experience."
|
||||||
|
(zpg-with-state
|
||||||
|
(xp-donation state)
|
||||||
|
(setq zpg-player-gold (- zpg-player-gold 20000)
|
||||||
|
zpg-game-state (cons 'in-town '(:no-donation t)))
|
||||||
|
(zpg-award-exp (/ (zpg-level-up-xp) 20))
|
||||||
|
(zpg-add-log "You have sacrificed 20 gold pouches for experience. ")))
|
||||||
|
|
||||||
|
(defun zpg-handle-in-town ()
|
||||||
|
"Handles the 'in-town' state. See `zpg-game-state'."
|
||||||
|
(zpg-with-state
|
||||||
|
(in-town state)
|
||||||
|
;; Donate, but only once
|
||||||
|
(cond ((and (>= zpg-player-gold 20000) (not (plist-get state :no-donation)))
|
||||||
|
(setq zpg-game-state (cons 'xp-donation nil)))
|
||||||
|
;; Sell stuff if we have it
|
||||||
|
((> (length zpg-player-inventory) 0)
|
||||||
|
(setq zpg-game-state (cons 'trading nil)))
|
||||||
|
;; quest completed.
|
||||||
|
((and
|
||||||
|
(equal (zpg-closest-town zpg-player-position) (caar zpg-cities))
|
||||||
|
(plist-get (cdr zpg-current-task) :progress)
|
||||||
|
(>= (plist-get (cdr zpg-current-task) :progress)
|
||||||
|
(plist-get (cdr zpg-current-task) :finish-progress)))
|
||||||
|
(let ((new-gold (cond
|
||||||
|
((equal (car zpg-current-task) 'normal) (+ 4000 (random 2000)))
|
||||||
|
((equal (car zpg-current-task) 'epic) (+ 40000 (random 20000))))))
|
||||||
|
(setq zpg-player-gold (+ zpg-player-gold new-gold))
|
||||||
|
(zpg-add-log "Quest complete! Earned %s gold." new-gold)
|
||||||
|
(setq zpg-current-task '('none))))
|
||||||
|
((not (plist-get (cdr zpg-current-task) :progress))
|
||||||
|
;; TODO: progress-point
|
||||||
|
(zpg-random-clause
|
||||||
|
(50 (setq zpg-current-task (cons 'normal (list :progress 0 :finish-progress 100 :progress-point 199))))
|
||||||
|
(1 (setq zpg-current-task (cons 'epic (list :progress 0 :finish-progress 1000 :progress-point 199)))))
|
||||||
|
(zpg-add-log "Got new quest."))
|
||||||
|
;; if we're broke, no items, maybe revel and go out.
|
||||||
|
(t
|
||||||
|
(if (> (random 5) 2)
|
||||||
|
(let* ((tenth (/ zpg-player-gold 10))
|
||||||
|
(gold-spent (+ (* tenth 4) (random (max tenth 1)))))
|
||||||
|
(setq zpg-player-gold (- zpg-player-gold gold-spent)
|
||||||
|
zpg-game-state (cons 'traveling nil))
|
||||||
|
(zpg-add-log "You spent %s gold in town" gold-spent)))
|
||||||
|
(setq zpg-game-state (cons 'traveling nil))
|
||||||
|
(zpg-add-log "Heading out.")))))
|
||||||
|
|
||||||
|
(defun zpg-list-windows (seq window-length fn)
|
||||||
|
"Applies FN to overlapping subsequences of SEQ of length WINDOW-LENGTH,
|
||||||
|
and makes a list of the results."
|
||||||
|
(let ((window '())
|
||||||
|
(result '())
|
||||||
|
(innerseq (reverse seq)))
|
||||||
|
|
||||||
|
(dotimes (_ window-length)
|
||||||
|
(setq window (cons (car innerseq) window))
|
||||||
|
(setq innerseq (cdr innerseq)))
|
||||||
|
(setq result (cons (apply fn window) result))
|
||||||
|
|
||||||
|
(while innerseq
|
||||||
|
(setf (cdr (last window 2)) nil) ; Remove the last element
|
||||||
|
(setq window (cons (car innerseq) window)
|
||||||
|
innerseq (cdr innerseq)
|
||||||
|
result (cons (apply fn window) result)))
|
||||||
|
|
||||||
|
result))
|
||||||
|
|
||||||
|
(defun zpg-closest-town (point)
|
||||||
|
"Returns the town closest to point. A specialized version of `zpg-list-windows'."
|
||||||
|
(let* ((window '())
|
||||||
|
(result '())
|
||||||
|
(seq (zpg-town-positions))
|
||||||
|
(window-length 2)
|
||||||
|
(fn (lambda (first second)
|
||||||
|
(if (and (>= point (car first)) (<= point (car second)))
|
||||||
|
(if (<= (- point (car first)) (- (car second) point))
|
||||||
|
(cdr first)
|
||||||
|
(cdr second)))))
|
||||||
|
(innerseq (reverse seq)))
|
||||||
|
|
||||||
|
(let
|
||||||
|
((extraresult
|
||||||
|
(catch :finished
|
||||||
|
;; compare with seq because we want the smallest
|
||||||
|
(if (<= point (caar seq))
|
||||||
|
(throw :finished (cdar seq)))
|
||||||
|
|
||||||
|
;; and now the biggest
|
||||||
|
(if (>= point (caar innerseq))
|
||||||
|
(throw :finished (cdar innerseq)))
|
||||||
|
|
||||||
|
(dotimes (_ window-length)
|
||||||
|
(setq window (cons (car innerseq) window))
|
||||||
|
(setq innerseq (cdr innerseq)))
|
||||||
|
(setq result (apply fn window))
|
||||||
|
|
||||||
|
(while (and innerseq (not result))
|
||||||
|
(setf (cdr (last window 2)) nil) ; Remove the last element
|
||||||
|
(setq window (cons (car innerseq) window)
|
||||||
|
innerseq (cdr innerseq)
|
||||||
|
result (apply fn window))))))
|
||||||
|
(if extraresult
|
||||||
|
(setq result extraresult)))
|
||||||
|
|
||||||
|
result))
|
||||||
|
|
||||||
|
(defun zpg-handle-trading ()
|
||||||
|
"Handles the 'trading' state. See `zpg-game-state'.
|
||||||
|
|
||||||
|
In this state, we try to sell all our items."
|
||||||
|
(zpg-with-state
|
||||||
|
(trading state)
|
||||||
|
(let ((item (car zpg-player-inventory)))
|
||||||
|
(if item
|
||||||
|
(progn
|
||||||
|
(setq zpg-player-inventory (cdr zpg-player-inventory)
|
||||||
|
zpg-player-gold
|
||||||
|
(+ zpg-player-gold
|
||||||
|
(let* ((rarity (plist-get (cdr item) :rarity))
|
||||||
|
(base-reward (+ 50 (- 100 (random 115))))
|
||||||
|
(reward
|
||||||
|
(cond
|
||||||
|
((equal rarity 'rare)
|
||||||
|
(+ (random 10) (* base-reward 10)))
|
||||||
|
(t base-reward))))
|
||||||
|
(zpg-add-log "You sold %s for %s gold." (car item) reward)
|
||||||
|
reward))))
|
||||||
|
(progn
|
||||||
|
(setq zpg-game-state (cons 'in-town '(:no-donation t))))))))
|
||||||
|
|
||||||
|
(defun zpg-handle-death ()
|
||||||
|
"Handles the 'dead' state. See `zpg-game-state'."
|
||||||
|
(zpg-with-state
|
||||||
|
(dead state)
|
||||||
|
(let ((closest-town (zpg-closest-town zpg-player-position)))
|
||||||
|
(setq zpg-player-position
|
||||||
|
(plist-get
|
||||||
|
(alist-get closest-town zpg-cities) :pos)
|
||||||
|
zpg-game-state (cons 'traveling nil))
|
||||||
|
(zpg-add-log "Respawning at %s" closest-town))))
|
||||||
|
|
||||||
|
(defvar zpg-state-handlers '((traveling . zpg-handle-travel)
|
||||||
|
(fighting . zpg-handle-fight)
|
||||||
|
(retreat . zpg-handle-retreat)
|
||||||
|
(healing . zpg-handle-healing)
|
||||||
|
(dead . zpg-handle-death)
|
||||||
|
(in-town . zpg-handle-in-town)
|
||||||
|
(xp-donation . zpg-handle-xp-donation)
|
||||||
|
(trading . zpg-handle-trading))
|
||||||
|
"Alist that maps the game states to their respective handlers. See
|
||||||
|
`zpg-game-state'.")
|
||||||
|
|
||||||
|
(defun zpg-level-up-xp ()
|
||||||
|
"Calculates how much experience is needed for a level-up. See
|
||||||
|
`zpg-player-level' and `zpg-player-exp'.
|
||||||
|
|
||||||
|
Currently, to level up you simply need the amount of experience equal to
|
||||||
|
the cube of the level."
|
||||||
|
(* zpg-player-level zpg-player-level zpg-player-level))
|
||||||
|
|
||||||
|
(defun zpg-do-game-step (&optional skip-rendering)
|
||||||
|
"Performs an actual step of the game simulation.
|
||||||
|
|
||||||
|
Each step, the current state (`zpg-game-state') is mapped to its
|
||||||
|
handler (`zpg-state-handlers'), which is then called. The handler is
|
||||||
|
what performs the actual stepping.
|
||||||
|
|
||||||
|
If in zpg-mode buffer, re-renders it after the step is done, unless
|
||||||
|
SKIP-RENDERING is non-nil."
|
||||||
|
(interactive)
|
||||||
|
(let ((current-state (car zpg-game-state)))
|
||||||
|
(funcall (alist-get current-state zpg-state-handlers)))
|
||||||
|
(if (and (equal major-mode 'zpg-mode) (not skip-rendering))
|
||||||
|
(zpg-render))
|
||||||
|
(setq zpg-statistics-steps (1+ zpg-statistics-steps)))
|
||||||
|
|
||||||
|
(defun zpg-create-status-string ()
|
||||||
|
"Returns a string that describes the current state of the player for
|
||||||
|
rendering in the UI."
|
||||||
|
(let ((state-name (car zpg-game-state))
|
||||||
|
(state-value (cdr zpg-game-state)))
|
||||||
|
(cond ((equal state-name 'traveling) "You are currently traveling.\n")
|
||||||
|
((equal state-name 'retreat) "You are currently retreating.\n")
|
||||||
|
((equal state-name 'dead) "You are dead.\n")
|
||||||
|
((equal state-name 'healing)
|
||||||
|
(format "You are currently healing in %s.\n"
|
||||||
|
(plist-get state-value :town)))
|
||||||
|
((equal state-name 'fighting)
|
||||||
|
(format "You are currently fighting against %s. \nThey have %s health remaining."
|
||||||
|
(plist-get state-value :name)
|
||||||
|
(plist-get state-value :health)))
|
||||||
|
((equal state-name 'trading)
|
||||||
|
(format "You are trading in %s\n"
|
||||||
|
(zpg-closest-town zpg-player-position)))
|
||||||
|
((equal state-name 'in-town)
|
||||||
|
(format "You are staying in %s\n"
|
||||||
|
(zpg-closest-town zpg-player-position)))
|
||||||
|
(t ""))))
|
||||||
|
|
||||||
|
(defun zpg-render (&rest args)
|
||||||
|
"Clears and renders the ZPG-mode buffer. Arguments are ignored."
|
||||||
|
(if (not (equal major-mode 'zpg-mode))
|
||||||
|
(error "Must be called only in zpg-mode buffers."))
|
||||||
|
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(erase-buffer)
|
||||||
|
(insert
|
||||||
|
(format "Health: %s / %s\n"
|
||||||
|
zpg-player-health
|
||||||
|
zpg-player-max-health))
|
||||||
|
(insert (format "Position: %s\n" zpg-player-position))
|
||||||
|
(insert (format "Level: %s\n" zpg-player-level))
|
||||||
|
(insert (format "EXP: %s\n" zpg-player-exp))
|
||||||
|
(insert (format "Gold: %s\n" zpg-player-gold))
|
||||||
|
(insert
|
||||||
|
(format "Current quest: %s. Progress: %s / %s\n"
|
||||||
|
(car zpg-current-task)
|
||||||
|
(plist-get (cdr zpg-current-task) :progress)
|
||||||
|
(plist-get (cdr zpg-current-task) :finish-progress)))
|
||||||
|
(insert (zpg-create-status-string) "\n\n")
|
||||||
|
(insert "Inventory:\n")
|
||||||
|
(dolist (i zpg-player-inventory)
|
||||||
|
(insert (format "%s\n" (car i))))
|
||||||
|
(insert "\nHere is the current log lol: \n")
|
||||||
|
(dolist (log (take zpg-log-size zpg-log))
|
||||||
|
(insert log "\n"))
|
||||||
|
(insert "\nSome stats for you:\n")
|
||||||
|
(insert (format "In total, you killed %s enemies.\n" zpg-statistics-kills))
|
||||||
|
(insert (format "In total, you died %s times.\n" zpg-statistics-death))
|
||||||
|
(insert (format "A total of %s steps were simulated.\n" zpg-statistics-steps)))
|
||||||
|
(goto-char (point-min)))
|
||||||
|
|
||||||
|
(defun zpg-fast-forward (steps)
|
||||||
|
"Performs the specified amount of steps of the game."
|
||||||
|
(interactive "nHow many steps to fast-forward? ")
|
||||||
|
(dotimes (i steps)
|
||||||
|
(zpg-do-game-step t))
|
||||||
|
(zpg-render))
|
||||||
|
|
||||||
|
(defun zpg-toggle-autostep ()
|
||||||
|
"Starts or stops the auto stepping timer. See `zpg-step-timeout'."
|
||||||
|
(interactive)
|
||||||
|
(if zpg--step-timer
|
||||||
|
(progn
|
||||||
|
(cancel-timer zpg--step-timer)
|
||||||
|
(setq zpg--step-timer nil)
|
||||||
|
(message "Disabled auto-stepping."))
|
||||||
|
(progn
|
||||||
|
(setq zpg--step-timer
|
||||||
|
(run-at-time t zpg-step-timeout 'zpg-do-game-step))
|
||||||
|
(message "Enabled auto-stepping."))))
|
||||||
|
|
||||||
|
(defun zpg-save ()
|
||||||
|
"Saves the current game in `zpg-save-location'. See `zpg-loadables'."
|
||||||
|
(interactive)
|
||||||
|
(let ((data '()))
|
||||||
|
(dolist (item zpg-loadables)
|
||||||
|
(setq data (cons (list (car item) (symbol-value (cdr item))) data)))
|
||||||
|
(with-temp-file zpg-save-location
|
||||||
|
(prin1 data (current-buffer))))
|
||||||
|
(message (format "Saved to %s" zpg-save-location)))
|
||||||
|
|
||||||
|
(defun zpg-load ()
|
||||||
|
"Loads the game saved in `zpg-save-location'. See `zpg-loadables'."
|
||||||
|
(let ((data (with-temp-buffer
|
||||||
|
(insert-file-contents zpg-save-location)
|
||||||
|
(read (current-buffer)))))
|
||||||
|
(dolist (item data)
|
||||||
|
(set (alist-get (car item) zpg-loadables) (cadr item)))))
|
||||||
|
|
||||||
|
(defvar zpg-mode-map
|
||||||
|
(let ((map (make-sparse-keymap)))
|
||||||
|
(set-keymap-parent map special-mode-map)
|
||||||
|
(define-key map (kbd "s") 'zpg-do-game-step)
|
||||||
|
(define-key map (kbd "S") 'zpg-fast-forward)
|
||||||
|
(define-key map (kbd "t") 'zpg-toggle-autostep)
|
||||||
|
map)
|
||||||
|
"Keymap for `zpg-mode'.")
|
||||||
|
|
||||||
|
(define-derived-mode zpg-mode special-mode
|
||||||
|
"ZPG"
|
||||||
|
"A zero player game in Emacs."
|
||||||
|
:interactive nil
|
||||||
|
(setq-local revert-buffer-function 'zpg-render)
|
||||||
|
(add-hook 'window-selection-change-functions 'zpg-render nil t)
|
||||||
|
(zpg-render))
|
||||||
|
|
||||||
|
(defun zpg ()
|
||||||
|
"Starts the zpg-mode buffer."
|
||||||
|
(interactive)
|
||||||
|
(let ((buffer (get-buffer-create "*zpg*")))
|
||||||
|
(pop-to-buffer-same-window buffer)
|
||||||
|
(zpg-mode)))
|
||||||
|
|
||||||
|
(provide 'zpg)
|
||||||
|
|
||||||
|
;; Local Variables:
|
||||||
|
;; eval: (add-to-list 'imenu-generic-expression '("Variables" "^\\s-*(\\(defvar-zpg\\)\\s-+\\(\\(?:\\w\\|\\s_\\|\\\\.\\)+\\)" 2))
|
||||||
|
;; End:
|
||||||
|
|
||||||
|
;;; zpg.el ends here
|
||||||
104
post-init.el
Normal file
104
post-init.el
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
;;; post-init.el --- This file is loaded after init.el. -*- no-byte-compile: t; lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(load-theme 'modus-operandi)
|
||||||
|
|
||||||
|
(set-face-attribute 'default nil :height 110 :font "Iosevka Nerd Font" :weight 'normal)
|
||||||
|
(setq initial-frame-alist
|
||||||
|
'((width . 100) (height . 25)))
|
||||||
|
|
||||||
|
;; Use straight.el for package management, integrate with use-package.
|
||||||
|
(setq straight-use-package-by-default t)
|
||||||
|
|
||||||
|
(defvar bootstrap-version)
|
||||||
|
(let ((bootstrap-file
|
||||||
|
(expand-file-name
|
||||||
|
"straight/repos/straight.el/bootstrap.el"
|
||||||
|
(or (bound-and-true-p straight-base-dir)
|
||||||
|
user-emacs-directory)))
|
||||||
|
(bootstrap-version 7))
|
||||||
|
(unless (file-exists-p bootstrap-file)
|
||||||
|
(with-current-buffer
|
||||||
|
(url-retrieve-synchronously
|
||||||
|
"https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
|
||||||
|
'silent 'inhibit-cookies)
|
||||||
|
(goto-char (point-max))
|
||||||
|
(eval-print-last-sexp)))
|
||||||
|
(load bootstrap-file nil 'nomessage))
|
||||||
|
|
||||||
|
(unless (memq 'use-package-autoloads features)
|
||||||
|
(straight-use-package 'use-package))
|
||||||
|
|
||||||
|
;; This should be loaded as early as possible
|
||||||
|
(use-package compile-angel
|
||||||
|
:demand t
|
||||||
|
:custom
|
||||||
|
(compile-angel-verbose nil)
|
||||||
|
:config
|
||||||
|
(compile-angel-on-load-mode)
|
||||||
|
(add-hook 'emacs-lisp-mode-hook #'compile-angel-on-save-local-mode))
|
||||||
|
|
||||||
|
;; Minibuffers and stuff
|
||||||
|
(setq enable-recursive-minibuffers t)
|
||||||
|
(which-key-mode t)
|
||||||
|
|
||||||
|
;; Modeline
|
||||||
|
(display-time-mode)
|
||||||
|
(setq display-time-24hr-format t)
|
||||||
|
|
||||||
|
(use-package diminish
|
||||||
|
:ensure t)
|
||||||
|
|
||||||
|
;; Since diminish was loaded after compile-angel, we cannot use the use-package
|
||||||
|
;; integration to diminish it. So, we do it manually here. Also, built-in modes.1
|
||||||
|
(diminish 'compile-angel-on-save-local-mode)
|
||||||
|
(diminish 'compile-angel-on-load-mode)
|
||||||
|
(diminish 'eldoc-mode)
|
||||||
|
(diminish 'which-key-mode)
|
||||||
|
|
||||||
|
;; Avoid backups or lockfiles to prevent creating world-readable copies of files
|
||||||
|
(setq create-lockfiles nil)
|
||||||
|
(setq make-backup-files nil)
|
||||||
|
|
||||||
|
(setq backup-directory-alist
|
||||||
|
`((".*" . ,(expand-file-name "backup" user-emacs-directory))))
|
||||||
|
(setq tramp-backup-directory-alist backup-directory-alist)
|
||||||
|
(setq backup-by-copying-when-linked t)
|
||||||
|
(setq backup-by-copying t) ; Backup by copying rather renaming
|
||||||
|
(setq delete-old-versions t) ; Delete excess backup versions silently
|
||||||
|
(setq version-control t) ; Use version numbers for backup files
|
||||||
|
(setq kept-new-versions 5)
|
||||||
|
(setq kept-old-versions 5)
|
||||||
|
|
||||||
|
;; Syntax highlights
|
||||||
|
(setq treesit-font-lock-level 4)
|
||||||
|
|
||||||
|
;; NixOS Specific
|
||||||
|
(if (functionp 'nix--profile-paths)
|
||||||
|
(progn
|
||||||
|
(unless (memq 'nix-ts-mode features)
|
||||||
|
(load "nix-ts-mode" t)
|
||||||
|
(unless (memq 'nix-ts-mode features)
|
||||||
|
(warn "Failed to load nix-ts-mode. It is probably not installed."))))
|
||||||
|
(progn
|
||||||
|
(message "Not on NixOS. Will try to install packages usually managed by it through use-package.")
|
||||||
|
|
||||||
|
(use-package vterm
|
||||||
|
:defer t
|
||||||
|
:ensure t)
|
||||||
|
|
||||||
|
(use-package nix-ts-mode
|
||||||
|
:defer t
|
||||||
|
:ensure t)))
|
||||||
|
|
||||||
|
;; LSP and stuff
|
||||||
|
(add-hook 'nix-ts-mode-hook 'eglot-ensure)
|
||||||
|
(add-to-list 'auto-mode-alist '("\\.nix\\'" . nix-ts-mode))
|
||||||
|
|
||||||
|
;; Load the configs from plug-in files.
|
||||||
|
(let ((config-dir (concat minimal-emacs-user-directory ".config.d")))
|
||||||
|
(if (not (file-exists-p config-dir))
|
||||||
|
(make-directory config-dir))
|
||||||
|
(dolist (lisp-file (directory-files config-dir t directory-files-no-dot-files-regexp))
|
||||||
|
(load lisp-file nil 'nomessage)))
|
||||||
|
|
||||||
|
;;; post-init.el ends here
|
||||||
8
pre-early-init.el
Normal file
8
pre-early-init.el
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
;;; pre-early-init.el --- This file is loaded before early-init.el. -*- no-byte-compile: t; lexical-binding: t; -*-
|
||||||
|
|
||||||
|
;; Reducing clutter in ~/.emacs.d by redirecting files to ~/emacs.d/var/
|
||||||
|
(setq minimal-emacs-var-dir (expand-file-name "var/" minimal-emacs-user-directory))
|
||||||
|
(setq package-user-dir (expand-file-name "elpa" minimal-emacs-var-dir))
|
||||||
|
(setq user-emacs-directory minimal-emacs-var-dir)
|
||||||
|
|
||||||
|
;;; pre-early-init.el ends here
|
||||||
12
templates
Normal file
12
templates
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
;;; -*- mode: lisp-data; -*-
|
||||||
|
|
||||||
|
emacs-lisp-mode
|
||||||
|
|
||||||
|
(up "(use-package " p n> ":ensure t" n> ":defer t" n ")")
|
||||||
|
|
||||||
|
rust-mode
|
||||||
|
|
||||||
|
(str "struct " p " {" n> p n> "}")
|
||||||
|
(imp "impl " p " {" n> p n> "}")
|
||||||
|
(impf "impl " p " for " p " {" n> p n> "}")
|
||||||
|
(trt "trait " p " {" n> p n> "}")
|
||||||
Reference in New Issue
Block a user