1

I have the following widget:

(widget-create 'editable-field :size 76 :format "Title: %v")

However, when I create this widget and edit its value, I can use C-j to insert new lines.

How can I restrict the widget to one line?

Runnable code:

(defun widget-example ()
  (interactive)
  (switch-to-buffer "*Widget Example*")
  (kill-all-local-variables)
  (let ((inhibit-read-only t))
    (erase-buffer))
  (remove-overlays)

  (widget-create 'editable-field :size 76 :format "Title: %v")

  (use-local-map widget-keymap)
  (widget-setup))
Sean Allred
  • 6,861
  • 16
  • 85

1 Answers1

1

I recommend using the :validate option (works on any widget type) or the :valid-regexp option (for the editable-field widget only) to reject inputs that you don't like. See section 5.5 of the Widget Library manual.

Note, however, that validation doesn't appear to happen automatically. It appears to be the case that you must explicitly use (widget-apply widget :validate) on all of your widgets at some point. The documentation doesn't seem to state this anywhere, but I suppose it makes sense; the widget library doesn't need to make many assumptions about what you're going to do with the values the user enters, leaving that up to your own code. Since mostly the widgets are used by the customization system, it just looks like this is automatic. The group widget will automatically validate its children when validated; using one could simplify your code.

There are, of course, a few other options. The most promising is to simply remove newlines from the value when you process the form. This is not much extra work for you, and saves the user from the cognitive overhead of remembering not to enter newlines, or of following extra directions on some fields, or of having to go back and fix up the value when they get an error. The more I consider it, the more I like this option in this case.

Another possibility, if you're really dead-set on not letting the user enter a newline at all, is to modify the keymap used while editing the value. All widgets take a :keymap argument, and editable-field widgets have a special keymap that remaps <RET>. You could extend that keymap to also remap C-j. Note however that the user could also use C-q C-j to enter a newline, and that you don't want to completely prevent them from using C-q; it's far too useful. This is probably more work than it's worth.

db48x
  • 15,741
  • 1
  • 19
  • 23
  • `:valid-regexp (rx (not (any "\n")))` does not seem to stop me from inserting the newline. – Sean Allred Feb 21 '17 at 04:00
  • 1
    No, but it will let you show an error message; see the `:error` option. Also, it's good to see people using the rx library over raw regexes. :) – db48x Feb 21 '17 at 04:06
  • 1
    Although it just occurred to me that your regex isn't right; it only matches a single non-newline character. Try this: `(rx (and string-start (zero-or-more (not (any ?\n))) string-end))` – db48x Feb 21 '17 at 04:19
  • Alright, but when is this error supposed to show up? I'm still able to insert newlines. – Sean Allred Feb 21 '17 at 12:54
  • I was under the impression that this happened automatically whenever you saved the form, but I double checked and I guess it doesn't. If you look in cus-edit.el, line 2880, you'll see that the customize system specifically validates all widgets and calls `error` when it finds one that fails. You'll probably have to do something similar. I do note that the default validation function for `editable-field` widgets calls `error` for you, so simply calling the `:validate` function will be enough (Unless, and this seems likely, you use multiple types of widgets.) – db48x Feb 21 '17 at 23:16