* Need some education on defmacro define-toggle @ 2009-12-28 5:16 Lennart Borgman 2009-12-28 19:28 ` Lennart Borgman [not found] ` <mailman.352.1262028532.18930.help-gnu-emacs@gnu.org> 0 siblings, 2 replies; 6+ messages in thread From: Lennart Borgman @ 2009-12-28 5:16 UTC (permalink / raw) To: emacs help I just got into some trouble because of a badly written macro I believe. After the long discussions about defmacro here I wonder if anyone wants to help me out. How should I write the defmacro below? I need to be able to autolad the defmacro in a little bit strange way too. It is not a normal autoload. I want to redefine it. I do something like: (defun web-autoload (fun src docstring interactive type) "Similar to autoload, but the SRC arg is different." (let ((int (when interactive '(interactive)))) (cond ((eq type 'macro) (setq type 'defmacro)) (t (setq type 'defun))) (eval `(web-autoload-1 ,fun ,src ,docstring ,int ,type)))) (defmacro web-autoload-1 (fun src docstring interactive type) .... (let ((the-macro (append '(,fun) args nil))) (eval the-macro)) ) Here is the troublesome macro: (defmacro define-toggle (symbol value doc &rest args) "Declare SYMBOL as a customizable variable with a toggle function. The purpose of this macro is to define a defcustom and a toggle function suitable for use in a menu. The arguments have the same meaning as for `defcustom' with these restrictions: - The :type keyword cannot be used. Type is always 'boolean. - VALUE must be t or nil. DOC and ARGS are just passed to `defcustom'. A `defcustom' named SYMBOL with doc-string DOC and a function named SYMBOL-toggle is defined. The function toggles the value of SYMBOL. It takes no parameters. To create a menu item something similar to this can be used: \(define-key map [SYMBOL] \(list 'menu-item \"Toggle nice SYMBOL\" 'SYMBOL-toggle :button '(:toggle . SYMBOL)))" (declare (doc-string 3)) (list 'progn (let ((var-decl (list 'custom-declare-variable (list 'quote symbol) (list 'quote value) doc))) (while args (let ((arg (car args))) (setq args (cdr args)) (unless (symbolp arg) (error "Junk in args %S" args)) (let ((keyword arg) (value (car args))) (unless args (error "Keyword %s is missing an argument" keyword)) (setq args (cdr args)) (cond ((not (memq keyword '(:type))) (setq var-decl (append var-decl (list keyword value)))) (t (lwarn '(define-toggle) :error "Keyword %s can't be used here" keyword)))))) (when (assoc :type var-decl) (error ":type is set. Should not happen!")) (setq var-decl (append var-decl (list :type '(quote boolean)))) var-decl) (let* ((SYMBOL-toggle (intern (concat (symbol-name symbol) "-toggle"))) (SYMBOL-name (symbol-name symbol)) (fun-doc (concat "Toggles the \(boolean) value of `" SYMBOL-name "'.\n" "For how to set it permanently see this variable.\n" ;;"\nDescription of `" SYMBOL-name "':\n" doc ))) `(defun ,SYMBOL-toggle () ,fun-doc (interactive) (customize-set-variable (quote ,symbol) (not ,symbol))) ))) ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Need some education on defmacro define-toggle 2009-12-28 5:16 Need some education on defmacro define-toggle Lennart Borgman @ 2009-12-28 19:28 ` Lennart Borgman [not found] ` <mailman.352.1262028532.18930.help-gnu-emacs@gnu.org> 1 sibling, 0 replies; 6+ messages in thread From: Lennart Borgman @ 2009-12-28 19:28 UTC (permalink / raw) To: emacs help On Mon, Dec 28, 2009 at 6:16 AM, Lennart Borgman <lennart.borgman@gmail.com> wrote: > I just got into some trouble because of a badly written macro I > believe. After the long discussions about defmacro here I wonder if > anyone wants to help me out. How should I write the defmacro below? I resorted to self education (which is not too bad). However I still got problems - just on a more complicated level. The macro now looks like this: (defmacro define-toggle (symbol value doc &rest args) "Declare SYMBOL as a customizable variable with a toggle function." (declare (doc-string 3) (debug t)) (let* ((SYMBOL-toggle (intern (concat (symbol-name symbol) "-toggle"))) (SYMBOL-name (symbol-name symbol)) (var-doc doc) (fun-doc (concat "Toggles the \(boolean) value of `" SYMBOL-name "'.\nFor how to set it permanently see this variable.\n"))) (let ((var (append `(defcustom ,symbol ,value ,var-doc) args nil)) (fun `(defun ,SYMBOL-toggle () ,fun-doc (interactive) (customize-set-variable (quote ,symbol) (not ,symbol))))) `(list 'progn ,var ,fun)))) This seems to work, but if the call to define-toggle already has been done then loading a file with this define-toggle gives trouble: Debugger entered--Lisp error: (void-variable rngalt-display-validation-header-toggle) (progn rngalt-display-validation-header rngalt-display-validation-header-toggle) (define-toggle rngalt-display-validation-header t "Display XML validation headers at the top of buffer when t.\nThe validation header is only displayed in buffers where the main\nmajor mode is derived from `nxml-mode'." :set (lambda (sym val) (set-default sym val) (rngalt-update-validation-header-overlay-everywhere)) :group (quote relax-ng) :group (quote nxhtml)) eval-buffer(#<buffer *load*<3>> nil "c:/emacs/p/091204/EmacsW32/nxhtml/nxhtml/rngalt.el" nil t) ; Reading at buffer position 24737 load-with-code-conversion("c:/emacs/p/091204/EmacsW32/nxhtml/nxhtml/rngalt.el" "c:/emacs/p/091204/EmacsW32/nxhtml/nxhtml/rngalt.el" t t) require(rngalt nil t) (progn (require (quote rngalt) nil t)) (eval-and-compile (require (quote rngalt) nil t)) eval-buffer(#<buffer *load*<2>> nil "c:/emacs/p/091204/EmacsW32/nxhtml/nxhtml/nxhtml-mode.el" nil t) ; Reading at buffer position 2959 load-with-code-conversion("c:/emacs/p/091204/EmacsW32/nxhtml/nxhtml/nxhtml-mode.el" "c:/emacs/p/091204/EmacsW32/nxhtml/nxhtml/nxhtml-mode.el" t t) require(nxhtml-mode nil t) (progn (require (quote nxhtml-mode) nil t)) (if (fboundp (quote nxml-mode)) (progn (require ... nil t))) (when (fboundp (quote nxml-mode)) (require (quote nxhtml-mode) nil t)) (progn (when (fboundp ...) (require ... nil t))) (eval-when-compile (when (fboundp ...) (require ... nil t))) eval-buffer(#<buffer *load*> nil "c:/emacs/p/091204/EmacsW32/nxhtml/nxhtml/nxhtml-menu.el" nil t) ; Reading at buffer position 3227 load-with-code-conversion("c:/emacs/p/091204/EmacsW32/nxhtml/nxhtml/nxhtml-menu.el" "c:/emacs/p/091204/EmacsW32/nxhtml/nxhtml/nxhtml-menu.el" nil nil) load("c:/emacs/p/091204/EmacsW32/nxhtml/nxhtml/nxhtml-menu.el") (let* ((vcs ...) (base-url ...) (rel-url ...) (base-dir ...) (rel-url-el ...) file-url dl-file) (unless (stringp base-url) (setq base-url ...)) (unless (stringp base-dir) (setq base-dir ...)) (setq dl-file (expand-file-name rel-url-el base-dir)) (message "dl-file=%s" dl-file) (unless (file-exists-p dl-file) (web-vcs-get-missing-matching-files vcs base-url base-dir rel-url-el) (unless ... ...)) (load dl-file) (unless (symbol-function ...) (setq err ...))) (if (not (listp ...)) (let (...) (load ...) (unless ... ...)) (let* (... ... ... ... ... file-url dl-file) (unless ... ...) (unless ... ...) (setq dl-file ...) (message "dl-file=%s" dl-file) (unless ... ... ...) (load dl-file) (unless ... ...))) (let* ((lib-web ...) (old-hist-elt ...) (auto-fun ...) err) (fset (quote nxhtml-global-minor-mode) nil) (if (not ...) (let ... ... ...) (let* ... ... ... ... ... ... ... ...)) (if (not err) (progn ... ...) (fset ... auto-fun) (error "web-autoload: %s" err))) nxhtml-global-minor-mode(1) (let* ((util-dir ...) (related-dir ...) (nxhtml-dir ...) (company-dir ...) (tests-dir ...)) (add-to-list (quote load-path) nxhtml-dir) (add-to-list (quote load-path) related-dir) (add-to-list (quote load-path) util-dir) (add-to-list (quote load-path) nxhtml-install-dir) (add-to-list (quote load-path) company-dir) (add-to-list (quote load-path) tests-dir) (setq web-autoload-default-filename-element nxhtml-install-dir) (message "... nXhtml loading %.1f seconds elapsed ..." (- ... nxhtml-load-time-start)) (load (expand-file-name "nxhtml-loaddefs" nxhtml-install-dir)) (message "... nXhtml loading %.1f seconds elapsed ..." (- ... nxhtml-load-time-start)) (message "Turn on `nxhtml-global-minor-mode' unconditionally") (nxhtml-global-minor-mode 1) (message "... nXhtml loading %.1f seconds elapsed ..." (- ... nxhtml-load-time-start)) (when (fboundp ...) (load ...) (rncpp-patch-xhtml-loader)) (message "... nXhtml loading %.1f seconds elapsed ..." (- ... nxhtml-load-time-start)) (load (expand-file-name "nxhtml/nxhtml-autoload" nxhtml-install-dir))) (if nil nil (provide (quote nxhtml-autostart)) (if (< emacs-major-version 23) (load ...) (let ... ...)) (let* (... ... ... ... ...) (add-to-list ... nxhtml-dir) (add-to-list ... related-dir) (add-to-list ... util-dir) (add-to-list ... nxhtml-install-dir) (add-to-list ... company-dir) (add-to-list ... tests-dir) (setq web-autoload-default-filename-element nxhtml-install-dir) (message "... nXhtml loading %.1f seconds elapsed ..." ...) (load ...) (message "... nXhtml loading %.1f seconds elapsed ..." ...) (message "Turn on `nxhtml-global-minor-mode' unconditionally") (nxhtml-global-minor-mode 1) (message "... nXhtml loading %.1f seconds elapsed ..." ...) (when ... ... ...) (message "... nXhtml loading %.1f seconds elapsed ..." ...) (load ...)) (message "... nXhtml loading %.1f seconds elapsed ..." (- ... nxhtml-load-time-start)) (when nxhtml-flymake-setup (flymake-js-load) (flymake-css-load) (flymake-java-1-load) (add-hook ... ...)) (nxhtml-list-loaded-features nil) (message "Nxml/Nxhtml Autostart.el loaded in %.1f seconds" (- ... nxhtml-load-time-start))) (unless nil (provide (quote nxhtml-autostart)) (if (< emacs-major-version 23) (load ...) (let ... ...)) (let* (... ... ... ... ...) (add-to-list ... nxhtml-dir) (add-to-list ... related-dir) (add-to-list ... util-dir) (add-to-list ... nxhtml-install-dir) (add-to-list ... company-dir) (add-to-list ... tests-dir) (setq web-autoload-default-filename-element nxhtml-install-dir) (message "... nXhtml loading %.1f seconds elapsed ..." ...) (load ...) (message "... nXhtml loading %.1f seconds elapsed ..." ...) (message "Turn on `nxhtml-global-minor-mode' unconditionally") (nxhtml-global-minor-mode 1) (message "... nXhtml loading %.1f seconds elapsed ..." ...) (when ... ... ...) (message "... nXhtml loading %.1f seconds elapsed ..." ...) (load ...)) (message "... nXhtml loading %.1f seconds elapsed ..." (- ... nxhtml-load-time-start)) (when nxhtml-flymake-setup (flymake-js-load) (flymake-css-load) (flymake-java-1-load) (add-hook ... ...)) (nxhtml-list-loaded-features nil) (message "Nxml/Nxhtml Autostart.el loaded in %.1f seconds" (- ... nxhtml-load-time-start))) eval-buffer() ; Reading at buffer position 8253 call-interactively(eval-buffer nil nil) There is obviously something I got wrong in the evaluation order since now, in this situation, the macro now tries to evaluate (progn rngalt-display-validation-header rngalt-display-validation-header-toggle) I expected it to redefine the defcustom and the defun instead. Can someone please try to explain what is going on? ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <mailman.352.1262028532.18930.help-gnu-emacs@gnu.org>]
* Re: Need some education on defmacro define-toggle [not found] ` <mailman.352.1262028532.18930.help-gnu-emacs@gnu.org> @ 2009-12-28 21:33 ` Pascal J. Bourguignon 2009-12-28 21:58 ` Lennart Borgman [not found] ` <mailman.358.1262037566.18930.help-gnu-emacs@gnu.org> 0 siblings, 2 replies; 6+ messages in thread From: Pascal J. Bourguignon @ 2009-12-28 21:33 UTC (permalink / raw) To: help-gnu-emacs Lennart Borgman <lennart.borgman@gmail.com> writes: > On Mon, Dec 28, 2009 at 6:16 AM, Lennart Borgman > <lennart.borgman@gmail.com> wrote: >> I just got into some trouble because of a badly written macro I >> believe. After the long discussions about defmacro here I wonder if >> anyone wants to help me out. How should I write the defmacro below? > > > I resorted to self education (which is not too bad). However I still > got problems - just on a more complicated level. The macro now looks > like this: > > (defmacro define-toggle (symbol value doc &rest args) > "Declare SYMBOL as a customizable variable with a toggle function." > (declare (doc-string 3) (debug t)) > (let* ((SYMBOL-toggle (intern (concat (symbol-name symbol) "-toggle"))) > (SYMBOL-name (symbol-name symbol)) > (var-doc doc) > (fun-doc (concat "Toggles the \(boolean) value of `" SYMBOL-name > "'.\nFor how to set it permanently see this > variable.\n"))) > (let ((var (append `(defcustom ,symbol ,value ,var-doc) > args > nil)) > (fun `(defun ,SYMBOL-toggle () > ,fun-doc > (interactive) > (customize-set-variable (quote ,symbol) (not ,symbol))))) > `(list 'progn ,var ,fun)))) > > This seems to work, but if the call to define-toggle already has been > done then loading a file with this define-toggle gives trouble: > > Debugger entered--Lisp error: (void-variable rngalt-display-validation-header-toggle) > (progn rngalt-display-validation-header rngalt-display-validation-header-toggle) > (define-toggle rngalt-display-validation-header t "Display XML validation headers at the top of buffer when t.\nThe validation header is only displayed in buffers where the main\nmajor mode is derivd from `nxml-mode'." :set (lambda (sym val) (set-default sym val) (rngalt-update-validation-header-overlay-everywhere)) :group (quote relax-ng) :group (quote nxhtml)) > > ... > > There is obviously something I got wrong in the evaluation order since > now, in this situation, the macro now tries to evaluate > > (progn rngalt-display-validation-header rngalt-display-validation-header-toggle) > > I expected it to redefine the defcustom and the defun instead. > Can someone please try to explain what is going on? There must be an eval somewhere that tries to evaluate one time too many. That said, why doesn't your macro just return `(progn ,var ,fun) instead of returning a list form that evaluates to something such as (progn rngalt-display-validation-header rngalt-display-validation-header-toggle) that needs to be evaluated (and of course fails since you didn't define these symbols as variables)? -- __Pascal Bourguignon__ http://www.informatimago.com/ ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Need some education on defmacro define-toggle 2009-12-28 21:33 ` Pascal J. Bourguignon @ 2009-12-28 21:58 ` Lennart Borgman [not found] ` <mailman.358.1262037566.18930.help-gnu-emacs@gnu.org> 1 sibling, 0 replies; 6+ messages in thread From: Lennart Borgman @ 2009-12-28 21:58 UTC (permalink / raw) To: Pascal J. Bourguignon; +Cc: help-gnu-emacs On Mon, Dec 28, 2009 at 10:33 PM, Pascal J. Bourguignon <pjb@informatimago.com> wrote: > Lennart Borgman <lennart.borgman@gmail.com> writes: > >> On Mon, Dec 28, 2009 at 6:16 AM, Lennart Borgman >> <lennart.borgman@gmail.com> wrote: >>> I just got into some trouble because of a badly written macro I >>> believe. After the long discussions about defmacro here I wonder if >>> anyone wants to help me out. How should I write the defmacro below? >> >> >> I resorted to self education (which is not too bad). However I still >> got problems - just on a more complicated level. The macro now looks >> like this: >> >> (defmacro define-toggle (symbol value doc &rest args) >> "Declare SYMBOL as a customizable variable with a toggle function." >> (declare (doc-string 3) (debug t)) >> (let* ((SYMBOL-toggle (intern (concat (symbol-name symbol) "-toggle"))) >> (SYMBOL-name (symbol-name symbol)) >> (var-doc doc) >> (fun-doc (concat "Toggles the \(boolean) value of `" SYMBOL-name >> "'.\nFor how to set it permanently see this >> variable.\n"))) >> (let ((var (append `(defcustom ,symbol ,value ,var-doc) >> args >> nil)) >> (fun `(defun ,SYMBOL-toggle () >> ,fun-doc >> (interactive) >> (customize-set-variable (quote ,symbol) (not ,symbol))))) >> `(list 'progn ,var ,fun)))) >> >> This seems to work, but if the call to define-toggle already has been >> done then loading a file with this define-toggle gives trouble: >> >> Debugger entered--Lisp error: (void-variable rngalt-display-validation-header-toggle) >> (progn rngalt-display-validation-header rngalt-display-validation-header-toggle) >> (define-toggle rngalt-display-validation-header t "Display XML validation headers at the top of buffer when t.\nThe validation header is only displayed in buffers where the main\nmajor mode is derivd from `nxml-mode'." :set (lambda (sym val) (set-default sym val) (rngalt-update-validation-header-overlay-everywhere)) :group (quote relax-ng) :group (quote nxhtml)) >> >> ... >> >> There is obviously something I got wrong in the evaluation order since >> now, in this situation, the macro now tries to evaluate >> >> (progn rngalt-display-validation-header rngalt-display-validation-header-toggle) >> >> I expected it to redefine the defcustom and the defun instead. >> Can someone please try to explain what is going on? > > There must be an eval somewhere that tries to evaluate one time too many. Hm, yes, but it is not mine... As you can see from the backtrace there is some eval-buffer in the stack. > That said, why doesn't your macro just return > > `(progn ,var ,fun) > > instead of returning a list form that evaluates to something such as > > (progn rngalt-display-validation-header rngalt-display-validation-header-toggle) > > that needs to be evaluated (and of course fails since you didn't > define these symbols as variables)? It fails sometimes, but not always. It looks like it has something to do with those eval above, but I do not understand how. If I just do eval-buffer it works as I expect it to. I have done some small changes and at the moment it seems to work, but I have no idea why... There is clearly something in the order of evaluation that beats me. If I just print out the values of fun and var before comuting the result to return they look as I expect them to, ie they are lists. But then in the progn list they are converted to symbols, in some step. ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <mailman.358.1262037566.18930.help-gnu-emacs@gnu.org>]
* Re: Need some education on defmacro define-toggle [not found] ` <mailman.358.1262037566.18930.help-gnu-emacs@gnu.org> @ 2009-12-29 0:37 ` Pascal J. Bourguignon 2009-12-29 0:49 ` Lennart Borgman 0 siblings, 1 reply; 6+ messages in thread From: Pascal J. Bourguignon @ 2009-12-29 0:37 UTC (permalink / raw) To: help-gnu-emacs Lennart Borgman <lennart.borgman@gmail.com> writes: > On Mon, Dec 28, 2009 at 10:33 PM, Pascal J. Bourguignon > <pjb@informatimago.com> wrote: >> Lennart Borgman <lennart.borgman@gmail.com> writes: >> >>> On Mon, Dec 28, 2009 at 6:16 AM, Lennart Borgman >>> <lennart.borgman@gmail.com> wrote: >>>> I just got into some trouble because of a badly written macro I >>>> believe. After the long discussions about defmacro here I wonder if >>>> anyone wants to help me out. How should I write the defmacro below? >>> >>> >>> I resorted to self education (which is not too bad). However I still >>> got problems - just on a more complicated level. The macro now looks >>> like this: >>> >>> (defmacro define-toggle (symbol value doc &rest args) >>> "Declare SYMBOL as a customizable variable with a toggle function." >>> (declare (doc-string 3) (debug t)) >>> (let* ((SYMBOL-toggle (intern (concat (symbol-name symbol) "-toggle"))) >>> (SYMBOL-name (symbol-name symbol)) >>> (var-doc doc) >>> (fun-doc (concat "Toggles the \(boolean) value of `" SYMBOL-name >>> "'.\nFor how to set it permanently see this >>> variable.\n"))) >>> (let ((var (append `(defcustom ,symbol ,value ,var-doc) >>> args >>> nil)) >>> (fun `(defun ,SYMBOL-toggle () >>> ,fun-doc >>> (interactive) >>> (customize-set-variable (quote ,symbol) (not ,symbol))))) >>> `(list 'progn ,var ,fun)))) >>> >>> This seems to work, but if the call to define-toggle already has been >>> done then loading a file with this define-toggle gives trouble: >>> >>> Debugger entered--Lisp error: (void-variable rngalt-display-validation-header-toggle) >>> (progn rngalt-display-validation-header rngalt-display-validation-header-toggle) >>> (define-toggle rngalt-display-validation-header t "Display XML validation headers at the top of buffer when t.\nThe validation header is only displayed in buffers where the main\nmajor mode is derivd from `nxml-mode'." :set (lambda (sym val) (set-default sym val) (rngalt-update-validation-header-overlay-everywhere)) :group (quote relax-ng) :group (quote nxhtml)) >>> >>> ... >>> >>> There is obviously something I got wrong in the evaluation order since >>> now, in this situation, the macro now tries to evaluate >>> >>> (progn rngalt-display-validation-header rngalt-display-validation-header-toggle) >>> >>> I expected it to redefine the defcustom and the defun instead. >>> Can someone please try to explain what is going on? >> >> There must be an eval somewhere that tries to evaluate one time too many. > > > Hm, yes, but it is not mine... > > As you can see from the backtrace there is some eval-buffer in the stack. > > > >> That said, why doesn't your macro just return >> >> `(progn ,var ,fun) >> >> instead of returning a list form that evaluates to something such as >> >> (progn rngalt-display-validation-header rngalt-display-validation-header-toggle) >> >> that needs to be evaluated (and of course fails since you didn't >> define these symbols as variables)? > > > It fails sometimes, but not always. It looks like it has something to > do with those eval above, but I do not understand how. If I just do > eval-buffer it works as I expect it to. > > I have done some small changes and at the moment it seems to work, but > I have no idea why... There is clearly something in the order of > evaluation that beats me. If I just print out the values of fun and > var before comuting the result to return they look as I expect them > to, ie they are lists. But then in the progn list they are converted > to symbols, in some step. Of course, when you evaluate `(list 'progn ,defcustom-form ,defun-form) the defcustom and the defun are evaluated, and they return their name argument. That's why I advise you to write instead: `(progn ,defcustom-form ,defun-form) -- __Pascal Bourguignon__ http://www.informatimago.com/ ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Need some education on defmacro define-toggle 2009-12-29 0:37 ` Pascal J. Bourguignon @ 2009-12-29 0:49 ` Lennart Borgman 0 siblings, 0 replies; 6+ messages in thread From: Lennart Borgman @ 2009-12-29 0:49 UTC (permalink / raw) To: Pascal J. Bourguignon; +Cc: help-gnu-emacs On Tue, Dec 29, 2009 at 1:37 AM, Pascal J. Bourguignon <pjb@informatimago.com> wrote: > Lennart Borgman <lennart.borgman@gmail.com> writes: > >> On Mon, Dec 28, 2009 at 10:33 PM, Pascal J. Bourguignon >> <pjb@informatimago.com> wrote: >>> Lennart Borgman <lennart.borgman@gmail.com> writes: >>> >>>> On Mon, Dec 28, 2009 at 6:16 AM, Lennart Borgman >>>> <lennart.borgman@gmail.com> wrote: >>>>> I just got into some trouble because of a badly written macro I >>>>> believe. After the long discussions about defmacro here I wonder if >>>>> anyone wants to help me out. How should I write the defmacro below? >>>> >>>> >>>> I resorted to self education (which is not too bad). However I still >>>> got problems - just on a more complicated level. The macro now looks >>>> like this: >>>> >>>> (defmacro define-toggle (symbol value doc &rest args) >>>> "Declare SYMBOL as a customizable variable with a toggle function." >>>> (declare (doc-string 3) (debug t)) >>>> (let* ((SYMBOL-toggle (intern (concat (symbol-name symbol) "-toggle"))) >>>> (SYMBOL-name (symbol-name symbol)) >>>> (var-doc doc) >>>> (fun-doc (concat "Toggles the \(boolean) value of `" SYMBOL-name >>>> "'.\nFor how to set it permanently see this >>>> variable.\n"))) >>>> (let ((var (append `(defcustom ,symbol ,value ,var-doc) >>>> args >>>> nil)) >>>> (fun `(defun ,SYMBOL-toggle () >>>> ,fun-doc >>>> (interactive) >>>> (customize-set-variable (quote ,symbol) (not ,symbol))))) >>>> `(list 'progn ,var ,fun)))) >> >> >>> That said, why doesn't your macro just return >>> >>> `(progn ,var ,fun) >>> >>> instead of returning a list form that evaluates to something such as >>> >>> (progn rngalt-display-validation-header rngalt-display-validation-header-toggle) >>> >>> that needs to be evaluated (and of course fails since you didn't >>> define these symbols as variables)? >> >> >> It fails sometimes, but not always. It looks like it has something to >> do with those eval above, but I do not understand how. If I just do >> eval-buffer it works as I expect it to. > > Of course, when you evaluate `(list 'progn ,defcustom-form ,defun-form) > the defcustom and the defun are evaluated, and they return their name argument. Hm, in that case the defcustom and defun must have been evaluated earlier because they did exist. Now I have changed this so many times so I am not sure when. > That's why I advise you to write instead: > > `(progn ,defcustom-form ,defun-form) Thanks, yes, I understand that. I tried a lot of alternatives though to get evaluation at the right time. Surprisingly enough it sometimes worked with `(list 'prog ,var ,fun) and sometimes not. I did not dig deep in this, because I know there are other people here who understands this much better than me ... ;-) In the current implementation (which seems to work) I have this (let ((var (append `(defcustom ,symbol ,value ,var-doc) args nil)) (fun `(defun ,SYMBOL-toggle () ,fun-doc (interactive) (customize-set-variable (quote ,symbol) (not ,symbol))))) `(progn ,fun ,var) ))) Does that look correct? ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2009-12-29 0:49 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-12-28 5:16 Need some education on defmacro define-toggle Lennart Borgman 2009-12-28 19:28 ` Lennart Borgman [not found] ` <mailman.352.1262028532.18930.help-gnu-emacs@gnu.org> 2009-12-28 21:33 ` Pascal J. Bourguignon 2009-12-28 21:58 ` Lennart Borgman [not found] ` <mailman.358.1262037566.18930.help-gnu-emacs@gnu.org> 2009-12-29 0:37 ` Pascal J. Bourguignon 2009-12-29 0:49 ` Lennart Borgman
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).