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?

antonio
  • 1,762
  • 12
  • 24
  • Note, that the [`point` is the insertion positions **between** character positions](https://www.gnu.org/software/emacs/manual/html_node/emacs/Point.html). 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`](https://www.gnu.org/software/emacs/manual/html_node/emacs/Cursor-Display.html#Cursor-Display) to `bar`. Difficult to spot -- not the default. Your problem does not occur immediately before `text2` but immediately behind the widget field. – Tobias Mar 02 '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 02 '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 03 '18 at 02: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 03 '18 at 02:37
  • The only solution I could come up with is hacky: Do what they do when a field ends in a newline -- add a 'field` property with value `boundary` and the widget as value for `real-field` to the space: `(with-current-buffer (get-buffer-create "*test*") (setq wid (widget-create 'editable-field :size 4 :format "text1 %v")) (widget-create 'editable-field :size 0 :format (concat (propertize " " 'field 'boundary 'real-field wid) "text2")) (widget-setup))` – Tobias Mar 03 '18 at 03:08
  • @Tobias: For the record: `M-x customize`. Hit enter just before the search button (immediately behind the widget field) and you have again this nasty behaviour. Is it the way it should be or is it a bug? – antonio Mar 03 '18 at 19:24
  • 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`](https://www.gnu.org/software/emacs/manual/html_node/efaq/Reporting-bugs.html). – Tobias Mar 04 '18 at 22:05
  • @Tobias: BTW, I posted a more general workaround. Maybe you want to have a look and possibly spot something wrong. – antonio Mar 04 '18 at 23:29

1 Answers1

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.

antonio
  • 1,762
  • 12
  • 24
  • 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 04 '18 at 02:00
  • @phils: My Emacs is not configured to send emails and emails sent directly to bug-gnu-emacs@gnu.org do not show on gnu.emacs.bug newsgroup. In case your Emacs is enabled, I'll be glad if you could submit this post. – antonio Feb 19 '20 at 14:18