Emacs : config restruction with crafted-emacs

This commit is contained in:
2023-01-10 19:21:27 +09:00
parent 1e55f1962d
commit 8e6f9119ca
18 changed files with 1904 additions and 0 deletions

View File

@ -0,0 +1,120 @@
;;;; crafted-package/package.el --- Configuration to use `package.el'. -*- lexical-binding: t; -*-
;; Copyright (C) 2022
;; SPDX-License-Identifier: MIT
;; Author: System Crafters Community
;;; Commentary:
;; Bootstrap `package.el' configuration. This is the default package
;; manager for Crafted Emacs. Code provided herein is intended for
;; internal use, the user is not expected to use the interface
;; provided here to manage their packages. In fact, should the user
;; prefer to use `use-package' in their configuration, that should
;; work seamlessly with this configuration. The user will need to
;; install `use-package', of course. That being said, the user is
;; welcome to use the macros presented here. They provide
;; `crafted-emacs' a standard way to install packages in the modules
;; provided as we can't predict if the user will choose to use
;; `package.el' or some other tool.
;;; Code:
;; package configuration
(require 'package)
(require 'time-date)
;; Emacs 27.x has gnu elpa as the default
;; Emacs 28.x adds the nongnu elpa to the list by default, so only
;; need to add nongnu when this isn't Emacs 28+
(when (version< emacs-version "28")
(add-to-list 'package-archives '("nongnu" . "https://elpa.nongnu.org/nongnu/")))
(add-to-list 'package-archives '("stable" . "https://stable.melpa.org/packages/"))
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(customize-set-variable 'package-archive-priorities
'(("gnu" . 99) ; prefer GNU packages
("nongnu" . 80) ; use non-gnu packages if
; not found in GNU elpa
("stable" . 70) ; prefer "released" versions
; from melpa
("melpa" . 0))) ; if all else fails, get it
; from melpa
(customize-set-variable 'package-user-dir
(expand-file-name "elpa/" crafted-config-path))
;; make sure the elpa/ folder exists after setting it above.
(unless (file-exists-p package-user-dir)
(mkdir package-user-dir t))
(defvar crafted-bootstrap-package-perform-stale-archive-check t
"Flag to allow the user to turn off checking if an archive is
stale on startup.")
(defvar crafted-bootstrap-package-update-days 1
"The number of days old a package archive must be before it is
considered stale.")
;;; package configuration
(defun crafted-package-archive-stale-p (archive)
"Return `t' if ARCHIVE is stale.
ARCHIVE is stale if the on-disk cache is older than
`crafted-bootstrap-package-update-days' old. If
`crafted-bootstrap-package-perform-stale-archive-check' is nil,
the check is skipped."
(let* ((today (decode-time nil nil t))
(archive-name (expand-file-name
(format "archives/%s/archive-contents" archive)
package-user-dir))
(last-update-time (decode-time (file-attribute-modification-time
(file-attributes archive-name))))
(delta (make-decoded-time :day crafted-bootstrap-package-update-days)))
(if crafted-bootstrap-package-perform-stale-archive-check
(time-less-p (encode-time (decoded-time-add last-update-time delta))
(encode-time today))
nil)))
(defun crafted-package-archives-stale-p ()
"Return `t' if any PACKAGE-ARHIVES cache is out of date.
Check each archive listed in PACKAGE-ARCHIVES, if the on-disk
cache is older than 1 day, return a non-nil value. Fails fast,
will return `t' for the first stale archive found or `nil' if
they are all up-to-date."
(interactive)
(cl-some #'crafted-package-archive-stale-p (mapcar #'car package-archives)))
(defmacro crafted-package-install-package (package)
"Only install the package if it is not already installed."
`(unless (package-installed-p ,package) (package-install ,package)))
(defmacro crafted-package-installed-p (package)
`(package-installed-p ,package))
(defun crafted-package-initialize ()
"Initialize the package system."
;; Only use package.el if it is enabled. The user may have turned it
;; off in their `early-config.el' file, so respect their wishes if so.
(when package-enable-at-startup
(package-initialize)
(require 'seq)
;; Only refresh package contents once per day on startup, or if the
;; `package-archive-contents' has not been initialized. If Emacs has
;; been running for a while, user will need to manually run
;; `package-refresh-contents' before calling `package-install'.
(cond ((seq-empty-p package-archive-contents)
(progn
(message "crafted-init: package archives empty, initializing")
(package-refresh-contents)))
((crafted-package-archives-stale-p)
(progn
(message "crafted-init: package archives stale, refreshing in the background")
(package-refresh-contents t))))
))
(provide 'crafted-package/package)
;;; crafted-package/package.el ends here

View File

@ -0,0 +1,66 @@
;;;; crafted-package.el --- Configuration to use `package.el'. -*- lexical-binding: t; -*-
;; Copyright (C) 2022
;; SPDX-License-Identifier: MIT
;; Author: System Crafters Community
;;; Commentary:
;; This library provides a package related interface for
;; `crafted-emacs'.
;; So far, it has two backends:
;; - `package.el' -- The default.
;; - `straight.el' -- A popular option.
;; Other backends could be added. To add a backend, add the name to
;; the list above, provide a bootstrap file (the name must match
;; `crafted-%s-bootstrap.el' or it will fail to be loaded with this
;; code), and make sure to implement the following macros (at a
;; minimum):
;;
;; `crafted-package-install-package' which should receive a package to
;; install and perform the appropriate operations to install that
;; package.
;;
;; `crafted-package-installed-p' which should identify if a package is
;; installed (ie, it should return `t' if the package is installed and
;; `nil' otherwise)
;;
;; See the bootstrap files in this directory for examples. The macros
;; mentioned above are intended to provide a consistent interface for
;; the modules to use when installing packages. The user is not
;; expected to use them in their own configuration, but they may if
;; they choose. Or they may choose a different interface, like
;; `use-package' or `leaf'.
;;; Code:
(defvar crafted-package-system 'package
"What package system to use.
By default, it uses 'package for `package.el'. Another option is
'straight for `straight.el'.")
(defun crafted-package-bootstrap (&optional system)
"Load the configuration and defaults to the selected package.
This will check for the value of the variable
`crafted-package-system', but could be overriden with the
optional parameter SYSTEM.
This is called when `early-init.el' runs."
(let* ((module (make-symbol (format "crafted-%s-bootstrap.el"
(symbol-name (or system
crafted-package-system
;; In case both above are nil
'package)))))
(module-path (expand-file-name (symbol-name module) crafted-bootstrap-directory)))
(if (file-exists-p module-path)
(load module-path)
(error "Could not find module %s" module))))
(provide 'crafted-package)
;;; crafted-package.el ends here

View File

@ -0,0 +1,56 @@
;;;; crafted-package/straight.el --- Configuration to use `straigt.el`. -*- lexical-binding: t; -*-
;; Copyright (C) 2022
;; SPDX-License-Identifier: MIT
;; Author: System Crafters Community
;;; Commentary:
;; This code loads the bootstrap code for `straight.el', according as
;; described in <https://github.com/radian-software/straight.el>.
;; Bootstrap `straight.el' configuration, as described in
;; <https://github.com/radian-software/straight.el>. Code provided
;; herein is intended for internal use, the user is not expected to
;; use the interface provided here to manage their packages. In fact,
;; should the user prefer to use `use-package' in their configuration,
;; that should work seamlessly with this configuration. The user will
;; need to install `use-package', of course. That being said, the
;; user is welcome to use the macros presented here. They provide
;; `crafted-emacs' a standard way to install packages in the modules
;; provided as we can't predict if the user will choose to use
;; `straight.el' or some other tool.
;;; Code:
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" crafted-config-path))
(bootstrap-version 6))
;; moves the straight install directory to the users crafted
;; configuration folder rather than the `user-emacs-directory'
(setq straight-base-dir crafted-config-path)
(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))
(defmacro crafted-package-install-package (package)
"Crafted Emacs interface to install packages.
Only install the package if it is not already installed using
straight.el."
`(straight-use-package ,package))
(defmacro crafted-package-installed-p (package)
"Crafted Emacs interface to check if a package is installed."
`(straight--installed-p ,package))
(provide 'crafted-package/straight)
;;; crafted-package/straight.el ends here

48
.config/emacs/config.el Normal file
View File

@ -0,0 +1,48 @@
(require 'crafted-defaults) ; Sensible Default settings for Emacs
(require 'crafted-updates) ; Tools to upgrade Crafted Emacs
(require 'crafted-completion) ; selection framework based on 'vertico'
(require 'crafted-ui) ; Better UI experience (modeline etc..)
;;(require 'crafted-windows) ; Window management configuration
(require 'crafted-evil) ; An 'evil-mode' configuration
;;(require 'custom-evil) ; An 'evil-mode' configuration
(setq-default tab-width 4)
(defvaralias 'c-basic-offset 'tab-width)
(setq default-input-method "korean-hangul")
(global-set-key (kbd "<Hangul>") 'toggle-input-method)
(setq user-full-name "JaeYoo-Im"
user-mail-address "cpu3792@gmail.com")
;; Line numbers
(column-number-mode)
(global-display-line-numbers-mode t)
(dolist (mode '(org-mode-hook
vterm-mode-hook
dired-mode-hook
;;shell-mode-hook
;;treemacs-mode-hook
eshell-mode-hook))
(add-hook mode (lambda () (display-line-numbers-mode 0))))
(add-hook 'emacs-startup-hook
(lambda ()
(custom-set-faces
`(default ((t (:font "Fira Code 10"))))
`(fixed-pitch ((t (:inherit (default)))))
`(fixed-pitch-serif ((t (:inherit (default)))))
`(variable-pitch ((t (:font "Ubuntu 10")))))))
(set-fontset-font t `hangul (font-spec :name "NanumGothic"))
;; loading themes
(crafted-package-install-package 'doom-themes)
(progn
(disable-theme 'deeper-blue) ; first turn off the deeper-blue theme
(if (display-graphic-p)
(load-theme 'doom-palenight t)
(load-theme 'doom-gruvbox t))
(unless (display-graphic-p)
(xterm-mouse-mode)))
(require 'custom-dashboard)

View File

@ -0,0 +1,63 @@
;;; early-init.el -*- lexical-binding: t; -*-
;;; Garbage collection
;; Increase the GC threshold for faster startup
;; The default is 800 kilobytes. Measured in bytes.
(setq gc-cons-threshold (* 50 1000 1000))
;;; Emacs lisp source/compiled preference
;; Prefer loading newest compiled .el file
(customize-set-variable 'load-prefer-newer t)
(defvar crafted-config-path "~/.cache/emacs")
(unless (file-exists-p crafted-config-path)
(mkdir crafted-config-path t))
;;; Native compilation settings
(when (featurep 'native-compile)
;; Silence compiler warnings as they can be pretty disruptive
(setq native-comp-async-report-warnings-errors nil)
;; Make native compilation happens asynchronously
(setq native-comp-deferred-compilation t)
;; Set the right directory to store the native compilation cache
;; NOTE the method for setting the eln-cache directory depends on the emacs version
(when (fboundp 'startup-redirect-eln-cache)
(if (version< emacs-version "29")
(add-to-list 'native-comp-eln-load-path (convert-standard-filename (expand-file-name "var/eln-cache/" user-emacs-directory)))
(startup-redirect-eln-cache (convert-standard-filename (expand-file-name "var/eln-cache/" user-emacs-directory)))))
(add-to-list 'native-comp-eln-load-path (expand-file-name "eln-cache/" user-emacs-directory)))
;;; UI configuration
;; Remove some unneeded UI elements (the user can turn back on anything they wish)
(setq inhibit-startup-message t)
(push '(tool-bar-lines . 0) default-frame-alist)
(push '(menu-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)
(push '(mouse-color . "white") default-frame-alist)
;; Loads a nice blue theme, avoids the white screen flash on startup.
(load-theme 'deeper-blue t)
;; Make the initial buffer load faster by setting its mode to fundamental-mode
(customize-set-variable 'initial-major-mode 'fundamental-mode)
;;; Package system
;; Load the package-system. If needed, the user could customize the
;; system to use in `early-config.el'.
(defvar crafted-bootstrap-directory (expand-file-name "bootstrap/" user-emacs-directory)
"Package system bootstrap configuration.")
(load (expand-file-name "crafted-package.el" crafted-bootstrap-directory))
(when (eq crafted-package-system 'package)
;; needed in case `early-config.el' has pinned packages configured
(require 'package))
;; this is the default
;; (setq crafted-package-system 'package)
;; use this in `early-config.el' to switch to `straight.el'
;; (setq crafted-package-system 'straight)
(crafted-package-bootstrap crafted-package-system)

66
.config/emacs/init.el Normal file
View File

@ -0,0 +1,66 @@
;;; init.el -*- lexical-binding: t; -*-
;; Profile emacs startup
(add-hook 'emacs-startup-hook
(lambda ()
(message "Crafted Emacs loaded in %s."
(emacs-init-time))))
(when (eq crafted-package-system 'package)
(crafted-package-initialize))
;; Add the modules folder to the load path
(add-to-list 'load-path (expand-file-name "modules/" user-emacs-directory))
;; Set default coding system (especially for Windows)
(set-default-coding-systems 'utf-8)
(customize-set-variable 'visible-bell 1) ; turn off beeps, make them flash!
(customize-set-variable 'large-file-warning-threshold 100000000) ;; change to ~100 MB
(defun crafted-ensure-package (package &optional args)
"Ensure that PACKAGE is installed on the system, either via
package.el or Guix depending on the value of
`crafted-prefer-guix-packages'."
(if crafted-prefer-guix-packages
(unless (featurep package)
(message "Package '%s' does not appear to be installed by Guix: " package))
(crafted-package-install-package package)))
;; Check the system used
(defconst ON-LINUX (eq system-type 'gnu/linux))
(defconst ON-MAC (eq system-type 'darwin))
(defconst ON-BSD (or ON-MAC (eq system-type 'berkeley-unix)))
(defconst ON-WINDOWS (memq system-type '(cygwin windows-nt ms-dos)))
;; Defines the user configuration var and etc folders
;; and ensure they exist.
(defvar crafted-config-etc-directory (expand-file-name "etc/" crafted-config-path)
"The user's configuration etc/ folder.")
(defvar crafted-config-var-directory (expand-file-name "var/" crafted-config-path)
"The user's configuration var/ folder.")
(mkdir crafted-config-etc-directory t)
(mkdir crafted-config-var-directory t)
;; Find the user configuration file
(defvar crafted-config-file (expand-file-name "config.el" "~/.config/emacs")
"The user's configuration file.")
;; Load the user configuration file if it exists
(when (file-exists-p crafted-config-file)
(load crafted-config-file nil 'nomessage))
;; Make GC pauses faster by decreasing the threshold.
(setq gc-cons-threshold (* 2 1000 1000))
(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.
'(package-selected-packages '(doom-themes)))
(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.
)

View File

@ -0,0 +1,198 @@
jjjjjjjjjjj;;; crafted-ui.el -*- lexical-binding: t; -*-
;; Copyright (C) 2022
;; SPDX-License-Identifier: MIT
;; Author: System Crafters Community
;; Commentary
;; User interface customizations. Examples are the modeline and how
;; help buffers are displayed.
;; This package provides a basic, customized appearance for
;; Emacs. Specifically, it uses: Helpful to customize the information
;; and visual display of help buffers, such as that created by M-x
;; `describe-function'; Doom Modeline and Themes, to customize the
;; appearance of buffers, text, et cetera; All-the-icons, to provide
;; Doom Modeline with font-based icons (rather than raster or vector
;; images); and includes some Emacs Lisp demonstrations.
;;  Run `all-the-icons-install-fonts' to ensure the fonts necessary
;; for ALL THE ICONS are available on your system. You must run this
;; function if the "stop" icon at the beginning of this paragraph is
;; not displayed properly (it appears as a box with some numbers
;; and/or letters inside it).
;; Read the documentation for `all-the-icons'; on Windows,
;; `all-the-icons-install-fonts' only downloads fonts, they must be
;; installed manually. This is necessary if icons are not displaying
;; properly.
;;; Code:
(crafted-package-install-package 'all-the-icons)
(crafted-package-install-package 'elisp-demos)
(crafted-package-install-package 'helpful)
;;;; Font
(defun crafted-ui--set-default-font (spec)
"Set the default font based on SPEC.
SPEC is expected to be a plist with the same key names
as accepted by `set-face-attribute'."
(when spec
(apply 'set-face-attribute 'default nil spec)))
(defun crafted-ui--toggle-doom-modeline-mode (state)
"Turn on/off doom-modeline-mode if it is installed.
STATE is either 1 to turn the mode on, or -1 to turn it off."
(when (package-installed-p 'doom-modeline)
(doom-modeline-mode state)))
(defgroup crafted-ui '()
"User interface related configuration for Crafted Emacs."
:tag "Crafted UI"
:group 'crafted)
(define-obsolete-variable-alias
'rational-ui-default-font
'crafted-ui-default-font
"1")
(defcustom crafted-ui-default-font nil
"The configuration of the `default' face.
Use a plist with the same key names as accepted by `set-face-attribute'."
:group 'crafted-ui
:type '(plist :key-type: symbol)
:tag "Default font"
:set (lambda (sym val)
(let ((prev-val (if (boundp 'crafted-ui-default-font)
crafted-ui-default-font
nil)))
(set-default sym val)
(when (and val (not (eq val prev-val)))
(crafted-ui--set-default-font val)))))
;;;; Mode-Line
(defcustom crafted-ui-use-doom-modeline nil
"Use doom-modeline-mode."
:group 'crafted-ui
:type 'boolean
:tag "Use Doom Modeline"
:set (lambda (sym val)
(set-default sym val)
(if val
(crafted-ui--toggle-doom-modeline-mode 1)
(crafted-ui--toggle-doom-modeline-mode -1))))
;; Configure `doom-modeline' if it is enabled
(when crafted-ui-use-doom-modeline
(crafted-package-install-package 'doom-modeline)
(customize-set-variable 'doom-modeline-height 15)
(customize-set-variable 'doom-modeline-bar-width 6)
(customize-set-variable 'doom-modeline-minor-modes t)
(customize-set-variable 'doom-modeline-buffer-file-name-style 'truncate-except-project))
;;;; Help Buffers
;; Make `describe-*' screens more helpful
(require 'helpful)
(define-key helpful-mode-map [remap revert-buffer] #'helpful-update)
(global-set-key [remap describe-command] #'helpful-command)
(global-set-key [remap describe-function] #'helpful-callable)
(global-set-key [remap describe-key] #'helpful-key)
(global-set-key [remap describe-symbol] #'helpful-symbol)
(global-set-key [remap describe-variable] #'helpful-variable)
(global-set-key (kbd "C-h F") #'helpful-function)
;; Bind extra `describe-*' commands
(global-set-key (kbd "C-h K") #'describe-keymap)
;;;; Line Numbers
(define-obsolete-variable-alias
'rational-ui-line-numbers-enabled-modes
'crafted-ui-line-numbers-enabled-modes
"1")
(defcustom crafted-ui-line-numbers-enabled-modes
'(conf-mode prog-mode)
"Modes which should display line numbers."
:type 'list
:group 'crafted-ui)
(define-obsolete-variable-alias
'rational-ui-line-numbers-disabled-modes
'crafted-ui-line-numbers-disabled-modes
"1")
(defcustom crafted-ui-line-numbers-disabled-modes
'(org-mode)
"Modes which should not display line numbers.
Modes derived from the modes defined in
`crafted-ui-line-number-enabled-modes', but should not display line numbers."
:type 'list
:group 'crafted-ui)
(defun crafted-ui--enable-line-numbers-mode ()
"Turn on line numbers mode.
Used as hook for modes which should display line numbers."
(display-line-numbers-mode 1))
(defun crafted-ui--disable-line-numbers-mode ()
"Turn off line numbers mode.
Used as hook for modes which should not display line numebrs."
(display-line-numbers-mode -1))
(defun crafted-ui--update-line-numbers-display ()
"Update configuration for line numbers display."
(if crafted-ui-display-line-numbers
(progn
(dolist (mode crafted-ui-line-numbers-enabled-modes)
(add-hook (intern (format "%s-hook" mode))
#'crafted-ui--enable-line-numbers-mode))
(dolist (mode crafted-ui-line-numbers-disabled-modes)
(add-hook (intern (format "%s-hook" mode))
#'crafted-ui--disable-line-numbers-mode))
(setq-default
display-line-numbers-grow-only t
display-line-numbers-type t
display-line-numbers-width 2))
(progn
(dolist (mode crafted-ui-line-numbers-enabled-modes)
(remove-hook (intern (format "%s-hook" mode))
#'crafted-ui--enable-line-numbers-mode))
(dolist (mode crafted-ui-line-numbers-disabled-modes)
(remove-hook (intern (format "%s-hook" mode))
#'crafted-ui--disable-line-numbers-mode)))))
(define-obsolete-variable-alias
'rational-ui-display-line-numbers
'crafted-ui-display-line-numbers
"1")
(defcustom crafted-ui-display-line-numbers nil
"Whether line numbers should be enabled."
:type 'boolean
:group 'crafted-ui
:set (lambda (sym val)
(set-default sym val)
(crafted-ui--update-line-numbers-display)))
;;;; Elisp-Demos
;; also add some examples
(require 'elisp-demos)
(advice-add 'helpful-update :after #'elisp-demos-advice-helpful-update)
;; add visual pulse when changing focus, like beacon but built-in
;; from from https://karthinks.com/software/batteries-included-with-emacs/
(defun pulse-line (&rest _)
"Pulse the current line."
(pulse-momentary-highlight-one-line (point)))
(dolist (command '(scroll-up-command scroll-down-command
recenter-top-bottom other-window))
(advice-add command :after #'pulse-line))
(provide 'crafted-ui)
;;; crafted-ui.el ends here

View File

@ -0,0 +1,153 @@
;;; crafted-completion.el --- Crafted Completion Configuration -*- lexical-binding: t; -*-
;; Copyright (C) 2022
;; SPDX-License-Identifier: MIT
;; Author: System Crafters Community
;;; Commentary:
;; Setup completion packages. Completion in this sense is more like
;; narrowing, allowing the user to find matches based on minimal
;; inputs and "complete" the commands, variables, etc from the
;; narrowed list of possible choices.
;;; Code:
(crafted-package-install-package 'cape)
(crafted-package-install-package 'consult)
(crafted-package-install-package 'corfu)
(crafted-package-install-package 'corfu-terminal)
(crafted-package-install-package 'embark)
(crafted-package-install-package 'embark-consult)
(crafted-package-install-package 'marginalia)
(crafted-package-install-package 'orderless)
(crafted-package-install-package 'vertico)
(defun crafted-completion/minibuffer-backward-kill (arg)
"Delete word or delete up to parent folder when completion is a file.
ARG is the thing being completed in the minibuffer."
(interactive "p")
(if minibuffer-completing-file-name
;; Borrowed from https://github.com/raxod502/selectrum/issues/498#issuecomment-803283608
(if (string-match-p "/." (minibuffer-contents))
(zap-up-to-char (- arg) ?/)
(delete-minibuffer-contents))
(backward-kill-word arg)))
;;; Vertico
(require 'vertico)
;; Straight and Package bundle the vertico package differently. When
;; using `package.el', the extensions are built into the package and
;; available on the load-path. When using `straight.el', the
;; extensions are not built into the package, so have to add that path
;; to the load-path manually to enable the following require.
(when (eq crafted-package-system 'straight)
(add-to-list 'load-path
(expand-file-name "straight/build/vertico/extensions"
straight-base-dir)))
(require 'vertico-directory)
(with-eval-after-load 'evil
(define-key vertico-map (kbd "C-j") 'vertico-next)
(define-key vertico-map (kbd "C-k") 'vertico-previous)
(define-key vertico-map (kbd "M-h") 'vertico-directory-up))
;; Cycle back to top/bottom result when the edge is reached
(customize-set-variable 'vertico-cycle t)
;; Start Vertico
(vertico-mode 1)
;;; Marginalia
;; Configure Marginalia
(require 'marginalia)
(customize-set-variable 'marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
(marginalia-mode 1)
;; Set some consult bindings
(global-set-key (kbd "C-s") 'consult-line)
(define-key minibuffer-local-map (kbd "C-r") 'consult-history)
(setq completion-in-region-function #'consult-completion-in-region)
;;; Orderless
;; Set up Orderless for better fuzzy matching
(require 'orderless)
(customize-set-variable 'completion-styles '(orderless basic))
(customize-set-variable 'completion-category-overrides '((file (styles . (partial-completion)))))
;;; Embark
(require 'embark)
(require 'embark-consult)
(global-set-key [remap describe-bindings] #'embark-bindings)
(global-set-key (kbd "C-.") 'embark-act)
;; Use Embark to show bindings in a key prefix with `C-h`
(setq prefix-help-command #'embark-prefix-help-command)
(with-eval-after-load 'embark-consult
(add-hook 'embark-collect-mode-hook #'consult-preview-at-point-mode))
;;; Corfu
(when (eq crafted-package-system 'straight)
(add-to-list 'load-path
(expand-file-name "straight/build/corfu/extensions"
straight-base-dir)))
(require 'corfu-popupinfo)
(require 'corfu)
(unless (display-graphic-p)
(require 'corfu-terminal)
(corfu-terminal-mode +1))
;; Setup corfu for popup like completion
(customize-set-variable 'corfu-cycle t) ; Allows cycling through candidates
(customize-set-variable 'corfu-auto t) ; Enable auto completion
(customize-set-variable 'corfu-auto-prefix 2) ; Complete with less prefix keys
(customize-set-variable 'corfu-auto-delay 0.0) ; No delay for completion
(customize-set-variable 'corfu-echo-documentation 0.25) ; Echo docs for current completion option
(global-corfu-mode 1)
(corfu-popupinfo-mode 1)
(eldoc-add-command #'corfu-insert)
(define-key corfu-map (kbd "M-p") #'corfu-popupinfo-scroll-down)
(define-key corfu-map (kbd "M-n") #'corfu-popupinfo-scroll-up)
(define-key corfu-map (kbd "M-d") #'corfu-popupinfo-toggle)
;;; Cape
;; Setup Cape for better completion-at-point support and more
(require 'cape)
;; Add useful defaults completion sources from cape
(add-to-list 'completion-at-point-functions #'cape-file)
(add-to-list 'completion-at-point-functions #'cape-dabbrev)
;; Silence the pcomplete capf, no errors or messages!
;; Important for corfu
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-silent)
;; Ensure that pcomplete does not write to the buffer
;; and behaves as a pure `completion-at-point-function'.
(advice-add 'pcomplete-completions-at-point :around #'cape-wrap-purify)
(add-hook 'eshell-mode-hook
(lambda () (setq-local corfu-quit-at-boundary t
corfu-quit-no-match t
corfu-auto nil)
(corfu-mode)))
(provide 'crafted-completion)
;;; crafted-completion.el ends here

View File

@ -0,0 +1,116 @@
;;; crafted-defaults.el -*- lexical-binding: t; -*-
;; Revert Dired and other buffers
(customize-set-variable 'global-auto-revert-non-file-buffers t)
;; Revert buffers when the underlying file has changed
(global-auto-revert-mode 1)
(setq global-auto-revert-non-file-buffers t) ;; TODO check
;; Typed text replaces the selection if the selection is active,
;; pressing delete or backspace deletes the selection.
(delete-selection-mode)
;; Use spaces instead of tabs // TODO Check!!
(setq-default indent-tabs-mode nil)
;; Use "y" and "n" to confirm/negate prompt instead of "yes" and "no"
;; Using `advice' here to make it easy to reverse in custom
;; configurations with `(advice-remove 'yes-or-no-p #'y-or-n-p)'
;;
;; N.B. Emacs 28 has a variable for using short answers, which should
;; be preferred if using that version or higher.
(if (boundp 'use-short-answers)
(setq use-short-answers t)
(advice-add 'yes-or-no-p :override #'y-or-n-p))
;; Turn on recentf mode
(add-hook 'after-init-hook #'recentf-mode)
(customize-set-variable 'recentf-save-file
(expand-file-name "recentf" crafted-config-var-directory))
;; Do not save duplicates in kill-ring
(customize-set-variable 'kill-do-not-save-duplicates t)
;; Make scrolling less stuttered // TODO emacs29 scroll check!!
;;(setq auto-window-vscroll nil)
;;(customize-set-variable 'fast-but-imprecise-scrolling t)
;;(customize-set-variable 'scroll-conservatively 101)
;;(customize-set-variable 'scroll-margin 0)
;;(customize-set-variable 'scroll-preserve-screen-position t)
;; Better support for files with long lines
(setq-default bidi-paragraph-direction 'left-to-right)
(setq-default bidi-inhibit-bpa t)
(global-so-long-mode 1)
;; Make shebang (#!) file executable when saved
(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)
;; Enable savehist-mode for command history
(savehist-mode 1)
;; Keep state files in `crafted-config-var-directory' by default
;; we use `with-eval-after-load' to only affect what is being used.
;;
;; Note that this can introduce issues depending on how each module
;; works. Like, for example, if the module reads those files during
;; load it may happen that it reads the file on its default location
;; before the path is changed (because this code runs after-load,
;; and user customization is run after all of crafted-emacs is loaded)
;;
;; So, each variable needs some thought on how/when to set it,
;; while also trying to not set variables for modules the user
;; is not loading / using.
;; Enable the sensible path defaults
(defcustom crafted-folders t
"Non-nil enabled 'sensible folder layout' behaviour."
:type 'boolean
:group 'crafted)
(defun crafted-defaults--sensible-path
(root varname name)
"Sets the VARNAME to a path named NAME inside ROOT.
But only if `crafted-folders' is enabled (`t').
For example (crafted-config-var-directory 'savehist-file \"history\")
Will set `savehist-file' to, ie, ~/.config/crafted-emacs/var/history"
(if-let ((path (expand-file-name name root))
(crafted-folders))
(customize-set-variable varname path)
))
(crafted-defaults--sensible-path crafted-config-var-directory
'savehist-file "history")
(crafted-defaults--sensible-path crafted-config-var-directory
'auto-save-list-file-prefix "auto-save-list/.saves-")
(with-eval-after-load 'saveplace
(crafted-defaults--sensible-path crafted-config-var-directory
'save-place-file "places"))
(with-eval-after-load 'bookmark
(crafted-defaults--sensible-path crafted-config-var-directory
'bookmark-default-file "bookmarks"))
(with-eval-after-load 'tramp
(crafted-defaults--sensible-path crafted-config-var-directory
'tramp-persistency-file-name
"tramp"))
(with-eval-after-load 'org-id
(crafted-defaults--sensible-path crafted-config-var-directory
'org-id-locations-file
"org-id-locations"))
(with-eval-after-load 'nsm
(crafted-defaults--sensible-path crafted-config-var-directory
'nsm-settings-file
"network-security.data"))
(with-eval-after-load 'project
(crafted-defaults--sensible-path crafted-config-var-directory
'project-list-file
"projects"))
(provide 'crafted-defaults)

View File

@ -0,0 +1,120 @@
;;; crafted-defaults.el -*- lexical-binding: t; -*-
;; Revert Dired and other buffers
(customize-set-variable 'global-auto-revert-non-file-buffers t)
;; Revert buffers when the underlying file has changed
(global-auto-revert-mode 1)
(setq global-auto-revert-non-file-buffers t) ;; TODO check
;; Line numbers
(global-display-line-numbers-mode 1)
(setq display-line-numbers-type `relative)
;; Typed text replaces the selection if the selection is active,
;; pressing delete or backspace deletes the selection.
(delete-selection-mode)
;; Use spaces instead of tabs // TODO Check!!
(setq-default indent-tabs-mode nil)
;; Use "y" and "n" to confirm/negate prompt instead of "yes" and "no"
;; Using `advice' here to make it easy to reverse in custom
;; configurations with `(advice-remove 'yes-or-no-p #'y-or-n-p)'
;;
;; N.B. Emacs 28 has a variable for using short answers, which should
;; be preferred if using that version or higher.
(if (boundp 'use-short-answers)
(setq use-short-answers t)
(advice-add 'yes-or-no-p :override #'y-or-n-p))
;; Turn on recentf mode
(add-hook 'after-init-hook #'recentf-mode)
(customize-set-variable 'recentf-save-file
(expand-file-name "recentf" crafted-config-var-directory))
;; Do not save duplicates in kill-ring
(customize-set-variable 'kill-do-not-save-duplicates t)
;; Make scrolling less stuttered // TODO emacs29 scroll check!!
;;(setq auto-window-vscroll nil)
;;(customize-set-variable 'fast-but-imprecise-scrolling t)
;;(customize-set-variable 'scroll-conservatively 101)
;;(customize-set-variable 'scroll-margin 0)
;;(customize-set-variable 'scroll-preserve-screen-position t)
;; Better support for files with long lines
(setq-default bidi-paragraph-direction 'left-to-right)
(setq-default bidi-inhibit-bpa t)
(global-so-long-mode 1)
;; Make shebang (#!) file executable when saved
(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p)
;; Enable savehist-mode for command history
(savehist-mode 1)
;; Keep state files in `crafted-config-var-directory' by default
;; we use `with-eval-after-load' to only affect what is being used.
;;
;; Note that this can introduce issues depending on how each module
;; works. Like, for example, if the module reads those files during
;; load it may happen that it reads the file on its default location
;; before the path is changed (because this code runs after-load,
;; and user customization is run after all of crafted-emacs is loaded)
;;
;; So, each variable needs some thought on how/when to set it,
;; while also trying to not set variables for modules the user
;; is not loading / using.
;; Enable the sensible path defaults
(defcustom crafted-folders t
"Non-nil enabled 'sensible folder layout' behaviour."
:type 'boolean
:group 'crafted)
(defun crafted-defaults--sensible-path
(root varname name)
"Sets the VARNAME to a path named NAME inside ROOT.
But only if `crafted-folders' is enabled (`t').
For example (crafted-config-var-directory 'savehist-file \"history\")
Will set `savehist-file' to, ie, ~/.config/crafted-emacs/var/history"
(if-let ((path (expand-file-name name root))
(crafted-folders))
(customize-set-variable varname path)
))
(crafted-defaults--sensible-path crafted-config-var-directory
'savehist-file "history")
(crafted-defaults--sensible-path crafted-config-var-directory
'auto-save-list-file-prefix "auto-save-list/.saves-")
(with-eval-after-load 'saveplace
(crafted-defaults--sensible-path crafted-config-var-directory
'save-place-file "places"))
(with-eval-after-load 'bookmark
(crafted-defaults--sensible-path crafted-config-var-directory
'bookmark-default-file "bookmarks"))
(with-eval-after-load 'tramp
(crafted-defaults--sensible-path crafted-config-var-directory
'tramp-persistency-file-name
"tramp"))
(with-eval-after-load 'org-id
(crafted-defaults--sensible-path crafted-config-var-directory
'org-id-locations-file
"org-id-locations"))
(with-eval-after-load 'nsm
(crafted-defaults--sensible-path crafted-config-var-directory
'nsm-settings-file
"network-security.data"))
(with-eval-after-load 'project
(crafted-defaults--sensible-path crafted-config-var-directory
'project-list-file
"projects"))
(provide 'crafted-defaults)

View File

@ -0,0 +1,109 @@
;;; crafted-evil.el --- Evil mode configuration -*- lexical-binding: t; -*-
;; Copyright (C) 2022
;; SPDX-License-Identifier: MIT
;; Author: System Crafters Community
;;; Commentary:
;; Evil mode configuration, for those who prefer `Vim' keybindings.
;;; Code:
(defgroup crafted-evil '()
"Vim-like related configuration for Crafted Emacs."
:tag "Crafted Evil"
:group 'crafted)
;; Define configuration variables
(define-obsolete-variable-alias
'rational-evil-discourage-arrow-keys
'crafted-evil-discourage-arrow-keys
"1")
(defcustom crafted-evil-discourage-arrow-keys nil
"When non-nil, prevent navigation with the arrow keys in Normal state."
:group 'crafted-evil
:type 'boolean)
(define-obsolete-variable-alias
'rational-evil-vim-muscle-memory
'crafted-evil-vim-muscle-memory
"1")
(defcustom crafted-evil-vim-muscle-memory nil
"When non-nil, let evil mode take some of the default keybindings, in order to make a more familiar Vim experience."
:group 'crafted-evil
:type 'boolean)
;; Install dependencies
(crafted-package-install-package 'evil)
(crafted-package-install-package 'evil-collection)
(crafted-package-install-package 'evil-nerd-commenter)
;; Turn on undo-tree globally
(when (< emacs-major-version 28)
(crafted-package-install-package 'undo-tree)
(global-undo-tree-mode))
;; Set some variables that must be configured before loading the package
(customize-set-variable 'evil-want-integration t)
(customize-set-variable 'evil-want-keybinding nil)
(customize-set-variable 'evil-want-C-i-jump nil)
(customize-set-variable 'evil-respect-visual-line-mode t)
;; C-h is backspace in insert state
(customize-set-variable 'evil-want-C-h-delete t)
(if (< emacs-major-version 28)
(customize-set-variable 'evil-undo-system 'undo-tree)
(customize-set-variable 'evil-undo-system 'undo-redo))
(when crafted-evil-vim-muscle-memory
(customize-set-variable 'evil-want-C-i-jump t)
(customize-set-variable 'evil-want-Y-yank-to-eol t)
(customize-set-variable 'evil-want-fine-undo t))
;; Load Evil and enable it globally
(require 'evil)
(evil-mode 1)
;; Make evil search more like vim
(evil-select-search-module 'evil-search-module 'evil-search)
;; Turn on Evil Nerd Commenter
(evilnc-default-hotkeys)
;; Make C-g revert to normal state
(define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
;; Rebind `universal-argument' to 'C-M-u' since 'C-u' now scrolls the buffer
(global-set-key (kbd "C-M-u") 'universal-argument)
;; Use visual line motions even outside of visual-line-mode buffers
(evil-global-set-key 'motion "j" 'evil-next-visual-line)
(evil-global-set-key 'motion "k" 'evil-previous-visual-line)
(defun crafted-evil/discourage-arrow-keys ()
(interactive)
(message "Use HJKL keys instead!"))
(when crafted-evil-discourage-arrow-keys
;; Disable arrow keys in normal and visual modes
(define-key evil-normal-state-map (kbd "<left>") 'crafted-evil/discourage-arrow-keys)
(define-key evil-normal-state-map (kbd "<right>") 'crafted-evil/discourage-arrow-keys)
(define-key evil-normal-state-map (kbd "<down>") 'crafted-evil/discourage-arrow-keys)
(define-key evil-normal-state-map (kbd "<up>") 'crafted-evil/discourage-arrow-keys)
(evil-global-set-key 'motion (kbd "<left>") 'crafted-evil/discourage-arrow-keys)
(evil-global-set-key 'motion (kbd "<right>") 'crafted-evil/discourage-arrow-keys)
(evil-global-set-key 'motion (kbd "<down>") 'crafted-evil/discourage-arrow-keys)
(evil-global-set-key 'motion (kbd "<up>") 'crafted-evil/discourage-arrow-keys))
;; Make sure some modes start in Emacs state
;; TODO: Split this out to other configuration modules?
(dolist (mode '(custom-mode
eshell-mode
term-mode))
(add-to-list 'evil-emacs-state-modes mode))
(evil-collection-init)
(provide 'crafted-evil)
;;; crafted-evil.el ends here

View File

@ -0,0 +1,203 @@
;;; crafted-startup.el --- Crafted Emacs splash screen on startup -*- lexical-binding: t; -*-
;; Copyright (C) 2022
;; SPDX-License-Identifier: MIT
;; Author: System Crafters Community
;;; Commentary:
;; Provide a fancy splash screen similar to the Emacs default splash
;; screen or the Emacs about page.
;;; Code:
(require 'crafted-updates)
(defgroup crafted-startup '()
"Startup configuration for Crafted Emacs"
:tag "Crafted Startup"
:group 'crafted)
(define-obsolete-variable-alias
'rational-startup-inhibit-splash
'crafted-startup-inhibit-splash
"1")
(defcustom crafted-startup-inhibit-splash nil
"Disable the Crafted Emacs Splash screen"
:type 'boolean
:group 'crafted-startup)
(define-obsolete-variable-alias
'rational-startup-recentf-count
'crafted-startup-recentf-count
"1")
(defcustom crafted-startup-recentf-count 10
"The number of recent files to display on the splash screen"
:type 'number
:group 'crafted-startup)
(defconst crafted-startup-text
`((:face (variable-pitch font-lock-comment-face (:height 1.5) bold)
,(let* ((welcome-text "Welcome to Crafted Emacs!\n\n")
(welcome-len (length welcome-text))
(welcome-mid (/ welcome-len 2)))
(concat
(make-string (abs (- (/ (window-width) 2)
welcome-mid))
? )
welcome-text))
:face variable-pitch
:link ("View Crafted Emacs Manual" ,(lambda (_button) (info "crafted-emacs")))
"\tView the Crafted Emacs manual using Info\n"
"\n"))
"A list of texts to show in the middle part of splash screens.
Each element in the list should be a list of strings or pairs
`:face FACE', like `fancy-splash-insert' accepts them.")
(defvar crafted-startup-screen-inhibit-startup-screen nil)
(defun crafted-startup-tail (&optional concise)
"Insert the tail part of the splash screen into the current buffer."
(fancy-splash-insert
:face 'variable-pitch
"\nTo start... "
:link `("Open a File"
,(lambda (_button) (call-interactively 'find-file))
"Specify a new file's name, to edit the file")
" "
:link `("Open Home Directory"
,(lambda (_button) (dired "~"))
"Open your home directory, to operate on its files")
" "
:link `("Open Crafted Config Directory"
,(lambda (_button) (dired crafted-config-path))
"Open the Crafted Emacs configuration directory, to operate on its files")
" "
:link `("Customize Crafted Emacs"
,(lambda (_button) (customize-group 'crafted))
"Change initialization settings including this screen")
"\n")
(fancy-splash-insert
:face '(variable-pitch (:height 0.7))
"\n\nTurn this screen off by adding:\n"
:face '(default font-lock-keyword-face)
"`(customize-set-variable 'crafted-startup-inhibit-splash t)'\n"
:face '(variable-pitch (:height 0.7))
" to your " crafted-config-file "\n"
"Or check the box and click the link below, which will do the same thing.")
(fancy-splash-insert
:face 'variable-pitch "\n"
:link `("Dismiss this startup screen"
,(lambda (_button)
(when crafted-startup-screen-inhibit-startup-screen
(customize-set-variable 'crafted-startup-inhibit-splash t)
(customize-mark-to-save 'crafted-startup-inhibit-splash)
(custom-save-all))
(quit-windows-on "*Crafted Emacs*" t)))
" ")
(when custom-file
(let ((checked (create-image "checked.xpm"
nil nil :ascent 'center))
(unchecked (create-image "unchecked.xpm"
nil nil :ascent 'center)))
(insert-button
" "
:on-glyph checked
:off-glyph unchecked
'checked nil 'display unchecked 'follow-link t
'action (lambda (button)
(if (overlay-get button 'checked)
(progn (overlay-put button 'checked nil)
(overlay-put button 'display
(overlay-get button :off-glyph))
(setq crafted-startup-screen-inhibit-startup-screen
nil))
(overlay-put button 'checked t)
(overlay-put button 'display
(overlay-get button :on-glyph))
(setq crafted-startup-screen-inhibit-startup-screen t))))))
(fancy-splash-insert :face '(variable-pitch (:height 0.9))
" Never show it again."))
(defun crafted-startup-recentf ()
(message "Showing recents on splash screen")
(fancy-splash-insert
:face '(variable-pitch font-lock-string-face italic)
(condition-case recentf-list
(if (not (seq-empty-p recentf-list))
"Recent Files:\n"
"\n")
(error "\n")))
(condition-case recentf-list
(if (not (seq-empty-p recentf-list))
(dolist (file (seq-take recentf-list crafted-startup-recentf-count))
(fancy-splash-insert
:face 'default
:link `(,file ,(lambda (_button) (find-file file)))
"\n"))
"\n")
(error "\n")))
(defun crafted-startup-screen (&optional concise)
"Display fancy startup screen.
If CONCISE is non-nil, display a concise version of the
splash screen in another window."
(message "Loading Crafted Startup Screen")
(let ((splash-buffer (get-buffer-create "*Crafted Emacs*")))
(with-current-buffer splash-buffer
(let ((inhibit-read-only t))
(erase-buffer)
(setq default-directory command-line-default-directory)
(make-local-variable 'crafted-startup-screen-inhibit-startup-screen)
(if pure-space-overflow
(insert pure-space-overflow-message))
(dolist (text crafted-startup-text)
(apply #'fancy-splash-insert text)
(insert "\n"))
(crafted-updates-check-for-latest)
(if (> (condition-case nil
(crafted-updates--get-new-commit-count)
(error 0)) 0)
(fancy-splash-insert
:face '(variable-pitch font-lock-keyword-face bold)
(format "%s : " (crafted-updates-status-message))
:face '(variable-pitch font-lock-keyword-face)
:link `(" Show Updates " ,(lambda (_button) (crafted-updates-show-latest)))
:face '(variable-pitch font-lock-keyword-face)
:link `(" Get Updates " ,(lambda (_button) (crafted-updates-pull-latest t)))
"\n")
(fancy-splash-insert
:face '(variable-pitch font-lock-keyword-face bold)
(format "%s\n" (condition-case nil
(crafted-updates-status-message)
(error "Crafted Emacs status could not be determined.")))))
(insert "\n\n")
(crafted-startup-recentf)
(skip-chars-backward "\n")
(delete-region (point) (point-max))
(insert "\n")
(crafted-startup-tail concise))
(use-local-map splash-screen-keymap)
(setq-local browse-url-browser-function 'eww-browse-url)
(setq tab-width 22
buffer-read-only t)
(set-buffer-modified-p nil)
(if (and view-read-only (not view-mode))
(view-mode-enter nil 'kill-buffer))
(goto-char (point-min))
(forward-line (if concise 2 4)))
(if concise
(progn
(display-buffer splash-buffer)
;; If the splash screen is in a split window, fit it.
(let ((window (get-buffer-window splash-buffer t)))
(or (null window)
(eq window (selected-window))
(eq window (next-window window))
(fit-window-to-buffer window))))
(switch-to-buffer splash-buffer))))
(provide 'crafted-startup)
;;; crafted-startup.el ends here

View File

@ -0,0 +1,198 @@
;;; crafted-ui.el -*- lexical-binding: t; -*-
;; Copyright (C) 2022
;; SPDX-License-Identifier: MIT
;; Author: System Crafters Community
;; Commentary
;; User interface customizations. Examples are the modeline and how
;; help buffers are displayed.
;; This package provides a basic, customized appearance for
;; Emacs. Specifically, it uses: Helpful to customize the information
;; and visual display of help buffers, such as that created by M-x
;; `describe-function'; Doom Modeline and Themes, to customize the
;; appearance of buffers, text, et cetera; All-the-icons, to provide
;; Doom Modeline with font-based icons (rather than raster or vector
;; images); and includes some Emacs Lisp demonstrations.
;;  Run `all-the-icons-install-fonts' to ensure the fonts necessary
;; for ALL THE ICONS are available on your system. You must run this
;; function if the "stop" icon at the beginning of this paragraph is
;; not displayed properly (it appears as a box with some numbers
;; and/or letters inside it).
;; Read the documentation for `all-the-icons'; on Windows,
;; `all-the-icons-install-fonts' only downloads fonts, they must be
;; installed manually. This is necessary if icons are not displaying
;; properly.
;;; Code:
(crafted-package-install-package 'all-the-icons)
(crafted-package-install-package 'elisp-demos)
(crafted-package-install-package 'helpful)
;;;; Font
(defun crafted-ui--set-default-font (spec)
"Set the default font based on SPEC.
SPEC is expected to be a plist with the same key names
as accepted by `set-face-attribute'."
(when spec
(apply 'set-face-attribute 'default nil spec)))
(defun crafted-ui--toggle-doom-modeline-mode (state)
"Turn on/off doom-modeline-mode if it is installed.
STATE is either 1 to turn the mode on, or -1 to turn it off."
(when (package-installed-p 'doom-modeline)
(doom-modeline-mode state)))
(defgroup crafted-ui '()
"User interface related configuration for Crafted Emacs."
:tag "Crafted UI"
:group 'crafted)
(define-obsolete-variable-alias
'rational-ui-default-font
'crafted-ui-default-font
"1")
(defcustom crafted-ui-default-font nil
"The configuration of the `default' face.
Use a plist with the same key names as accepted by `set-face-attribute'."
:group 'crafted-ui
:type '(plist :key-type: symbol)
:tag "Default font"
:set (lambda (sym val)
(let ((prev-val (if (boundp 'crafted-ui-default-font)
crafted-ui-default-font
nil)))
(set-default sym val)
(when (and val (not (eq val prev-val)))
(crafted-ui--set-default-font val)))))
;;;; Mode-Line
(defcustom crafted-ui-use-doom-modeline nil
"Use doom-modeline-mode."
:group 'crafted-ui
:type 'boolean
:tag "Use Doom Modeline"
:set (lambda (sym val)
(set-default sym val)
(if val
(crafted-ui--toggle-doom-modeline-mode 1)
(crafted-ui--toggle-doom-modeline-mode -1))))
;; Configure `doom-modeline' if it is enabled
(when crafted-ui-use-doom-modeline
(crafted-package-install-package 'doom-modeline)
(customize-set-variable 'doom-modeline-height 15)
(customize-set-variable 'doom-modeline-bar-width 6)
(customize-set-variable 'doom-modeline-minor-modes t)
(customize-set-variable 'doom-modeline-buffer-file-name-style 'truncate-except-project))
;;;; Help Buffers
;; Make `describe-*' screens more helpful
(require 'helpful)
(define-key helpful-mode-map [remap revert-buffer] #'helpful-update)
(global-set-key [remap describe-command] #'helpful-command)
(global-set-key [remap describe-function] #'helpful-callable)
(global-set-key [remap describe-key] #'helpful-key)
(global-set-key [remap describe-symbol] #'helpful-symbol)
(global-set-key [remap describe-variable] #'helpful-variable)
(global-set-key (kbd "C-h F") #'helpful-function)
;; Bind extra `describe-*' commands
(global-set-key (kbd "C-h K") #'describe-keymap)
;;;; Line Numbers
(define-obsolete-variable-alias
'rational-ui-line-numbers-enabled-modes
'crafted-ui-line-numbers-enabled-modes
"1")
(defcustom crafted-ui-line-numbers-enabled-modes
'(conf-mode prog-mode)
"Modes which should display line numbers."
:type 'list
:group 'crafted-ui)
(define-obsolete-variable-alias
'rational-ui-line-numbers-disabled-modes
'crafted-ui-line-numbers-disabled-modes
"1")
(defcustom crafted-ui-line-numbers-disabled-modes
'(org-mode)
"Modes which should not display line numbers.
Modes derived from the modes defined in
`crafted-ui-line-number-enabled-modes', but should not display line numbers."
:type 'list
:group 'crafted-ui)
(defun crafted-ui--enable-line-numbers-mode ()
"Turn on line numbers mode.
Used as hook for modes which should display line numbers."
(display-line-numbers-mode 1))
(defun crafted-ui--disable-line-numbers-mode ()
"Turn off line numbers mode.
Used as hook for modes which should not display line numebrs."
(display-line-numbers-mode -1))
(defun crafted-ui--update-line-numbers-display ()
"Update configuration for line numbers display."
(if crafted-ui-display-line-numbers
(progn
(dolist (mode crafted-ui-line-numbers-enabled-modes)
(add-hook (intern (format "%s-hook" mode))
#'crafted-ui--enable-line-numbers-mode))
(dolist (mode crafted-ui-line-numbers-disabled-modes)
(add-hook (intern (format "%s-hook" mode))
#'crafted-ui--disable-line-numbers-mode))
(setq-default
display-line-numbers-grow-only t
display-line-numbers-type t
display-line-numbers-width 2))
(progn
(dolist (mode crafted-ui-line-numbers-enabled-modes)
(remove-hook (intern (format "%s-hook" mode))
#'crafted-ui--enable-line-numbers-mode))
(dolist (mode crafted-ui-line-numbers-disabled-modes)
(remove-hook (intern (format "%s-hook" mode))
#'crafted-ui--disable-line-numbers-mode)))))
(define-obsolete-variable-alias
'rational-ui-display-line-numbers
'crafted-ui-display-line-numbers
"1")
(defcustom crafted-ui-display-line-numbers nil
"Whether line numbers should be enabled."
:type 'boolean
:group 'crafted-ui
:set (lambda (sym val)
(set-default sym val)
(crafted-ui--update-line-numbers-display)))
;;;; Elisp-Demos
;; also add some examples
(require 'elisp-demos)
(advice-add 'helpful-update :after #'elisp-demos-advice-helpful-update)
;; add visual pulse when changing focus, like beacon but built-in
;; from from https://karthinks.com/software/batteries-included-with-emacs/
(defun pulse-line (&rest _)
"Pulse the current line."
(pulse-momentary-highlight-one-line (point)))
(dolist (command '(scroll-up-command scroll-down-command
recenter-top-bottom other-window))
(advice-add command :after #'pulse-line))
(provide 'crafted-ui)
;;; crafted-ui.el ends here

View File

@ -0,0 +1,120 @@
;;;; crafted-updates.el --- Provides automatic update behavior for the configuration. -*- lexical-binding: t; -*-
;; Copyright (C) 2022
;; SPDX-License-Identifier: MIT
;; Author: System Crafters Community
;; Commentary
;;; Code:
(autoload 'vc-git--out-ok "vc-git")
(defun crafted-updates--call-git (&rest args)
(let ((default-directory user-emacs-directory))
(with-temp-buffer
(if (apply #'vc-git--out-ok args)
(buffer-string)
nil))))
(defun crafted-updates--get-new-commit-count ()
(string-to-number (crafted-updates--call-git "rev-list" "--count" "master..origin/master")))
(defun crafted-updates-status-message ()
"Status message indicating availble updates or not."
(if (> (crafted-updates--get-new-commit-count) 0)
"Crafted Emacs updates are available!"
"Crafted Emacs is up to date!"))
(defun crafted-updates--notify-of-updates ()
(message (crafted-updates-status-message)))
(defun crafted-updates--poll-git-fetch-status (process)
(if (eql (process-status process) 'exit)
(when (eql (process-exit-status process) 0)
)
(run-at-time 1 nil #'crafted-updates--poll-git-fetch-status process)))
(defun crafted-updates--find-init-el ()
(find-file-noselect (expand-file-name "init.el" user-emacs-directory)))
(defun crafted-updates-check-for-latest ()
"Fetches the latest Crafted Emacs commits from GitHub and
notifies you if there are any updates."
(interactive)
(message "Checking for Crafted Emacs updates...")
(when (crafted-updates--call-git #' "fetch" "origin")
(crafted-updates--notify-of-updates)))
(defun crafted-updates-show-latest ()
"Shows a buffer containing a log of the latest commits to
Crafted Emacs."
(interactive)
(message "Fetching latest commit log for Crafted Emacs...")
(with-current-buffer (find-file-noselect (expand-file-name "init.el" user-emacs-directory))
(vc-log-incoming)))
(defun crafted-updates--pull-commits ()
(message "Pulling latest commits to Crafted Emacs...")
(with-current-buffer (find-file-noselect (expand-file-name "init.el" user-emacs-directory))
(vc-pull)))
(defun crafted-updates-pull-latest (do-pull)
"Pull the latest Crafted Emacs version into the local repository.
If DO-PULL is nil then only the latest updates will be shown,
otherwise the local repository will get updated to the GitHub
version.
Interactively, the default if you just type RET is to show recent
changes as if you called `crafted-updates-show-latest'.
With a `\\[universal-argument]' prefix immediately pull changes
and don't prompt for confirmation."
(interactive
(list
(or current-prefix-arg
(pcase (completing-read "Crafted Update Action: " '("Show Log" "Update") nil t nil nil "Show Log")
("Show Log" nil)
("Update" t)))))
(if do-pull
(crafted-updates--pull-commits)
(crafted-updates-show-latest)))
(defgroup crafted-updates '()
"Configuration for keeping Crafted Emacs up-to-date."
:tag "Crafted Updates"
:group 'crafted)
;; TODO: use a derived type to check that the value is something `run-at-time'
;; will accept
(define-obsolete-variable-alias
'rational-updates-fetch-interval
'crafted-updates-fetch-interval
"1")
(defcustom crafted-updates-fetch-interval "24 hours"
"The interval at which `crafted-updates-mode' will check for updates.
The interval is scheduled with `run-at-time', so the value of
this variable must conform to a format accepted by
`run-at-time'."
:group 'crafted-updates)
(defun crafted-updates--do-automatic-fetch ()
(when crafted-updates-mode
(crafted-updates-check-for-latest)
(crafted-updates--schedule-fetch)))
(defun crafted-updates--schedule-fetch ()
(run-at-time crafted-updates-fetch-interval nil #'crafted-updates--do-automatic-fetch))
(define-minor-mode crafted-updates-mode
"Provides an automatic update checking feature for Crafted
Emacs. When enabled, it will automatically check for updates at
the specified `crafted-updates-fetch-interval'."
:global t
:group 'crafted-updates
(when crafted-updates-mode
(crafted-updates--schedule-fetch)))
(provide 'crafted-updates)
;;; crafted-updates.el ends here

View File

@ -0,0 +1,51 @@
;;; crafted-windows.el -*- lexical-binding: t; -*-
;; Copyright (C) 2022
;; SPDX-License-Identifier: MIT
;; Author: System Crafters Community
;; Commentary
;; Emacs windows configuration.
;;; Code:
(defgroup crafted-windows '()
"Window related configuration for Crafted Emacs."
:tag "Crafted Windows"
:group 'crafted)
(define-obsolete-variable-alias
'rational-windows-evil-style
'crafted-windows-evil-style
"1")
(defcustom crafted-windows-evil-style nil
"When non-nil, window movement will use evil-style bindings."
:group 'crafted-windows
:type 'boolean)
(define-obsolete-variable-alias
'rational-windows-prefix-key
'crafted-windows-prefix-key
"1")
(defcustom crafted-windows-prefix-key "C-c w"
"Configure the prefix key for `crafted-windows' bindings."
:group 'crafted-windows
:type 'key)
(winner-mode 1)
(define-prefix-command 'crafted-windows-key-map)
(define-key 'crafted-windows-key-map (kbd "u") 'winner-undo)
(define-key 'crafted-windows-key-map (kbd "n") 'windmove-down)
(define-key 'crafted-windows-key-map (kbd "p") 'windmove-up)
(define-key 'crafted-windows-key-map (kbd "b") 'windmove-left)
(define-key 'crafted-windows-key-map (kbd "f") 'windmove-right)
(global-set-key (kbd crafted-windows-prefix-key) 'crafted-windows-key-map)
(provide 'crafted-windows)
;;; crafted-windows.el ends here

View File

@ -0,0 +1,38 @@
;;; custom-dashboard.el -*- lexical-binding: t; -*-
(crafted-package-install-package 'dashboard)
(require 'dashboard)
(setq dashboard-set-heading-icons t)
(setq dashboard-set-file-icons t)
(setq dashboard-startup-banner 'logo) ;; use standard emacs logo as banner
(setq dashboard-center-content t) ;; set to 't' for centered content
(setq dashboard-items '((recents . 10)
(bookmarks . 5)))
;;(projects . 10))) // TODO after projectile
(setq dashboard-set-footer t)
(setq dashboard-page-separator "\n\n\f\n\n")
(setq dashboard-set-navigator t)
;; Format: "(icon title help action face prefix suffix)"
(setq dashboard-navigator-buttons
`(;; line1
((,(all-the-icons-octicon "mark-github" :height 1.1 :v-adjust 0.0)
"Github"
"Browse my Github"
(lambda (&rest _) (browse-url "https://github.com/JaeUs3792/")))
(,(all-the-icons-octicon "home" :height 1.1 :v-adjust 0.0)
"Homepage"
"Browse my Homepage"
(lambda (&rest _) (browse-url "https://jaeus.net"))))))
(dashboard-setup-startup-hook)
(dashboard-modify-heading-icons '((recents . "file-text")
(bookmarks . "book")))
(setq doom-fallback-buffer-name "*dashboard*")
(require 'linum)
(add-hook 'dashboard-mode-hook page-break-lines-mode)
(provide 'custom-dashboard)
;;; custom-dashboard.el end here

View File

@ -0,0 +1,70 @@
;;; crafted-evil.el --- Evil mode configuration -*- lexical-binding: t; -*-
;; Copyright (C) 2022
;; SPDX-License-Identifier: MIT
;; Author: System Crafters Community
;;; Commentary:
;; Evil mode configuration, for those who prefer `Vim' keybindings.
;;; Code:
;; Install dependencies
(crafted-package-install-package 'evil)
(crafted-package-install-package 'evil-collection)
(crafted-package-install-package 'evil-nerd-commenter)
;; Turn on undo-tree globally
(when (< emacs-major-version 28)
(crafted-package-install-package 'undo-tree)
(global-undo-tree-mode))
;; Set some variables that must be configured before loading the package
(customize-set-variable 'evil-want-integration t)
(customize-set-variable 'evil-want-keybinding nil)
(customize-set-variable 'evil-want-C-i-jump nil)
(customize-set-variable 'evil-respect-visual-line-mode t)
;; C-h is backspace in insert state
(customize-set-variable 'evil-want-C-h-delete t)
(if (< emacs-major-version 28)
(customize-set-variable 'evil-undo-system 'undo-tree)
(customize-set-variable 'evil-undo-system 'undo-redo))
(when crafted-evil-vim-muscle-memory
(customize-set-variable 'evil-want-C-i-jump t)
(customize-set-variable 'evil-want-Y-yank-to-eol t)
(customize-set-variable 'evil-want-fine-undo t))
;; Load Evil and enable it globally
(require 'evil)
(evil-mode 1)
;; Make evil search more like vim
(evil-select-search-module 'evil-search-module 'evil-search)
;; Turn on Evil Nerd Commenter
(evilnc-default-hotkeys)
;; Make C-g revert to normal state
(define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
;; Rebind `universal-argument' to 'C-M-u' since 'C-u' now scrolls the buffer
(global-set-key (kbd "C-M-u") 'universal-argument)
;; Use visual line motions even outside of visual-line-mode buffers
(evil-global-set-key 'motion "j" 'evil-next-visual-line)
(evil-global-set-key 'motion "k" 'evil-previous-visual-line)
;; Make sure some modes start in Emacs state
;; TODO: Split this out to other configuration modules?
(dolist (mode '(custom-mode
eshell-mode
term-mode))
(add-to-list 'evil-emacs-state-modes mode))
(evil-collection-init)
(provide 'crafted-evil)
;;; crafted-evil.el ends here

View File

@ -0,0 +1,109 @@
;;; crafted-evil.el --- Evil mode configuration -*- lexical-binding: t; -*-
;; Copyright (C) 2022
;; SPDX-License-Identifier: MIT
;; Author: System Crafters Community
;;; Commentary:
;; Evil mode configuration, for those who prefer `Vim' keybindings.
;;; Code:
(defgroup crafted-evil '()
"Vim-like related configuration for Crafted Emacs."
:tag "Crafted Evil"
:group 'crafted)
;; Define configuration variables
(define-obsolete-variable-alias
'rational-evil-discourage-arrow-keys
'crafted-evil-discourage-arrow-keys
"1")
(defcustom crafted-evil-discourage-arrow-keys nil
"When non-nil, prevent navigation with the arrow keys in Normal state."
:group 'crafted-evil
:type 'boolean)
(define-obsolete-variable-alias
'rational-evil-vim-muscle-memory
'crafted-evil-vim-muscle-memory
"1")
(defcustom crafted-evil-vim-muscle-memory nil
"When non-nil, let evil mode take some of the default keybindings, in order to make a more familiar Vim experience."
:group 'crafted-evil
:type 'boolean)
;; Install dependencies
(crafted-package-install-package 'evil)
(crafted-package-install-package 'evil-collection)
(crafted-package-install-package 'evil-nerd-commenter)
;; Turn on undo-tree globally
(when (< emacs-major-version 28)
(crafted-package-install-package 'undo-tree)
(global-undo-tree-mode))
;; Set some variables that must be configured before loading the package
(customize-set-variable 'evil-want-integration t)
(customize-set-variable 'evil-want-keybinding nil)
(customize-set-variable 'evil-want-C-i-jump nil)
(customize-set-variable 'evil-respect-visual-line-mode t)
;; C-h is backspace in insert state
(customize-set-variable 'evil-want-C-h-delete t)
(if (< emacs-major-version 28)
(customize-set-variable 'evil-undo-system 'undo-tree)
(customize-set-variable 'evil-undo-system 'undo-redo))
(when crafted-evil-vim-muscle-memory
(customize-set-variable 'evil-want-C-i-jump t)
(customize-set-variable 'evil-want-Y-yank-to-eol t)
(customize-set-variable 'evil-want-fine-undo t))
;; Load Evil and enable it globally
(require 'evil)
(evil-mode 1)
;; Make evil search more like vim
(evil-select-search-module 'evil-search-module 'evil-search)
;; Turn on Evil Nerd Commenter
(evilnc-default-hotkeys)
;; Make C-g revert to normal state
(define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
;; Rebind `universal-argument' to 'C-M-u' since 'C-u' now scrolls the buffer
(global-set-key (kbd "C-M-u") 'universal-argument)
;; Use visual line motions even outside of visual-line-mode buffers
(evil-global-set-key 'motion "j" 'evil-next-visual-line)
(evil-global-set-key 'motion "k" 'evil-previous-visual-line)
(defun crafted-evil/discourage-arrow-keys ()
(interactive)
(message "Use HJKL keys instead!"))
(when crafted-evil-discourage-arrow-keys
;; Disable arrow keys in normal and visual modes
(define-key evil-normal-state-map (kbd "<left>") 'crafted-evil/discourage-arrow-keys)
(define-key evil-normal-state-map (kbd "<right>") 'crafted-evil/discourage-arrow-keys)
(define-key evil-normal-state-map (kbd "<down>") 'crafted-evil/discourage-arrow-keys)
(define-key evil-normal-state-map (kbd "<up>") 'crafted-evil/discourage-arrow-keys)
(evil-global-set-key 'motion (kbd "<left>") 'crafted-evil/discourage-arrow-keys)
(evil-global-set-key 'motion (kbd "<right>") 'crafted-evil/discourage-arrow-keys)
(evil-global-set-key 'motion (kbd "<down>") 'crafted-evil/discourage-arrow-keys)
(evil-global-set-key 'motion (kbd "<up>") 'crafted-evil/discourage-arrow-keys))
;; Make sure some modes start in Emacs state
;; TODO: Split this out to other configuration modules?
(dolist (mode '(custom-mode
eshell-mode
term-mode))
(add-to-list 'evil-emacs-state-modes mode))
(evil-collection-init)
(provide 'crafted-evil)
;;; crafted-evil.el ends here