2

Using this widget:

(widget-create 'editable-field :size 4 :format "text1 %v text2")
(widget-setup)

I get the following output (where the underscores appear as a fillable grey area)

text1 ____ text2

In general, when hitting Enter inside an editable field area, the effect is a jump to the next field. (widget-setup) sets the buffer read-only, therefore outside the editable area, hitting Enter gives widget-before-change: Text is read-only: "Attempt to change text outside editable field".

However, if I place the cursor immediately before text2, hitting Enter inserts an undesired newline, while that should be a read-only area.

Why is a newline added despite that is a read-only area?
How can I prevent the newline insertion?

  • Note, that the point is the insertion positions between character positions. The rectangular cursor is a bit misleading in that regard. The relevant part of the cursor is its left edge which is actually better represented by the vertical bar you get when you customize cursor-type to bar. Difficult to spot -- not the default. Your problem does not occur immediately before text2 but immediately behind the widget field. – Tobias Mar 2 '18 at 23:41
  • Note that you can insert a linebreak anywhere in the widget field -- not by RET but by C-q C-j (which corresponds more or less to a literal RET). RET does not insert a linebreak in the widget field since it is bound to widget-field-activate in the widget-field-keymap which is active in the widget field. – Tobias Mar 2 '18 at 23:53
  • @Drew Those are really comments. The answer is quite more complicated. Widgets have their own treatment of overlays. See widget-before-change, widget-after-change, and the comment about not subtracting 1 if local-map is working at the end of the overlay in widget-field-end. – Tobias Mar 3 '18 at 2:27
  • @Drew I dug that deep when I got puzzled about the active keymap at the insertion end of the overlay which is one more than the last character position in the overlay. The overlay keymap shouldn't be active there but it magically is. – Tobias Mar 3 '18 at 2:37
  • 1
    You asked whether the behavior is a bug. I am not in the position to decide that. Just try and report it as an emacs bug to find out: M-x report-emacs-bug. – Tobias Mar 4 '18 at 22:05
2

Analysis of the problem

Looking at wid-edit.el, the only call to widget-field-activate happens inside widget-field-keymap:

(defvar widget-field-keymap
  (let ((map (copy-keymap widget-keymap)))
    ...
    (define-key map "\C-m" 'widget-field-activate)
    ...

I cannot find the function used elsewhere, therefore the widget-field-activate action can only be triggered when widget-field-keymap is active and when Enter is pressed. Since this keymap is associated to editable fields, it means one should be inside a field and hit Enter.

There is however a "dead" spot on the right field boundary where an anomalous behaviour happens:

  1. Pressing Enter triggers widget-field-activate, which would imply you are inside the field.
  2. However, using a Edebug, shows that this point is outside a field. In fact,

    (get-char-property (point) 'field)
    

    returns nil, rather than the field properties.

The function widget-field-keymap controls for this and: if Enter is pressed inside the field, activates the field; if Enter is pressed outside, executes the standard widget-global-map binding for RET, which is (newline):

(defun widget-field-activate (pos &optional event)
  "Invoke the editable field at point."
  (interactive "@d")
  (let ((field (widget-field-at pos)))    ; <- the func checks if we are in a field
    (if field
    (widget-apply-action field event)
      (call-interactively                 ; <- if not, lookup-key returns newline 
       (lookup-key widget-global-map (this-command-keys))))))

Calling the newline causes the bizarre result of visually breaking the field, spanning it over two lines. Instead, the function should do nothing if the activation cannot proceed or perhaps return the usual read-only warning. Hence, the following

General workaround

(defun widget-field-activate (pos &optional event)
(interactive "@d")
  (let ((field (widget-field-at pos)))
    (if field
    (widget-apply-action field event)
      (message "Text is read-only: \"Attempt to change text outside editable field\""))))

I don't know if this version fixes a bug, but I haven't found any side effect and that produces a more desirable behaviour.

  • I can't find any bug report mentioning widget-field-activate. As per the comments, this should be reported with M-x report-emacs-bug for discussion -- especially if you believe you may have a patch which fixes it. – phils May 4 '18 at 2:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.