diff --git a/.config/emacs/bootstrap/crafted-package-bootstrap.el b/.config/emacs/bootstrap/crafted-package-bootstrap.el new file mode 100644 index 0000000..d573f39 --- /dev/null +++ b/.config/emacs/bootstrap/crafted-package-bootstrap.el @@ -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 diff --git a/.config/emacs/bootstrap/crafted-package.el b/.config/emacs/bootstrap/crafted-package.el new file mode 100644 index 0000000..c5a49ab --- /dev/null +++ b/.config/emacs/bootstrap/crafted-package.el @@ -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 diff --git a/.config/emacs/bootstrap/crafted-straight-bootstrap.el b/.config/emacs/bootstrap/crafted-straight-bootstrap.el new file mode 100644 index 0000000..59df45e --- /dev/null +++ b/.config/emacs/bootstrap/crafted-straight-bootstrap.el @@ -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 . + +;; Bootstrap `straight.el' configuration, as described in +;; . 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 diff --git a/.config/emacs/config.el b/.config/emacs/config.el new file mode 100644 index 0000000..8a91ffc --- /dev/null +++ b/.config/emacs/config.el @@ -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 "") '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) diff --git a/.config/emacs/early-init.el b/.config/emacs/early-init.el new file mode 100644 index 0000000..24937ba --- /dev/null +++ b/.config/emacs/early-init.el @@ -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) diff --git a/.config/emacs/init.el b/.config/emacs/init.el new file mode 100644 index 0000000..4673010 --- /dev/null +++ b/.config/emacs/init.el @@ -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. + ) diff --git a/.config/emacs/modules/#crafted-ui.el# b/.config/emacs/modules/#crafted-ui.el# new file mode 100644 index 0000000..56eb196 --- /dev/null +++ b/.config/emacs/modules/#crafted-ui.el# @@ -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 diff --git a/.config/emacs/modules/crafted-completion.el b/.config/emacs/modules/crafted-completion.el new file mode 100644 index 0000000..c42a241 --- /dev/null +++ b/.config/emacs/modules/crafted-completion.el @@ -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 diff --git a/.config/emacs/modules/crafted-defaults.el b/.config/emacs/modules/crafted-defaults.el new file mode 100644 index 0000000..e93b0de --- /dev/null +++ b/.config/emacs/modules/crafted-defaults.el @@ -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) diff --git a/.config/emacs/modules/crafted-defaults.el~ b/.config/emacs/modules/crafted-defaults.el~ new file mode 100644 index 0000000..03bf913 --- /dev/null +++ b/.config/emacs/modules/crafted-defaults.el~ @@ -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) diff --git a/.config/emacs/modules/crafted-evil.el b/.config/emacs/modules/crafted-evil.el new file mode 100644 index 0000000..cf561f5 --- /dev/null +++ b/.config/emacs/modules/crafted-evil.el @@ -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 "") 'crafted-evil/discourage-arrow-keys) + (define-key evil-normal-state-map (kbd "") 'crafted-evil/discourage-arrow-keys) + (define-key evil-normal-state-map (kbd "") 'crafted-evil/discourage-arrow-keys) + (define-key evil-normal-state-map (kbd "") 'crafted-evil/discourage-arrow-keys) + (evil-global-set-key 'motion (kbd "") 'crafted-evil/discourage-arrow-keys) + (evil-global-set-key 'motion (kbd "") 'crafted-evil/discourage-arrow-keys) + (evil-global-set-key 'motion (kbd "") 'crafted-evil/discourage-arrow-keys) + (evil-global-set-key 'motion (kbd "") '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 diff --git a/.config/emacs/modules/crafted-startup.el b/.config/emacs/modules/crafted-startup.el new file mode 100644 index 0000000..dfc4cf8 --- /dev/null +++ b/.config/emacs/modules/crafted-startup.el @@ -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 diff --git a/.config/emacs/modules/crafted-ui.el b/.config/emacs/modules/crafted-ui.el new file mode 100644 index 0000000..925bd97 --- /dev/null +++ b/.config/emacs/modules/crafted-ui.el @@ -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 diff --git a/.config/emacs/modules/crafted-updates.el b/.config/emacs/modules/crafted-updates.el new file mode 100644 index 0000000..92c69f9 --- /dev/null +++ b/.config/emacs/modules/crafted-updates.el @@ -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 diff --git a/.config/emacs/modules/crafted-windows.el b/.config/emacs/modules/crafted-windows.el new file mode 100644 index 0000000..d198547 --- /dev/null +++ b/.config/emacs/modules/crafted-windows.el @@ -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 diff --git a/.config/emacs/modules/custom-dashboard.el b/.config/emacs/modules/custom-dashboard.el new file mode 100644 index 0000000..5cebdb3 --- /dev/null +++ b/.config/emacs/modules/custom-dashboard.el @@ -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 diff --git a/.config/emacs/modules/custom-evil.el b/.config/emacs/modules/custom-evil.el new file mode 100644 index 0000000..bab3d00 --- /dev/null +++ b/.config/emacs/modules/custom-evil.el @@ -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 diff --git a/.config/emacs/modules/custom-evil.el~ b/.config/emacs/modules/custom-evil.el~ new file mode 100644 index 0000000..cf561f5 --- /dev/null +++ b/.config/emacs/modules/custom-evil.el~ @@ -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 "") 'crafted-evil/discourage-arrow-keys) + (define-key evil-normal-state-map (kbd "") 'crafted-evil/discourage-arrow-keys) + (define-key evil-normal-state-map (kbd "") 'crafted-evil/discourage-arrow-keys) + (define-key evil-normal-state-map (kbd "") 'crafted-evil/discourage-arrow-keys) + (evil-global-set-key 'motion (kbd "") 'crafted-evil/discourage-arrow-keys) + (evil-global-set-key 'motion (kbd "") 'crafted-evil/discourage-arrow-keys) + (evil-global-set-key 'motion (kbd "") 'crafted-evil/discourage-arrow-keys) + (evil-global-set-key 'motion (kbd "") '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