all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Mauro Aranda <maurooaranda@gmail.com>
To: bovine@cyberscientist.ca
Cc: emacs-devel@gnu.org
Subject: Re: Community improvements to the Emacs Widget Library manual?
Date: Fri, 14 Jul 2023 21:08:25 -0300	[thread overview]
Message-ID: <09082742-1c5d-b8b6-49d8-dedcb5ee4347@gmail.com> (raw)
In-Reply-To: <8745efdbcf82ae2595a098fd09ba22d7@cyberscientist.ca>

bovine@cyberscientist.ca writes:

 > On 2023-07-14 10:41, Mauro Aranda wrote:
 >> Bryce Carson <bovine@cyberscientist.ca> writes:
 >>
 >>> Further, I can't seem to get these functions to work as documented or
 >>> expected.
 >>> Without these defined when I'm creating a widget with the following
 >>> code, I do get a button but the internal value is displayed in the
 >>> clickable
 >>> button. I'd like the external value to be displayed in the button
 >>> %v, just
 >>> as the menu-tag is is "externally facing".
 >>> <<widget>>=
 >>> (define-widget 'project-widget 'list
 >>>   :tag (let ((s "\n\tProject"))
 >>>          (put-text-property 0 (length s) 'face 'bold s) s)
 >>>   :format "%t\n%v "
 >>>   :offset 0
 >>>   :indent 0
 >>>   :convert-widget 'widget-types-convert-widget
 >>>   :args '((menu-choice
 >>>            :tag "EmacSQL-supported backend"
 >>>            :format "%[%t%]: %[%v%]"
 >>>            :value "sqlite"
 >>>            :value-to-external <<menu-choice internal value to
 >>> external lambda>>
 >>>            :value-to-internal <<menu-choice external value to
 >>> internal lambda>>
 >>>            (choice-item :menu-tag "MySQL" :value "mysql")
 >>>            (choice-item :menu-tag "PostgreSQL" :value "postgresql")
 >>>            (choice-item :menu-tag "SQLite" :value "sqlite"))))
 >>> <<menu-choice internal value to external lambda>>=
 >>> (lambda (widget internal-value)
 >>>   "Converts lowercase, internal values to the casing of trademarks."
 >>>   (pcase internal-value
 >>>     ("mysql" "MySQL")
 >>>     ("sqlite" "SQLite")
 >>>     ("postgresql" "PostgreSQL")))
 >>> <<menu-choice external value to internal lambda>>=
 >>> (lambda (widget external-value)
 >>>   "Converts the casing of trademarked names to lowercase, internal
 >>> values."
 >>>   (pcase external-value
 >>>     ("MySQL" "mysql")
 >>>     ("SQLite" "sqlite")
 >> When possible, please post code that can be evaled without making
 >> tweaks.
 >> Some things I noted:
 >> - Since the super is a list widget, then you don't need to specify
 >> :convert-widget.  The :convert-widget function is one of the few that
 >> gets called for all supers, so you end up converting twice the widget.
 >> In this case, it doesn't seem you want that.
 >> - You're specifying a value in the internal format for the
 >> menu-choice.
 >> The manual specifies that when creating a widget or defining a new
 >> one, the ‘:value’ should be in the external format.
 >> - I think you should give similar conversion functions to all
 >> choice-item, and also pass the :value in external format.
 >> Let me know if you still find problems after fixing these things.
 >
 > I fixed those issues and I do not see the invalid or void state, but
 > only nil is ever displayed in the buffer.
 > Below is the code I defined.

OK, I think you ran into something that's unsupported (maybe a bug, but
I'm not quite sure).

And thank you for providing the code, it made things easier for me to
see it.

 > (define-widget 'project-widget 'list
 >   "A mimimal example to demonstrate 'styled' choice item buttons in a
 >   choice menu."
 >   :tag (let ((s "\n\tProject"))
 >          (put-text-property 0 (length s) 'face 'bold s) s)
 >   :format "%t\n%v "
 >
 >   :args '((menu-choice
 >            :tag "EmacSQL-supported backend"
 >            :size 50
 >            :format "%[%t%]: %[%v%] \n"
 >
 >            :value "SQLite"
 >            :choice (database-choice-item :menu-tag "SQLite" :value
 >            "SQLite")
 >
 >            :value-to-external menu-choice-value-to-external
 >            :value-to-internal menu-choice-value-to-internal
 >
 >            (database-choice-item :menu-tag "MySQL" :value "MySQL")
 >            (database-choice-item :menu-tag "PostgreSQL" :value
 >            "PostgreSQL")
 >            (database-choice-item :menu-tag "SQLite" :value
 >            "SQLite"))))

