From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Eshel Yaron Newsgroups: gmane.emacs.devel Subject: Re: Word completion in text modes Date: Sat, 25 Nov 2023 13:11:27 +0100 Message-ID: References: <83h6ljme0j.fsf@gnu.org> <83edgnmaqw.fsf@gnu.org> <837cmfm30o.fsf@gnu.org> <834jhina3v.fsf@gnu.org> <83leamcdzv.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="2372"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sat Nov 25 13:12:29 2023 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1r6rWO-0000PW-FN for ged-emacs-devel@m.gmane-mx.org; Sat, 25 Nov 2023 13:12:28 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1r6rVY-0006uk-FQ; Sat, 25 Nov 2023 07:11:36 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1r6rVX-0006ub-3Q for emacs-devel@gnu.org; Sat, 25 Nov 2023 07:11:35 -0500 Original-Received: from mail.eshelyaron.com ([107.175.124.16] helo=eshelyaron.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1r6rVT-0002wS-C0; Sat, 25 Nov 2023 07:11:34 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=eshelyaron.com; s=mail; t=1700914290; bh=zMlZUIDn4DGnGM1TWdsYinpmOn3kjV8XTQJhioRr/Ow=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=lS1O1rFKULJhQWWPKPNMKJm+JFNhFjNKC5SHB+D4wfszK6zvHOV7N8FUUu/DnSUNr 93fMPNDpPJWFXt5C9YcJOpfV6rxba94QDA91zwt5Dq3qpT8xAtVddSX8vysXrvLFip HJhdOlQZw+nUssuNC4oIuRDrf35e/FSKe1RJENcJxitjC1uVtbD+1EsHuEHbx0mO2P lSxq6tJKSC8nhHzjTto7M91phr2I0aPSgqyVK0AeOxzeNDtpOEYRVPtTe2hoPHW8kb ohDIk0/dS0DAkmmM+nrzTvo8ORlEuPrKjtTni2k0VvFsjZjBApN8ErYpVV5d7K9MH8 TP0voRp3xnMVA== In-Reply-To: <83leamcdzv.fsf@gnu.org> (Eli Zaretskii's message of "Sat, 25 Nov 2023 12:40:36 +0200") Received-SPF: pass client-ip=107.175.124.16; envelope-from=me@eshelyaron.com; helo=eshelyaron.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:313207 Archived-At: --=-=-= Content-Type: text/plain Eli Zaretskii writes: >> From: Eshel Yaron >> >> I'm attaching below a patch that facilitates using `completion-at-point` >> in Text mode instead of `ispell-complete-word` by default. Other than >> the somewhat awkward name of the user option that restores the binding, >> I'm pretty happy with this patch as it brings about the three benefits I >> outlined in my original message in this thread. WDYT? > > See some comments below. > >> diff --git a/doc/emacs/fixit.texi b/doc/emacs/fixit.texi >> index 78503d31a38..51814ab30e0 100644 >> --- a/doc/emacs/fixit.texi >> +++ b/doc/emacs/fixit.texi >> @@ -292,11 +292,6 @@ Spelling >> Restart the spell-checker process, using @var{dict} as the dictionary. >> @item M-x ispell-kill-ispell >> Kill the spell-checker subprocess. >> -@item M-@key{TAB} >> -@itemx @key{ESC} @key{TAB} >> -@itemx C-M-i >> -Complete the word before point based on the spelling dictionary >> -(@code{ispell-complete-word}). >> @item M-x flyspell-mode >> Enable Flyspell mode, which highlights all misspelled words. >> @item M-x flyspell-prog-mode >> >> ... > The removal of the command from the summary violates our conventions > in such sections: we first show a summary of the commands described by > the section, and then have their full description. So please don't > remove the command from the summary; instead, change the description > and the command name to follow the code changes. I see, done in the updated patch I'm attaching below. >> diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi >> index 8670807cbdf..ffd7ad7f51d 100644 >> --- a/doc/lispref/modes.texi >> +++ b/doc/lispref/modes.texi >> @@ -981,9 +981,7 @@ Basic Major Modes >> @deffn Command text-mode >> Text mode is a major mode for editing human languages. It defines the >> @samp{"} and @samp{\} characters as having punctuation syntax >> -(@pxref{Syntax Class Table}), and binds @kbd{M-@key{TAB}} to >> -@code{ispell-complete-word} (@pxref{Spelling,,, emacs, The GNU Emacs >> -Manual}). >> +(@pxref{Syntax Class Table}). > > Why remove the reference to the command binding here? Text mode no longer binds `C-M-i` to anything, relying on the global binding instead. So there doesn't seem to be any reason to mention this binding here anymore, just like it's not mentioned in the description of `prog-mode` that follows this paragraph. Does that make sense? >> +(defcustom text-mode-meta-tab-ispell-complete-word nil >> + "Whether M-TAB invokes `ispell-complete-word' in Text mode. >> + >> +This user option only takes effect when you customize it in >> +Custom or with `setopt', not with `setq'." >> + :group 'text >> + :type 'boolean >> + :set (lambda (sym val) >> + (if (set sym val) >> + (keymap-set text-mode-map "C-M-i" #'ispell-complete-word) >> + (keymap-unset text-mode-map "C-M-i" t)))) > > The :version tag is missing. Thanks, I've added it in the updated patch. > Did you check what happens when Flyspell mode is turned on in a buffer > under Text mode or one of its descendants? Yes. Unless one sets `flyspell-use-meta-tab` to nil, Flyspell mode binds `C-M-i` to a completely different command, `flyspell-auto-correct-word`. That is something that people are hopefully aware of when they opt-in to enabling of this minor mode, I suppose. Personally, I don't really like that behavior, so I unbind many of Flyspell's bindings. I'd be happy to see `flyspell-use-meta-tab` set to nil be default, but since Flyspell is opt-in, I consider it a bit of a different story compared to the Text mode binding. Patch v2 follows: --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=v2-0001-Unbind-C-M-i-in-Text-mode.patch >From 6fb2bf3476bd0f2323ad921aef0c91cb60d2bf2c Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Tue, 21 Nov 2023 12:39:23 +0100 Subject: [PATCH v2] Unbind 'C-M-i' in Text mode Remove the binding of 'C-M-i' to 'ispell-complete-word' in Text mode. Define a new 'ispell-completion-at-point' function and add that to 'completion-at-point-functions' in Text mode, such that 'completion-at-point' provides the same word completions as 'ispell-complete-word' does OOTB. * lisp/textmodes/ispell.el (ispell-completion-at-point): New function. * lisp/textmodes/text-mode.el (text-mode): Add it to 'c-a-p-functions'. (text-mode-map): Remove 'C-M-i' binding. (text-mode-meta-tab-ispell-complete-word): New user option. * etc/NEWS: Announce it. * doc/emacs/fixit.texi (Spelling) * doc/emacs/text.texi (Text Mode) * doc/lispref/modes.texi (Basic Major Modes) (Example Major Modes): Update. * lisp/mail/sendmail.el (mail-abbrevs-loaded) * lisp/nxml/nxml-mode.el (nxml-mode-map): Remove superfluous binding. --- doc/emacs/fixit.texi | 15 ++++++--------- doc/emacs/text.texi | 12 ++++++------ doc/lispref/modes.texi | 13 +------------ etc/NEWS | 9 +++++++++ lisp/mail/sendmail.el | 1 - lisp/nxml/nxml-mode.el | 1 - lisp/textmodes/ispell.el | 22 ++++++++++++++++++++++ lisp/textmodes/text-mode.el | 19 ++++++++++++++++--- 8 files changed, 60 insertions(+), 32 deletions(-) diff --git a/doc/emacs/fixit.texi b/doc/emacs/fixit.texi index 78503d31a38..e31df4865fc 100644 --- a/doc/emacs/fixit.texi +++ b/doc/emacs/fixit.texi @@ -295,8 +295,8 @@ Spelling @item M-@key{TAB} @itemx @key{ESC} @key{TAB} @itemx C-M-i -Complete the word before point based on the spelling dictionary -(@code{ispell-complete-word}). +Complete the word before point based on the spelling dictionary and +other completion sources (@code{completion-at-point}). @item M-x flyspell-mode Enable Flyspell mode, which highlights all misspelled words. @item M-x flyspell-prog-mode @@ -398,14 +398,11 @@ Spelling Show the list of options. @end table -@findex ispell-complete-word - In Text mode and related modes, @kbd{M-@key{TAB}} -(@code{ispell-complete-word}) performs in-buffer completion based on -spelling correction. Insert the beginning of a word, and then type -@kbd{M-@key{TAB}}; this shows a list of completions. (If your + Use the command @kbd{M-@key{TAB}} (@code{completion-at-point}) to +complete the word at point. Insert the beginning of a word, and then +type @kbd{M-@key{TAB}} to select from a list of completions. (If your window manager intercepts @kbd{M-@key{TAB}}, type @w{@kbd{@key{ESC} -@key{TAB}}} or @kbd{C-M-i}.) Each completion is listed with a digit or -character; type that digit or character to choose it. +@key{TAB}}} or @kbd{C-M-i}.) @cindex @code{ispell} program @findex ispell-kill-ispell diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi index 6f57bae8fef..b6a9dd6de53 100644 --- a/doc/emacs/text.texi +++ b/doc/emacs/text.texi @@ -943,12 +943,12 @@ Text Mode composition, for instance. @kindex M-TAB @r{(Text mode)} - Text mode binds @kbd{M-@key{TAB}} to @code{ispell-complete-word}. -This command performs completion of the partial word in the buffer -before point, using the spelling dictionary as the space of possible -words. @xref{Spelling}. If your window manager defines -@kbd{M-@key{TAB}} to switch windows, you can type @kbd{@key{ESC} -@key{TAB}} or @kbd{C-M-i} instead. + The command @kbd{M-@key{TAB}} (@code{completion-at-point}) performs +completion of the partial word in the buffer before point, using the +spelling dictionary as the space of possible words by default. +@xref{Spelling}. If your window manager defines @kbd{M-@key{TAB}} to +switch windows, you can type @kbd{@key{ESC} @key{TAB}} or @kbd{C-M-i} +instead. @vindex text-mode-hook Entering Text mode runs the mode hook @code{text-mode-hook} diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 13090a13d71..6cdedfa4592 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -986,9 +986,7 @@ Basic Major Modes @deffn Command text-mode Text mode is a major mode for editing human languages. It defines the @samp{"} and @samp{\} characters as having punctuation syntax -(@pxref{Syntax Class Table}), and binds @kbd{M-@key{TAB}} to -@code{ispell-complete-word} (@pxref{Spelling,,, emacs, The GNU Emacs -Manual}). +(@pxref{Syntax Class Table}). An example of a major mode derived from Text mode is HTML mode. @xref{HTML Mode,,SGML and HTML Modes, emacs, The GNU Emacs Manual}. @@ -1382,15 +1380,6 @@ Example Major Modes st) "Syntax table used while in `text-mode'.") @end group - -;; @r{Create the keymap for this mode.} -@group -(defvar-keymap text-mode-map - :doc "Keymap for `text-mode'. -Many other modes, such as `mail-mode' and `outline-mode', inherit all -the commands defined in this map." - "C-M-i" #'ispell-complete-word) -@end group @end smallexample Here is how the actual mode command is defined now: diff --git a/etc/NEWS b/etc/NEWS index 458e9e513de..fd633fad6fb 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1132,6 +1132,15 @@ showcases all their customization options. * Incompatible Lisp Changes in Emacs 30.1 ++++ +** 'M-TAB' now invokes 'completion-at-point' also in Text mode. +Text mode no longer binds 'M-TAB' to 'ispell-complete-word', and +instead this mode arranges for 'completion-at-point', globally bound +to 'M-TAB', to perform word completion as well. If you want 'M-TAB' +to invoke 'ispell-complete-word', as it did in previous Emacs +versions, customize the new option +'text-mode-meta-tab-ispell-complete-word' to non-nil. + ** 'pp' and 'pp-to-string' now always include a terminating newline. In the past they included a terminating newline in most cases but not all. diff --git a/lisp/mail/sendmail.el b/lisp/mail/sendmail.el index 8306bd3b30c..b5dd5322ec1 100644 --- a/lisp/mail/sendmail.el +++ b/lisp/mail/sendmail.el @@ -269,7 +269,6 @@ mail-citation-prefix-regexp (defvar mail-abbrevs-loaded nil) (defvar mail-mode-map (let ((map (make-sparse-keymap))) - (define-key map "\M-\t" 'completion-at-point) (define-key map "\C-c?" 'describe-mode) (define-key map "\C-c\C-f\C-t" 'mail-to) (define-key map "\C-c\C-f\C-b" 'mail-bcc) diff --git a/lisp/nxml/nxml-mode.el b/lisp/nxml/nxml-mode.el index 67d136b5a66..bc32598003e 100644 --- a/lisp/nxml/nxml-mode.el +++ b/lisp/nxml/nxml-mode.el @@ -390,7 +390,6 @@ nxml-mode-map "C-c C-u" #'nxml-insert-named-char "C-c C-o" nxml-outline-prefix-map "/" #'nxml-electric-slash - "M-TAB" #'completion-at-point "S-" #'nxml-mouse-hide-direct-text-content) (defvar nxml-font-lock-keywords diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el index b71e85b0e37..8fdf9a764aa 100644 --- a/lisp/textmodes/ispell.el +++ b/lisp/textmodes/ispell.el @@ -3680,6 +3680,28 @@ ispell-horiz-scroll (if (>= column (- (window-width) 2)) (scroll-left (max (- column (window-width) -3) 10))))))) +;;;###autoload +(defun ispell-completion-at-point () + "Word completion function for use in `completion-at-point-functions'." + (pcase (bounds-of-thing-at-point 'word) + (`(,beg . ,end) + (when (and (< beg (point)) (<= (point) end)) + (let* ((word (buffer-substring-no-properties beg end)) + (len (length word)) + (inhibit-message t) + (all (cons word (ispell-lookup-words word))) + (cur all)) + (while cur + (unless (string-prefix-p word (car cur)) + (setcar cur (concat word (substring (car cur) len)))) + (while (when-let ((next (cadr cur))) + (not (string-prefix-p word next t))) + (setcdr cur (cddr cur))) + (setq cur (cdr cur))) + (list beg end (cdr all) + :annotation-function (lambda (_) " Dictionary word") + :exclusive 'no)))))) + ;;; Interactive word completion. ;; Forces "previous-word" processing. Do we want to make this selectable? diff --git a/lisp/textmodes/text-mode.el b/lisp/textmodes/text-mode.el index ccba1b063ab..7f38a1c463d 100644 --- a/lisp/textmodes/text-mode.el +++ b/lisp/textmodes/text-mode.el @@ -73,8 +73,20 @@ text-mode-syntax-table (defvar-keymap text-mode-map :doc "Keymap for `text-mode'. Many other modes, such as `mail-mode' and `outline-mode', inherit -all the commands defined in this map." - "C-M-i" #'ispell-complete-word) +all the commands defined in this map.") + +(defcustom text-mode-meta-tab-ispell-complete-word nil + "Whether M-TAB invokes `ispell-complete-word' in Text mode. + +This user option only takes effect when you customize it in +Custom or with `setopt', not with `setq'." + :group 'text + :type 'boolean + :version "30.1" + :set (lambda (sym val) + (if (set sym val) + (keymap-set text-mode-map "C-M-i" #'ispell-complete-word) + (keymap-unset text-mode-map "C-M-i" t)))) (easy-menu-define text-mode-menu text-mode-map "Menu for `text-mode'." @@ -131,7 +143,8 @@ text-mode ;; Enable text conversion in this buffer. (setq-local text-conversion-style t) - (add-hook 'context-menu-functions 'text-mode-context-menu 10 t)) + (add-hook 'context-menu-functions 'text-mode-context-menu 10 t) + (add-hook 'completion-at-point-functions #'ispell-completion-at-point 10 t)) (define-derived-mode paragraph-indent-text-mode text-mode "Parindent" "Major mode for editing text, with leading spaces starting a paragraph. -- 2.42.0 --=-=-=--