From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Emanuel Berg via Users list for the GNU Emacs text editor Newsgroups: gmane.emacs.help Subject: Re: Is there a way of setting a variable only when it exists? Date: Tue, 15 Mar 2022 12:29:32 +0100 Message-ID: <87v8wf1mjn.fsf@zoho.eu> References: <87lexdul8e.fsf@mbork.pl> <878rtcir1h.fsf@zoho.eu> <87a6drviwp.fsf@mbork.pl> Reply-To: Emanuel Berg Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="30112"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) To: help-gnu-emacs@gnu.org Cancel-Lock: sha1:YNO/Mawh8BS+68u/pbWGxkRhb7Y= Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Tue Mar 15 16:38:04 2022 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nU9FM-0007eQ-9J for geh-help-gnu-emacs@m.gmane-mx.org; Tue, 15 Mar 2022 16:38:04 +0100 Original-Received: from localhost ([::1]:44208 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nU9FK-0006Aw-UW for geh-help-gnu-emacs@m.gmane-mx.org; Tue, 15 Mar 2022 11:38:02 -0400 Original-Received: from eggs.gnu.org ([209.51.188.92]:42226) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nU5N2-0006F3-Or for help-gnu-emacs@gnu.org; Tue, 15 Mar 2022 07:29:49 -0400 Original-Received: from ciao.gmane.io ([116.202.254.214]:46034) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nU5Mz-0001Ud-JK for help-gnu-emacs@gnu.org; Tue, 15 Mar 2022 07:29:43 -0400 Original-Received: from list by ciao.gmane.io with local (Exim 4.92) (envelope-from ) id 1nU5Mx-0005OL-L1 for help-gnu-emacs@gnu.org; Tue, 15 Mar 2022 12:29:39 +0100 X-Injected-Via-Gmane: http://gmane.org/ Mail-Followup-To: help-gnu-emacs@gnu.org Mail-Copies-To: never Received-SPF: pass client-ip=116.202.254.214; envelope-from=geh-help-gnu-emacs@m.gmane-mx.org; helo=ciao.gmane.io X-Spam_score_int: -16 X-Spam_score: -1.7 X-Spam_bar: - X-Spam_report: (-1.7 / 5.0 requ) BAYES_00=-1.9, HEADER_FROM_DIFFERENT_DOMAINS=0.249, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Tue, 15 Mar 2022 11:35:49 -0400 X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "help-gnu-emacs" Xref: news.gmane.io gmane.emacs.help:136582 Archived-At: Jean Louis wrote: >> Understood. Perhaps that was a lame attempt at humour on >> my part. > > I totally understand it, people introducing their own > understanding of definitions will have troubles > communicating with others, it causes conflicts. ... > First we have to agree on what is the accepted definition. > There is nothing wrong in changing such definitions, though > it goes gradually again with agreements among people. Haha :) Anyway, here is some custom code I found by doing C-h f defcustom RET TAB RET ... (I don't have to do the TAB LOL. https://dataswamp.org/~incal/emacs-init/help-incal.el ) OK, here is the custom code. Does it look like anything you want to hand over your data to for safe-and-sound handling? Probably the best interface in the world? We came out of a crazy mind - and walked out on a piece of paper ... (defun custom-declare-variable (symbol default doc &rest args) "Like `defcustom', but SYMBOL and DEFAULT are evaluated as normal arguments. DEFAULT should be an expression to evaluate to compute the default value, not the default value itself. DEFAULT is stored as SYMBOL's standard value, in SYMBOL's property `standard-value'. At the same time, SYMBOL's property `force-value' is set to nil, as the value is no longer rogue." (put symbol 'standard-value (purecopy (list default))) ;; Maybe this option was rogue in an earlier version. It no longer is. (when (get symbol 'force-value) (put symbol 'force-value nil)) (if (keywordp doc) (error "Doc string is missing")) (let ((initialize #'custom-initialize-reset) (requests nil) ;; Whether automatically buffer-local. buffer-local) (unless (memq :group args) (let ((cg (custom-current-group))) (when cg (custom-add-to-group cg symbol 'custom-variable)))) (while args (let ((keyword (pop args))) (unless (symbolp keyword) (error "Junk in args %S" args)) (unless args (error "Keyword %s is missing an argument" keyword)) (let ((value (pop args))) ;; Can't use `pcase' because it is loaded after `custom.el' ;; during bootstrap. See `loadup.el'. (cond ((eq keyword :initialize) (setq initialize value)) ((eq keyword :set) (put symbol 'custom-set value)) ((eq keyword :get) (put symbol 'custom-get value)) ((eq keyword :require) (push value requests)) ((eq keyword :risky) (put symbol 'risky-local-variable value)) ((eq keyword :safe) (put symbol 'safe-local-variable value)) ((eq keyword :local) (when (memq value '(t permanent)) (setq buffer-local t)) (when (eq value 'permanent) (put symbol 'permanent-local t))) ((eq keyword :type) (put symbol 'custom-type (purecopy value))) ((eq keyword :options) (if (get symbol 'custom-options) ;; Slow safe code to avoid duplicates. (mapc (lambda (option) (custom-add-option symbol option)) value) ;; Fast code for the common case. (put symbol 'custom-options (copy-sequence value)))) (t (custom-handle-keyword symbol keyword value 'custom-variable)))))) ;; Set the docstring, record the var on load-history, as well ;; as set the special-variable-p flag. (internal--define-uninitialized-variable symbol doc) (put symbol 'custom-requests requests) ;; Do the actual initialization. (unless custom-dont-initialize (funcall initialize symbol default) ;; If there is a value under saved-value that wasn't saved by the user, ;; reset it: we used that property to stash the value, but we don't need ;; it anymore. ;; This can happen given the following: ;; 1. The user loaded a theme that had a setting for an unbound ;; variable, so we stashed the theme setting under the saved-value ;; property in `custom-theme-recalc-variable'. ;; 2. Then, Emacs evaluated the defcustom for the option ;; (e.g., something required the file where the option is defined). ;; If we don't reset it and the user later sets this variable via ;; Customize, we might end up saving the theme setting in the custom-file. ;; See the test `custom-test-no-saved-value-after-customizing-option'. (let ((theme (caar (get symbol 'theme-value)))) (when (and theme (not (eq theme 'user)) (get symbol 'saved-value)) (put symbol 'saved-value nil)))) (when buffer-local (make-variable-buffer-local symbol))) (run-hooks 'custom-define-hook) symbol) (defmacro defcustom (symbol standard doc &rest args) "Declare SYMBOL as a customizable variable. SYMBOL is the variable name; it should not be quoted. STANDARD is an expression specifying the variable's standard value. It should not be quoted. It is evaluated once by `defcustom', and the value is assigned to SYMBOL if the variable is unbound. The expression itself is also stored, so that Customize can re-evaluate it later to get the standard value. DOC is the variable documentation. This macro uses `defvar' as a subroutine, which also marks the variable as \"special\", so that it is always dynamically bound even when `lexical-binding' is t. The remaining arguments to `defcustom' should have the form [KEYWORD VALUE]... The following keywords are meaningful: :type VALUE should be a widget type for editing the symbol's value. Every `defcustom' should specify a value for this keyword. See Info node `(elisp) Customization Types' for a list of base types and useful composite types. :options VALUE should be a list of valid members of the widget type. :initialize VALUE should be a function used to initialize the variable. It takes two arguments, the symbol and value given in the `defcustom' call. The default is `custom-initialize-reset'. :set VALUE should be a function to set the value of the symbol when using the Customize user interface. It takes two arguments, the symbol to set and the value to give it. The function should not modify its value argument destructively. The default choice of function is `set-default'. :get VALUE should be a function to extract the value of symbol. The function takes one argument, a symbol, and should return the current value for that symbol. The default choice of function is `default-value'. :require VALUE should be a feature symbol. If you save a value for this option, then when your init file loads the value, it does (require VALUE) first. :set-after VARIABLES Specifies that SYMBOL should be set after the list of variables VARIABLES when both have been customized. :risky Set SYMBOL's `risky-local-variable' property to VALUE. :safe Set SYMBOL's `safe-local-variable' property to VALUE. See Info node `(elisp) File Local Variables'. :local If VALUE is t, mark SYMBOL as automatically buffer-local. If VALUE is `permanent', also set SYMBOL's `permanent-local' property to t. The following common keywords are also meaningful. :group VALUE should be a customization group. Add SYMBOL (or FACE with `defface') to that group. :link LINK-DATA Include an external link after the documentation string for this item. This is a sentence containing an active field which references some other documentation. There are several alternatives you can use for LINK-DATA: (custom-manual INFO-NODE) Link to an Info node; INFO-NODE is a string which specifies the node name, as in \"(emacs)Top\". (info-link INFO-NODE) Like `custom-manual' except that the link appears in the customization buffer with the Info node name. (url-link URL) Link to a web page; URL is a string which specifies the URL. (emacs-commentary-link LIBRARY) Link to the commentary section of LIBRARY. (emacs-library-link LIBRARY) Link to an Emacs Lisp LIBRARY file. (file-link FILE) Link to FILE. (function-link FUNCTION) Link to the documentation of FUNCTION. (variable-link VARIABLE) Link to the documentation of VARIABLE. (custom-group-link GROUP) Link to another customization GROUP. You can specify the text to use in the customization buffer by adding `:tag NAME' after the first element of the LINK-DATA; for example, (info-link :tag \"foo\" \"(emacs)Top\") makes a link to the Emacs manual which appears in the buffer as `foo'. An item can have more than one external link; however, most items have none at all. :version VALUE should be a string specifying that the variable was first introduced, or its default value was changed, in Emacs version VERSION. :package-version VALUE should be a list with the form (PACKAGE . VERSION) specifying that the variable was first introduced, or its default value was changed, in PACKAGE version VERSION. This keyword takes priority over :version. For packages which are bundled with Emacs releases, the PACKAGE and VERSION must appear in the alist `customize-package-emacs-version-alist'. Since PACKAGE must be unique and the user might see it in an error message, a good choice is the official name of the package, such as MH-E or Gnus. :tag LABEL Use LABEL, a string, instead of the item's name, to label the item in customization menus and buffers. :load FILE Load file FILE (a string) before displaying this customization item. Loading is done with `load', and only if the file is not already loaded. If SYMBOL has a local binding, then this form affects the local binding. This is normally not what you want. Thus, if you need to load a file defining variables with this form, or with `defvar' or `defconst', you should always load that file _outside_ any bindings for these variables. (`defvar' and `defconst' behave similarly in this respect.) This macro calls `custom-declare-variable'. If you want to programmatically alter a customizable variable (for instance, to write a package that extends the syntax of a variable), you can call that function directly. See Info node `(elisp) Customization' in the Emacs Lisp manual for more information." (declare (doc-string 3) (debug (name body)) (indent defun)) ;; It is better not to use backquote in this file, ;; because that makes a bootstrapping problem ;; if you need to recompile all the Lisp files using interpreted code. `(custom-declare-variable ',symbol ,(if lexical-binding ;; The STANDARD arg should be an expression that evaluates to ;; the standard value. The use of `eval' for it is spread ;; over many different places and hence difficult to ;; eliminate, yet we want to make sure that the `standard' ;; expression is checked by the byte-compiler, and that ;; lexical-binding is obeyed, so quote the expression with ;; `lambda' rather than with `quote'. ``(funcall #',(lambda () "" ,standard)) `',standard) ,doc ,@args)) -- underground experts united https://dataswamp.org/~incal