The menu-choice creation assumes no difference between the internal
format and external format.  So for now, try removing the
:value-to-external and :value-to-internal.  I think it does that
because there's no big reason for converting a menu-choice value, since
the menu-choice will get its value from a valid choice, and the
individual choice is responsible for the conversion between formats.

Oh, and don't use :value and :choice at the same.  Just use :value to
give it a default value.  So this widget should be:

(define-widget 'project-widget 'list
   "A mimimal example to demonstrate 'styled' choice item buttons in a
   choice menu."
   :tag (let ((s "\n\tProject"))
          (put-text-property 0 (length s) 'face 'bold s) s)
   :format "%t\n%v "
   :args '((menu-choice
            :tag "EmacSQL-supported backend"
            :size 50
            :format "%[%t%]: %[%v%] \n"
        :value "MySQL"
            (database-choice-item :menu-tag "MySQL"      :value "MySQL")
            (database-choice-item :menu-tag "PostgreSQL" :value
            "PostgreSQL")
            (database-choice-item :menu-tag "SQLite"     :value
            "SQLite"))))

 > (define-widget 'database-choice-item 'choice-item
 >   nil
 >   :value-to-external #'menu-choice-value-to-external
 >   :value-to-internal #'menu-choice-value-to-internal)

And now, you need a :match function for this widget, so that when it
gets passed an external value, such as "MySQL", it returns non-nil.

So maybe something like this:
(define-widget 'database-choice-item 'choice-item
   nil
   :match (lambda (widget value)
        (equal (widget-get widget :value) (widget-apply widget
                                :value-to-internal
                                value)))
   :value-to-external #'menu-choice-value-to-external
   :value-to-internal #'menu-choice-value-to-internal)

You need a custom :match function because otherwise the
database-choice-item would resort to matching like an item, and that's
not good when you have different internal and external formats.
Basically, if you use different formats, you should consider providing a
:match function yourself.

I think with these fixes, your code will run just as you expect it.




  reply	other threads:[~2023-07-15  0:08 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-12 11:43 Community improvements to the Emacs Widget Library manual? Mauro Aranda
2023-07-12 20:17 ` Bryce
2023-07-14  6:32 ` Bryce Carson
2023-07-14  6:52   ` Bryce Carson
2023-07-14  6:56     ` Bryce Carson
2023-07-14  6:59       ` Bryce Carson
2023-07-14  7:07         ` Bryce Carson
2023-07-14 14:41     ` Mauro Aranda
2023-07-14 18:50       ` bovine
2023-07-15  0:08         ` Mauro Aranda [this message]
2023-07-14 10:48   ` Mauro Aranda
  -- strict thread matches above, loose matches on Subject: below --
2023-07-09 12:17 Mauro Aranda
2023-07-12  4:07 ` Bryce
2023-07-12 11:34   ` Mauro Aranda
2023-07-13  3:30     ` Michael Heerdegen
2023-07-23 23:06   ` Bryce
2023-07-24 11:37     ` Eli Zaretskii
2023-07-08 20:18 Bryce Carson
2023-07-09  5:26 ` Eli Zaretskii
2023-07-09 12:02   ` Mauro Aranda
2023-07-09 12:16     ` Eli Zaretskii
2023-07-11  0:52   ` Bryce
2023-07-12 12:30     ` Eli Zaretskii
2023-07-12 16:42       ` Corwin Brust
2023-07-13 23:05         ` Bryce Carson
2023-07-10  3:38 ` Michael Heerdegen
2023-07-11 23:17   ` Bryce
2023-07-12  5:18     ` Michael Heerdegen
2023-07-12  7:21       ` Bryce
2023-07-13  2:59         ` Michael Heerdegen
2023-07-11 11:04 ` Kjartan Oli Agustsson
2023-07-14  2:02   ` Richard Stallman
2023-07-14  5:28     ` Bryce Carson

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

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

  git send-email \
    --in-reply-to=09082742-1c5d-b8b6-49d8-dedcb5ee4347@gmail.com \
    --to=maurooaranda@gmail.com \
    --cc=bovine@cyberscientist.ca \
    --cc=emacs-devel@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 external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.