In the mid-1990s, these functions were moved from Lisp to C to
"improve performance". However, Moore's Law, and perhaps other
improvements too, has made this rationale irrelevant.
On this machine, with --native-compilation=no, I observed only a
slight ~4% performance difference. For example, displaying a buffer
full of widgets (e.g., 'M-x customize RET browse-url RET') takes 4ms
here, meaning the performance gap is under 0.1ms. Even on less
powerful machines, this difference would remain imperceptible. Given
this, let's lift these functions back to to Lisp, which offers the
usual benefits.
We already have solid test coverage, but let's add a more focused test
for 'widget-get' and 'widget-put' to be thorough.
* lisp/wid-edit.el (widget-put, widget-get, widget-apply): Move to
Lisp from...
* src/fns.c (Fwidget_put, Fwidget_get, Fwidget_apply): ...here.
(syms_of_fns): Remove defsubrs for the above functions.
* test/lisp/wid-edit-tests.el
(widget-test-editable-field-widget-get/put): New test.
* lisp/wid-edit.el (widget-specify-inactive): When a widget is
already inactive, still move the overlay to the desired
positions. Improve docstring. (Bug#69941)
* doc/misc/widget.texi (default): Document the need to call the
:deactivate function when modifying an inactive widget.
* test/lisp/wid-edit-tests.el
(widget-test-modification-of-inactive-widget): New test
Recreating child widgets without recreating the parent widget
may lead to situations where the parent widget doesn't cover its
children or buttons entirely anymore. This bug manifests as a
faulty fontification of children or buttons, for example.
(Bug#69941)
* lisp/wid-edit.el (widget--prepare-markers-for-inside-insertion)
(widget--prepare-markers-for-outside-insertion): New functions.
(widget-default-create): Use them.
* test/lisp/wid-edit-tests.el (widget-test-insertion-at-parent-markers)
(widget-test-insertion-at-parent-markers-2): New tests.
* lisp/wid-edit.el (widget-specify-field): Store the end overlay
that we sometimes create for an editable-field widget.
(widget-field-value-delete): Make sure we delete all overlays
that belong to the widget. (Bug#75646)
* test/lisp/wid-edit-tests.el (widget-test-delete-field-overlays): New
test.
* lisp/wid-edit.el (widget-move): Avoid advancing point only if it
is at the start of a widget at BOB.
* test/lisp/wid-edit-tests.el (widget-test-widget-move-bug72995): New test.
* lisp/wid-edit.el (widget-move): Don't move backward when at
beginning of buffer, and keep point on widget's left side.
* test/lisp/wid-edit-tests.el (widget-test-widget-move): Test that
moving to a widget at beginning of buffer does not signal a
beginning-of-buffer error.
* lisp/wid-edit.el (restricted-sexp): Don't try to read
an empty string when converting the current value to the
external format. (Bug#63838)
* test/lisp/wid-edit-tests.el (widget-test-restricted-sexp-empty-val):
New test.
* lisp/wid-edit.el (widget-list-default-get)
(widget-alist-default-get): New functions.
(list, alist): Use it.
* test/lisp/cus-edit-tests.el (cus-edit-test-bug63290-option)
(cus-edit-test-bug63290-option-2): New test options.
(cus-edit-test-bug63290): New test.
* test/lisp/wid-edit-tests.el (widget-test-alist-default-value-1)
(widget-test-alist-default-value-2)
(widget-test-alist-default-value-3)
(widget-test-alist-default-value-4): New tests.
`pr-interface' specifies `inline' for its menu items, which is not
necessary, but it causes `widget-choice-value-create' to bug
out. (Bug#60501)
* lisp/wid-edit.el (widget-choice-value-create): Allow the value to be
a non-list.
* test/lisp/wid-edit-tests.el (widget-test-handle-spurious-inline):
Add test to ensure that unnecessary :inline is allowed.
* lisp/wid-edit.el (widget-move): Remove code that caused
widget-backward to skip an immediate previous widget when moving
backward from the start of a widget. (Bug#45623)
* test/lisp/wid-edit-tests.el (widget-test-widget-backward): New test.
A choice widget should be able to match either no inline values or
inline values, upon request. (Bug#44579)
* lisp/wid-edit.el (choice): New property, :inline-bubbles-p. A
predicate that returns non-nil if the choice widget can act as an
inline widget. Document it.
(widget-choice-inline-bubbles-p): New function, for the
:inline-bubbles-p property of the choice widget.
(widget-inline-p): New function. Use the :inline-bubbles-p property
of the widget, if any.
(widget-match-inline): Use the above to see if the widget can act like
an inline widget. Document it.
(widget-choice-value-create): Account for the case of a choice widget
that has inline members.
(widget-checklist-add-item, widget-editable-list-value-create)
(widget-group-value-create): Use widget-inline-p rather than just
checking for a non-nil :inline property, allowing these functions to
pass the complete information to widgets like the choice widget to
create their values.
* test/lisp/wid-edit-tests.el (widget-test-choice-match-no-inline)
(widget-test-choice-match-all-inline)
widget-test-choice-match-some-inline): New tests, to check that choice
widgets can match its choices, inline or not.
(widget-test-inline-p): New test, for the new function
widget-inline-p.
(widget-test-repeat-can-handle-choice)
(widget-test-repeat-can-handle-inlinable-choice)
(widget-test-list-can-handle-choice)
(widget-test-list-can-handle-inlinable-choice)
(widget-test-option-can-handle-choice)
(widget-test-option-can-handle-inlinable-choice): New tests. This
grouping widgets need to be able to create a choice widget regardless
if it has inline choices or not.
* etc/NEWS (Widget): Announce the feature (bug#6419).
* lisp/wid-edit.el (widget-editable-list-delete-at): Save into a new
widget property, :last-deleted, the WIDGET to be deleted. Add
docstring.
(widget-editable-list-insert-before): If there is a recently deleted
child for the editable list, insert that one, instead of a new default
widget. Add docstring.
(insert-button widget): Make :help-echo a function to avoid the
help-echo string become too long.
(delete-button widget): Tweak the :help-echo string, to document this
behavior.
* test/lisp/wid-edit-tests.el (widget-test-moving-editable-list-item):
Test the feature.
* lisp/wid-edit.el (widget-specify-field): Extend check for adding the
boundary overlay. Plus, a minor comment indentation fix.
(character widget): Tweak the valid-regexp to allow the newline
character.
* test/lisp/wid-edit-tests.el (widget-test-character-widget-value)
(widget-test-editable-field-widget-value): New tests (bug#15925).
* lisp/wid-edit.el (widget 'other): Use \n instead of the %n escape in the
:format property of this widget. If %n is used at the end of the
format string, unrelated widgets get indented. (Bug#12533)
* test/wid-edit-tests.el (widget-test-indentation-after-%n)
(widget-test-indentation-after-newline)
(widget-test-newline-and-indent-same-widget): New tests.
* lisp/button.el (button-at):
* lisp/wid-edit.el (widget-at): Avoid returning a false positive
when looking for a button and finding a widget, or vice versa.
* test/lisp/button-tests.el:
* test/lisp/wid-edit-tests.el: New files.