Add a theme and minor mode for new users

* doc/emacs/custom.texi (Beginners Theme): Document new theme.
* etc/NEWS: Mention new theme.
* etc/themes/newcomers-presets-theme.el: New file including
new theme.
This commit is contained in:
Philip Kaludercic 2026-02-14 16:33:51 +01:00
parent 0f832ad8bf
commit ed030e7942
No known key found for this signature in database
4 changed files with 202 additions and 0 deletions

View file

@ -32,6 +32,7 @@ Reference Manual}.
* Init File:: How to write common customizations in the
initialization file.
* Authentication:: Keeping persistent authentication information.
* Newcomers Theme:: A theme that enables options for newcomers.
@end menu
@ -3230,3 +3231,22 @@ auth, Emacs auth-source}.
configured backend, some of the backends offer to save it
persistently. This can be changed by customizing the user option
@code{auth-source-save-behavior}.
@node Newcomers Theme
@section Newcomers Theme
The default appearance and behaviour of Emacs is traditionally
conservative, not changing much between releases. While each release
brings more features, these are not enabled out of the box to not
disrupt existing workflows.
As a remedy for new users who would like to enable a larger set of
features in one fell swoop, the @code{newcomers-presets} theme
(@pxref{Custom Themes}) sets a collection of users options considered to
be too invasive by default, but useful for users acquainted with
conventions from other programs trying to learn Emacs.
Keep in mind that the functionality enabled by this theme may change
between releases, including adding new functionality that is expected to
be of value for new users or removing old functionality that is regarded
to be confusing or superseded.

View file

@ -3325,6 +3325,14 @@ If non-nil, FFAP always finds remote files in buffers with remote
'default-directory'. If nil, FFAP finds local files first for absolute
file names in above buffers. The default is nil.
+++
*** New theme 'newcomers-presets'
This new theme configures user options and minor modes that might
interest new users, but would otherwise be too invasive to enable by
default. Recall that an Emacs theme is a generic collection of
settings, that doesn't have to affect the appearance. See the Info node
"(emacs) Newcomers Theme" for more information.
** Edebug
+++

View file

@ -0,0 +1,142 @@
;;; newcomers-presets-theme.el --- Theme of user options for newcomers -*- lexical-binding:t -*-
;; Copyright (C) 2026 Free Software Foundation, Inc.
;; Author: Philip Kaludercic <philipk@posteo.net>
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary
;; A theme that enables user options new users might be interested in.
;; The guideline to enabling a feature is "would this interest someone
;; who wouldn't even know that this option exists?". Please avoid
;; opinionated cosmetic changes, that is the job of regular/color-scheme
;; themes.
;;; Code:
;; We define a `newcomers-presets-mode' that we can use to execute custom code
;; that we cannot express by setting existing users options.
(defvar newcomers-presets-mode-enabled-local-modes
'((prog-mode-hook . display-line-numbers-mode)
(prog-mode-hook . flymake-mode)
(prog-mode-hook . flyspell-prog-mode)
(text-mode-hook . display-line-numbers-mode)
(text-mode-hook . flyspell-mode)
)
"Alist mapping hooks to functions.
The functions are added to the corresponding hooks when enabling
`newcomers-presets-mode', and removed when disabling the mode.")
(defconst newcomers-presets--dnt-prop
(make-symbol "newcomers-presets-no-not-touch")
"A fresh constant to use as a symbol property.
The symbol property is used by `newcomers-presets-mode'")
;;;###autoload
(define-minor-mode newcomers-presets-mode
"A minor mode associated with the `newcomers-presets' theme.
This minor mode will enable and disable the theme on startup."
:global t
(cl-letf (((symbol-function 'newcomers-presets-mode)
;; As the theme enables/disables this mode we have to
;; prevent in indefinite mutual recursion to allow
;; `newcomers-presets-mode' to enable the `newcomers-presets' theme and
;; vice versa.
#'ignore))
(if newcomers-presets-mode
(enable-theme 'newcomers-presets)
(disable-theme 'newcomers-presets)))
;; TODO: extend `custom-theme-set-variables' to support function local
;; hooks.
(pcase-dolist (`(,hook . ,fn) newcomers-presets-mode-enabled-local-modes)
(cond
(newcomers-presets-mode
;; We check if a function is already in the hook, to avoid
;; removing it later if the user disables the theme.
(when (run-hook-wrapped hook (lambda (ent &rest _) (eq fn ent)))
(push fn (get hook newcomers-presets--dnt-prop)))
(add-hook hook fn))
(t
(unless (memq fn (get hook newcomers-presets--dnt-prop))
(remove-hook hook fn))
(put hook newcomers-presets--dnt-prop '())))))
;;;###theme-autoload
(deftheme newcomers-presets
"Theme of user options settings interesting for newcomers."
:kind 'user-options)
(custom-theme-set-variables
'newcomers-presets
'(newcomers-presets-mode t)
;;;; Appearance-related options
'(font-use-system-font t)
'(frame-resize-pixelwise t)
'(window-resize-pixelwise t)
;;;; Mouse-related options
'(context-menu-mode t)
'(save-interprogram-paste-before-kill t)
'(mouse-yank-at-point t)
'(pixel-scroll-mode t)
;; '(pixel-scroll-precision-mode t) ;; see bug#69972
'(mouse-drag-and-drop-region t)
'(mouse-drag-and-drop-region-cross-program t)
'(mouse-drag-mode-line-buffer t)
;;;; Persistence-related options
'(savehist-mode t)
'(save-place-mode t)
'(recentf-mode t)
;;;; Editing-related options
'(electric-pair-mode t)
'(repeat-mode t)
'(delete-selection-mode t)
'(editorconfig-mode t)
;;;; Directory managment-related options
'(dired-auto-revert-buffer t)
'(dired-mouse-drag-files t)
;;;; File-related options
'(vc-auto-revert-mode t)
;;;; Completion-related options
'(minibuffer-visible-completions t)
'(completions-detailed t)
'(completions-group t)
'(completion-auto-select 'second-tab)
'(completion-eager-update t)
'(completion-styles '(basic emacs22 flex))
'(global-completion-preview-mode t)
'(tab-always-indent 'complete)
'(which-key-mode t)
;;;; Package-related options
'(package-autosuggest-mode t)
'(package-menu-use-current-if-no-marks nil)
)
(provide-theme 'newcomers-presets)
;;; newcomers-presets-theme.el ends here

View file

@ -2158,6 +2158,38 @@ a face or button specification."
:face 'variable-pitch "To quit a partially entered command, type "
:face 'default "Control-g"
:face 'variable-pitch ".\n")
(fancy-splash-insert
:face '(variable-pitch (:height 0.8))
"Enable "
:link `("newcomer-friendly"
,(lambda (_button) (info "(emacs) Newcomers Theme")))
" options: ")
(let ((checked (create-image "checked.xpm"
nil nil :ascent 'center))
(unchecked (create-image "unchecked.xpm"
nil nil :ascent 'center))
(enabled (custom-theme-enabled-p 'newcomers-presets)))
(insert-button
" "
:on-glyph checked
:off-glyph unchecked
'checked enabled
'display (if enabled checked 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))
(disable-theme 'newcomers-presets))
(overlay-put button 'checked t)
(overlay-put button 'display
(overlay-get button :on-glyph))
(load-theme 'newcomers-presets)))))
(fancy-splash-insert :face 'variable-pitch "\n")
(save-restriction
(narrow-to-region (point) (point))
(fancy-splash-insert :face '(variable-pitch font-lock-builtin-face)