unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Drew Adams <drew.adams@oracle.com>
To: 27348@debbugs.gnu.org
Subject: bug#27348: 24.5; [PATCH] let defvars benefit from defcustom keywords and persistence
Date: Mon, 12 Jun 2017 14:34:35 -0700 (PDT)	[thread overview]
Message-ID: <85d6df89-9c08-4927-9b10-93a0b43808a7@default> (raw)

[-- Attachment #1: Type: text/plain, Size: 3983 bytes --]

This is an enhancement request, with a patch.

  [NOTE: I suggested this enhancement to emacs-devel in 2009.  There was
   exactly one reply, with only this text: "YAGNI".
   http://lists.gnu.org/archive/html/emacs-devel/2009-10/msg00668.html
   http://lists.gnu.org/archive/html/emacs-devel/2015-10/msg01481.html]

The ability to type-check, provide :set and :initialize trigger
functions, automatically :require libraries, add links to doc, associate
with one or more :groups, etc. - these are useful things to be able to
do with at least some defvars, not just with defcustoms.  Similarly, the
ability to persist non-option variables in a user's custom file can be
useful.

In sum, this enhancement makes it possible to uncouple interactive
customization from the other features that `custom.el' offers, in
particular, type-checking and persistence, and to provide the latter for
non-option variables.

Patch description:

1. New `defcustom' keyword `:not-custom-var'.  If non-nil, the variable
   does not satisfy `custom-variable-p'.  This means that users cannot
   customize it interactively, and it is not available for other
   interactive use (completion, `set-variable', inclusion in
   `apropos-user-option' output, etc.).

   Anyone and any code can still use `custom*' and other functions that
   do not check `custom-variable-p', to treat such a variable as a
   defcustom.  Similarly, users can still use `M-:', `C-x C-e' etc. to
   customize it.  See also #5, below.

2. New `defcustom' keyword `:not-custom-var'.  It causes property
   `not-custom-var' to be put on the variable symbol.  This property is
   what governs the behavior of `custom-variable-p'.

3. New macro `defvarc'.  It just invokes `defcustom', passing non-nil
   `:not-custom-var'.  The idea is to have a macro with a name similar
   to `defvar'.  Using it can make the non-customizable nature more
   apparent than using `defcustom' with explicit `:not-custom-var'.

   [Another possibility would be to directly modify `defvar', so that it
   optionally accepts `defcustom' keywords etc., but maybe that would
   not be acceptable immediately.  (For one thing, the cases of no
   initial value and no doc, `(defvar foo)' and `(defvar foo 4)', would
   still need to be supported.)]

4. `custom-variable-p' respects not only whether the variable has a
   non-nil `not-custom-var' property but also whether (new) global
   variable `custom-vars-all-customizable' is non-nil.  If either is
   true then the variable is not customizable (the predicate returns
   nil).

5. New macro `with-user-vars'.  It temporarily allows a set of variables
   to be customizable.  It takes as its first argument either a list of
   variables or the symbol `all', meaning all variables.  For `all', it
   just binds `custom-vars-all-customizable' to `t'.  For a list of
   variables, it sets property `not-custom-var' to `t' for each one.
   (The original property values are restored when done.)

I'm open as to how such a feature gets implemented.  That includes names
of things (`defvarc', for example) and whether or not to include this or
that part.  And I'm open to changes to the particular code in the patch.
There might be better ways to realize such a feature - what I came up
with is a pretty simple, naive approach.

FWIW: I haven't understood why apparently no one else has thought this
kind of thing could improve Emacs.  I've long thought that the power of
defcustom keywords and persistence should be freed from their coupling
with interactive customizing.  That combination is great, of course, but
it should not be obligatory - I see no reason why a non-user variable
should not take advantage of defcustom features.


In GNU Emacs 24.5.1 (i686-pc-mingw32)
 of 2015-04-11 on LEG570
Windowing system distributor `Microsoft Corp.', version 6.1.7601
Configured using:
 `configure --prefix=/c/usr --host=i686-pc-mingw32'

[-- Attachment #2: custom-2017-06-12.patch --]
[-- Type: application/octet-stream, Size: 3717 bytes --]

diff -u custom-2017-06-12.el custom-patched.el
--- custom-2017-06-12.el	2017-06-12 10:45:07.116868300 -0700
+++ custom-patched.el	2017-06-12 13:54:06.024567300 -0700
@@ -47,6 +47,10 @@
 (defvar custom-current-group-alist nil
   "Alist of (FILE . GROUP) indicating the current group to use for FILE.")
 
+(defvar custom-vars-all-customizable nil
+  "Non-nil means all variables defined using `defcustom' are customizable.
+This applies also to variables defined using `defvarc'.")
+
 ;;; The `defcustom' Macro.
 
 (defun custom-initialize-default (symbol exp)
@@ -318,6 +322,9 @@
         Load file FILE (a string) before displaying this customization
         item.  Loading is done with `load', and only if the file is
         not already loaded.
+:not-custom-var
+        Non-nil means the variable is not customizable.  More
+        precisely, it means that `custom-variable-p' returns nil.
 
 If SYMBOL has a local binding, then this form affects the local
 binding.  This is normally not what you want.  Thus, if you need
@@ -347,6 +354,34 @@
     ,doc
     ,@args))
 
+(defmacro defvarc (symbol &optional standard doc &rest args)
+  "Same as `defcustom' with non-nil keyword `:not-custom-var'.
+That is, SYMBOL does not satisfy `custom-variable-p'.
+
+Using this is equivalent to using `defcustom' with non-nil keyword
+`:not-custom-var' (which puts property `not-custom-var' on SYMBOL)."
+  `(defcustom ,symbol ,standard ,doc :not-custom-var t ,@args))
+
+(defmacro with-user-vars (symbols &rest body)
+  "Treat SYMBOLS as custom variables within the scope of the call.
+As an alternative to being a list of symbols, SYMBOLS can be the
+symbol `all', in which case all symbols defined using `defcustom' or
+`defvarc' are treated as custom variables."
+  (let ((symbs  (make-symbol "symbs"))
+        (symb   (make-symbol "symb"))
+        (binds  (make-symbol "binds"))
+        (s.p    (make-symbol "s.p")))
+    `(let ((,symbs  ',symbols))
+       (if (eq 'all ,symbs)
+           (let ((custom-vars-all-customizable  t)) ,@body)
+         (let ((,binds  (mapcar (lambda (,symb) (cons ,symb (get ,symb 'not-custom-var)))
+                                ,symbs)))
+           (unwind-protect
+                (progn (dolist (,symb  ,symbs) (put ,symb 'not-custom-var nil))
+                       ,@body)
+             (dolist (,s.p  ,binds)
+               (put (car ,s.p) 'not-custom-var (cdr ,s.p)))))))))
+
 ;;; The `defface' Macro.
 
 (defmacro defface (face spec doc &rest args)
@@ -538,6 +573,8 @@
 	 (put symbol 'custom-tag value))
 	((eq keyword :set-after)
 	 (custom-add-dependencies symbol value))
+        ((eq keyword :not-custom-var)
+         (put symbol 'not-custom-var value))
 	(t
 	 (error "Unknown keyword %s" keyword))))
 
@@ -603,11 +640,16 @@
   "Return non-nil if VARIABLE is a customizable variable.
 A customizable variable is either (i) a variable whose property
 list contains a non-nil `standard-value' or `custom-autoload'
-property, or (ii) an alias for another customizable variable."
-  (when (symbolp variable)
-    (setq variable (indirect-variable variable))
-    (or (get variable 'standard-value)
-	(get variable 'custom-autoload))))
+property, or (ii) an alias for another customizable variable.
+
+However, this returns nil if VARIABLE has non-nil property
+`not-custom-var', unless `custom-vars-all-customizable' is also
+non-nil."
+  (and (symbolp variable)
+       (or custom-vars-all-customizable  (not (get variable 'not-custom-var)))
+       (setq variable  (indirect-variable variable))
+       (or (get variable 'standard-value)
+           (get variable 'custom-autoload))))
 
 (define-obsolete-function-alias 'user-variable-p 'custom-variable-p "24.3")
 

             reply	other threads:[~2017-06-12 21:34 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-12 21:34 Drew Adams [this message]
2019-06-24 16:35 ` bug#27348: 24.5; [PATCH] let defvars benefit from defcustom keywords and persistence Lars Ingebrigtsen
2019-06-24 18:04   ` Drew Adams
2020-08-10 15:04 ` Lars Ingebrigtsen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=85d6df89-9c08-4927-9b10-93a0b43808a7@default \
    --to=drew.adams@oracle.com \
    --cc=27348@debbugs.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).