mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2025-01-03 11:33:37 +00:00
Allow moving members of editable-list widget, via delete+insert
* 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.
This commit is contained in:
parent
954a4decfc
commit
c009a0a6f7
7
etc/NEWS
7
etc/NEWS
@ -1166,6 +1166,13 @@ window after starting). This variable defaults to nil.
|
||||
+++
|
||||
*** 'widget-choose' now supports menus in extended format.
|
||||
|
||||
---
|
||||
*** The 'editable-list' widget now supports moving items up and down.
|
||||
You can now move items up and down by deleting and then reinserting
|
||||
them, using the DEL and INS buttons respectively. This is useful in
|
||||
Custom buffers, for example, to change the order of the elements in a
|
||||
list.
|
||||
|
||||
** Miscellaneous
|
||||
|
||||
---
|
||||
|
@ -2721,7 +2721,10 @@ Return an alist of (TYPE MATCH)."
|
||||
(define-widget 'insert-button 'push-button
|
||||
"An insert button for the `editable-list' widget."
|
||||
:tag "INS"
|
||||
:help-echo "Insert a new item into the list at this position."
|
||||
:help-echo (lambda (widget)
|
||||
(if (widget-get (widget-get widget :parent) :last-deleted)
|
||||
"Insert back the last deleted item from this list, at this position."
|
||||
"Insert a new item into the list at this position."))
|
||||
:action 'widget-insert-button-action)
|
||||
|
||||
(defun widget-insert-button-action (widget &optional _event)
|
||||
@ -2734,7 +2737,7 @@ Return an alist of (TYPE MATCH)."
|
||||
(define-widget 'delete-button 'push-button
|
||||
"A delete button for the `editable-list' widget."
|
||||
:tag "DEL"
|
||||
:help-echo "Delete this item from the list."
|
||||
:help-echo "Delete this item from the list, saving it for later reinsertion."
|
||||
:action 'widget-delete-button-action)
|
||||
|
||||
(defun widget-delete-button-action (widget &optional _event)
|
||||
@ -2824,9 +2827,18 @@ Return an alist of (TYPE MATCH)."
|
||||
(cons found value)))
|
||||
|
||||
(defun widget-editable-list-insert-before (widget before)
|
||||
;; Insert a new child in the list of children.
|
||||
"Insert a new widget as a child of WIDGET.
|
||||
|
||||
If there is a recently deleted child, the new widget is that deleted child.
|
||||
Otherwise, the new widget is the default child of WIDGET.
|
||||
|
||||
The new widget gets inserted at the position of the BEFORE child."
|
||||
(save-excursion
|
||||
(let ((children (widget-get widget :children))
|
||||
(last-deleted (when-let ((lst (widget-get widget :last-deleted)))
|
||||
(prog1
|
||||
(pop lst)
|
||||
(widget-put widget :last-deleted lst))))
|
||||
(inhibit-read-only t)
|
||||
(inhibit-modification-hooks t))
|
||||
(cond (before
|
||||
@ -2834,7 +2846,11 @@ Return an alist of (TYPE MATCH)."
|
||||
(t
|
||||
(goto-char (widget-get widget :value-pos))))
|
||||
(let ((child (widget-editable-list-entry-create
|
||||
widget nil nil)))
|
||||
widget (and last-deleted
|
||||
(widget-apply last-deleted
|
||||
:value-to-external
|
||||
(widget-get last-deleted :value)))
|
||||
last-deleted)))
|
||||
(when (< (widget-get child :entry-from) (widget-get widget :from))
|
||||
(set-marker (widget-get widget :from)
|
||||
(widget-get child :entry-from)))
|
||||
@ -2847,6 +2863,15 @@ Return an alist of (TYPE MATCH)."
|
||||
(widget-apply widget :notify widget))
|
||||
|
||||
(defun widget-editable-list-delete-at (widget child)
|
||||
"Delete the widget CHILD from the known children of widget WIDGET.
|
||||
|
||||
Save CHILD into the :last-deleted list, so it can be inserted later."
|
||||
;; Save the current value of CHILD, to use if the user later inserts the
|
||||
;; widget.
|
||||
(widget-put child :value (widget-apply child :value-get))
|
||||
(let ((lst (widget-get widget :last-deleted)))
|
||||
(push child lst)
|
||||
(widget-put widget :last-deleted lst))
|
||||
;; Delete child from list of children.
|
||||
(save-excursion
|
||||
(let ((buttons (copy-sequence (widget-get widget :buttons)))
|
||||
|
@ -129,4 +129,23 @@
|
||||
(widget-insert "And some non-widget text.")
|
||||
(should (string= (widget-apply wid :value-get) "")))))
|
||||
|
||||
(ert-deftest widget-test-moving-editable-list-item ()
|
||||
"Check that we can move an editable list item up or down, via delete+insert."
|
||||
(with-temp-buffer
|
||||
(widget-insert "Testing editable-list.\n\n")
|
||||
(let ((lst (widget-create 'editable-list
|
||||
:value '("beg" "end" "middle")
|
||||
'(editable-field :value "unknown"))))
|
||||
(use-local-map widget-keymap)
|
||||
(widget-setup)
|
||||
;; Go to the DEL button for the 2nd element and action it.
|
||||
(goto-char (widget-get (nth 2 (widget-get lst :buttons)) :from))
|
||||
(widget-apply-action (widget-at))
|
||||
;; Go to the INS button and action it.
|
||||
(goto-char (widget-get lst :to))
|
||||
(widget-backward 1)
|
||||
(widget-apply-action (widget-at))
|
||||
;; Check that we effectively moved the item to the last position.
|
||||
(should (equal (widget-value lst) '("beg" "middle" "end"))))))
|
||||
|
||||
;;; wid-edit-tests.el ends here
|
||||
|
Loading…
Reference in New Issue
Block a user