From 4dab9d7d9ff2c5530d7c65a4695dd53b3e70f843 Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Tue, 21 Nov 2023 12:39:23 +0100 Subject: [PATCH v3] 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 | 15 +++------------ 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, 62 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..70a4899b623 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -986,9 +986,9 @@ 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}), and arranges for +@code{completion-at-point} to complete words based on the spelling +dictionary (@pxref{Completion in Buffers}). 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 +1382,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