Sean Whitton <spwhit...@spwhitton.name> writes: > Hello, > > On Fri 06 Sep 2024 at 02:30pm +03, Eli Zaretskii wrote: > >> Thanks, but I see no reason to document this command in the manual, >> certainly not in the ELisp reference (it's a command, not a function). >> IMO it's obscure enough to be documented only in NEWS. > > That's quite fine with me. > >> Should this be "[:space:]\\n\\r" instead? if not, why not? >> >> Also note that [:space:] depends on mode-specific syntax table, so I >> question the wisdom of using it in a command that's supposed to be >> mode-agnostic. > > Both excellent points, thank you. I looked at the POSIX standard and > came up with a new default value. > >>> +This command is like `forward-word' except that words are always >>> +delimited by whitespace, regardless of the buffer's syntax table. >>> +Like `forward-word', this command respects fields. >>> + >>> +This emulates how C-w at the Unix terminal or shell identifies words. >>> +See the `unix-word-rubout' command in Info node `(readline)Commands For >>> +Killing'." >> >> This should try to be more explicit about what "word" means for this >> command. Since it's so different from any notion of "word" in Emacs, >> I would even seriously consider not to use that word, or maybe quote >> it (in addition to explaining what it means). > > This is very helpful. You're right. In the attached, I've tried using > "unix-word". Let me know what you think of that. > >> Also, since this is a command, its doc string should clearly separate >> what happens in interactive invocation from what happens when called >> from Lisp. DELIM belongs to the latter. (Is it even useful to >> provide that option for Lisp-only calls? what's the use case for >> that?) >> >> And finally, I wonder why we need this command? AFAIU, the original >> intent was to implement something similar to unix-word-rubout, not a >> new movement command. If the plan has changed, I think we need to >> discuss the need once again. > > I think it was unhelpful of me to send this in without callers. > I'm sorry about that. > > The reason for adding this is that it factors out what is in common > between what Philip is doing, and unix-word-rubout. > So in the attached revised patch, I've included unix-word-rubout.
Right, this is the command that we agreed on being necessary to appease both people who want C-w to kill the region when no transient region is active or to kill a word. > I've also included a second readline command which I have bound in my > own init. It demonstrates why there is a need for DELIM. > > By the way, forward-unix-word could also be a plain function. > I made it a command because, well, why not. Let me know if you think it > should be switched back to a function. > > -- > Sean Whitton > > From c047e640399bb923728ed9967e8545d53b22ea5c Mon Sep 17 00:00:00 2001 > From: Sean Whitton <spwhit...@spwhitton.name> > Date: Fri, 6 Sep 2024 11:35:46 +0100 > Subject: [PATCH] New commands for moving and killing unix-words > > * lisp/simple.el (forward-unix-word, unix-word-rubout) > (unix-filename-rubout): New commands. > * etc/NEWS: Document them. > --- > etc/NEWS | 7 +++++++ > lisp/simple.el | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 64 insertions(+) > > diff --git a/etc/NEWS b/etc/NEWS > index f3e719a34d3..54cf0a3df52 100644 > --- a/etc/NEWS > +++ b/etc/NEWS > @@ -123,6 +123,13 @@ When using 'visual-wrap-prefix-mode' in buffers with > variable-pitch > fonts, the wrapped text will now be lined up correctly so that it's > exactly below the text after the prefix on the first line. > > +--- > +** New commands for moving and killing unix-words. > +Unix-words are words separated by whitespace regardless of the buffer's > +syntax table. In a Unix terminal or shell, C-w kills by unix-word. > +The new commands 'forward-unix-word', 'unix-word-rubout' and > +'unix-filename-rubout' allow you to bind keys to operate more similarly > +to the terminal. > > * Changes in Specialized Modes and Packages in Emacs 31.1 > > diff --git a/lisp/simple.el b/lisp/simple.el > index 2453a129d0a..0322ac0cd8c 100644 > --- a/lisp/simple.el > +++ b/lisp/simple.el > @@ -8892,6 +8892,63 @@ current-word > ;; If we found something nonempty, return it as a string. > (unless (= start end) > (buffer-substring-no-properties start end))))) > + > +(defun forward-unix-word (arg &optional delim) > + "Move forward ARG unix-words. > +A unix-word is whitespace-delimited. > +Interactively, ARG is the numeric prefix argument, defaulting to 1. > +A negative ARG means go backwards to the beginning of unix-words. > + > +Unix-words differ from Emacs words in that they are always delimited by > +whitespace, regardless of the buffer's syntax table. This command > +emulates how C-w at the Unix terminal or shell identifies words. Should you mention the ^W notation here as well? > + > +When called from Lisp, DELIM specifies what characters are considered > +whitespace. It is a string as might be passed to `skip-chars-forward'. > +The default is \" \\f\\n\\r\\t\\v\". Do not prefix a `^' character." I think it would be worth checking for a ^ and then throwing a user-error. > + (interactive "^p") > + (unless (zerop arg) > + ;; We do skip over newlines by default because `backward-word' does. > + (let* ((delim (or delim " \f\n\r\t\v")) ^ I'd use "\s" here (and below). > + (ndelim (format "^%s" delim)) > + (start (point)) > + (fun (if (> arg 0) > + #'skip-chars-forward > + #'skip-chars-backward))) > + (dotimes (_ (abs arg)) > + (funcall fun delim) > + (funcall fun ndelim)) > + (constrain-to-field nil start)))) > + > +(defun unix-word-rubout (arg) > + "Kill ARG unix-words backwards. > +A unix-word is whitespace-delimited. > +Interactively, ARG is the numeric prefix argument, defaulting to 1. > +A negative ARG means to kill forwards. > + > +Unix-words differ from Emacs words in that they are always delimited by > +whitespace, regardless of the buffer's syntax table. Thus, this command > +emulates C-w at the Unix terminal or shell identifies words. > +See also this command's nakesake in Info node > +`(readline)Commands For Killing'." > + (interactive "^p") > + (let ((start (point))) > + (forward-unix-word (- arg)) > + (kill-region start (point)))) Won't there be an error here if the command is invoked with a negative argument? > + > +(defun unix-filename-rubout (arg) > + "Kill ARG unix-words backwards, also treating `/' as whitespace. > +A unix-word is whitespace-delimited. > +Interactively, ARG is the numeric prefix argument, defaulting to 1. > +A negative ARG means to kill forwards. > + > +This is like `unix-word-rubout' (which see), but `/' is also considered > +whitespace. See this command's namesake in Info node > +`(readline)Commands For Killing'." > + (interactive "^p") > + (let ((start (point))) > + (forward-unix-word (- arg) "/ \f\n\r\t\v") > + (kill-region start (point)))) > > (defcustom fill-prefix nil > "String for filling to insert at front of new line, or nil for none." -- Philip Kaludercic on siskin