Support transient input methods in Isearch mode (bug#44266)

* doc/emacs/mule.texi (Select Input Method): Rename
transient-input-method to activate-transient-input-method.

* doc/emacs/search.texi (Special Isearch):
Document isearch-transient-input-method.

* lisp/international/isearch-x.el (isearch-transient-input-method):
New function.
(isearch-process-search-multibyte-characters):
Call 'deactivate-transient-input-method' after 'read-string'.

* lisp/international/mule-cmds.el (mule-menu-keymap): Remove
duplicate menu item 'describe-input-method'.  Add new menu item
'activate-transient-input-method'.
(default-transient-input-method): Rename from transient-input-method.
(current-transient-input-method)
(previous-transient-input-method): New buffer-local variables.
(deactivate-input-method): Don't add
current-transient-input-method to input-method-history.
(toggle-input-method): Call deactivate-transient-input-method
when current-transient-input-method is non-nil.
(activate-transient-input-method): Rename from transient-input-method.
(deactivate-transient-input-method): New function with body from
renamed function transient-input-method.

* lisp/isearch.el (isearch-menu-bar-map): Add new menu item
'isearch-transient-input-method'.
(isearch-mode-map): Bind 'C-x \' to isearch-transient-input-method.
(isearch-forward): Add isearch-transient-input-method to docstring.
(isearch-message-prefix): Use shorter string for narrowed buffer.
This commit is contained in:
Juri Linkov 2020-11-06 10:31:58 +02:00
parent 2180ccbe29
commit af6891629d
6 changed files with 90 additions and 44 deletions

View file

@ -581,7 +581,7 @@ Select a new input method for the current buffer (@code{set-input-method}).
@item C-x \ @var{method} @key{RET} @item C-x \ @var{method} @key{RET}
Temporarily enable the selected transient input method ; it will be Temporarily enable the selected transient input method ; it will be
automatically disabled after inserting a single character automatically disabled after inserting a single character
(@code{transient-input-method}). (@code{activate-transient-input-method}).
@item C-h I @var{method} @key{RET} @item C-h I @var{method} @key{RET}
@itemx C-h C-\ @var{method} @key{RET} @itemx C-h C-\ @var{method} @key{RET}
@ -680,13 +680,13 @@ character.
input methods. The list gives information about each input method, input methods. The list gives information about each input method,
including the string that stands for it in the mode line. including the string that stands for it in the mode line.
@findex transient-input-method @findex activate-transient-input-method
@kindex C-x \ @kindex C-x \
Sometimes it can be convenient to enable an input method Sometimes it can be convenient to enable an input method
@dfn{transiently}, for inserting only a single character. Typing @dfn{transiently}, for inserting only a single character. Typing
@kbd{C-x \} (@code{transient-input-method}) will temporarily enable an @kbd{C-x \} (@code{activate-transient-input-method}) will temporarily
input method, let you insert a single character using the input method enable an input method, let you insert a single character using the input
rules, and then automatically disable the input method. If no method rules, and then automatically disable the input method. If no
transient input method was selected yet, @kbd{C-x \} will prompt you transient input method was selected yet, @kbd{C-x \} will prompt you
for an input method; subsequent invocations of this command will for an input method; subsequent invocations of this command will
enable the selected transient input method. To select a different enable the selected transient input method. To select a different

View file

@ -419,6 +419,7 @@ character into the search string, similar to the usual
@kindex C-^ @r{(Incremental Search)} @kindex C-^ @r{(Incremental Search)}
@findex isearch-toggle-input-method @findex isearch-toggle-input-method
@findex isearch-toggle-specified-input-method @findex isearch-toggle-specified-input-method
@findex isearch-transient-input-method
Use an input method (@pxref{Input Methods}). If an input method is Use an input method (@pxref{Input Methods}). If an input method is
enabled in the current buffer when you start the search, the same enabled in the current buffer when you start the search, the same
method will be active in the minibuffer when you type the search method will be active in the minibuffer when you type the search
@ -437,7 +438,10 @@ I-search [@var{im}]:
@noindent @noindent
where @var{im} is the mnemonic of the active input method. Any input where @var{im} is the mnemonic of the active input method. Any input
method you enable during incremental search remains enabled in the method you enable during incremental search remains enabled in the
current buffer afterwards. current buffer afterwards. You can temporarily enable a transient
input method with @kbd{C-x \} (@code{isearch-transient-input-method})
to insert a single character to the search string and automatically
disable the input method afterwards.
@end itemize @end itemize
@kindex M-s o @r{(Incremental Search)} @kindex M-s o @r{(Incremental Search)}

View file

@ -652,6 +652,8 @@ transient input method (which can be different from the input method
enabled by 'C-\'). For example, 'C-u C-x \ compose RET' selects the enabled by 'C-\'). For example, 'C-u C-x \ compose RET' selects the
'compose' input method; then typing 'C-x \ 1 2' will insert the 'compose' input method; then typing 'C-x \ 1 2' will insert the
character '½', and disable the 'compose' input method afterwards. character '½', and disable the 'compose' input method afterwards.
You can use 'C-x \' in incremental search to insert a single character
to the search string.
--- ---
*** New input method 'compose' based on X Multi_key sequences. *** New input method 'compose' based on X Multi_key sequences.

View file

@ -51,6 +51,17 @@
(setq input-method-function nil) (setq input-method-function nil)
(isearch-update)) (isearch-update))
;;;###autoload
(defun isearch-transient-input-method ()
"Activate transient input method in interactive search."
(interactive)
(let ((overriding-terminal-local-map nil))
(activate-transient-input-method))
(setq isearch-input-method-function input-method-function
isearch-input-method-local-p t)
(setq input-method-function nil)
(isearch-update))
(defvar isearch-minibuffer-local-map (defvar isearch-minibuffer-local-map
(let ((map (copy-keymap minibuffer-local-map))) (let ((map (copy-keymap minibuffer-local-map)))
(define-key map [with-keyboard-coding] 'isearch-with-keyboard-coding) (define-key map [with-keyboard-coding] 'isearch-with-keyboard-coding)
@ -117,6 +128,7 @@
(cons last-char unread-command-events)) (cons last-char unread-command-events))
;; Inherit current-input-method in a minibuffer. ;; Inherit current-input-method in a minibuffer.
str (read-string prompt isearch-message 'junk-hist nil t)) str (read-string prompt isearch-message 'junk-hist nil t))
(deactivate-transient-input-method)
(if (or (not str) (< (length str) (length isearch-message))) (if (or (not str) (< (length str) (length isearch-message)))
;; All inputs were deleted while the input method ;; All inputs were deleted while the input method
;; was working. ;; was working.

View file

@ -55,7 +55,7 @@
;; Keep "C-x C-m ..." for mule specific commands. ;; Keep "C-x C-m ..." for mule specific commands.
(define-key ctl-x-map "\C-m" mule-keymap) (define-key ctl-x-map "\C-m" mule-keymap)
(define-key ctl-x-map "\\" 'transient-input-method) (define-key ctl-x-map "\\" 'activate-transient-input-method)
(defvar describe-language-environment-map (defvar describe-language-environment-map
(let ((map (make-sparse-keymap "Describe Language Environment"))) (let ((map (make-sparse-keymap "Describe Language Environment")))
@ -140,8 +140,8 @@
`(menu-item "Set Coding Systems" ,set-coding-system-map)) `(menu-item "Set Coding Systems" ,set-coding-system-map))
(bindings--define-key map [separator-input-method] menu-bar-separator) (bindings--define-key map [separator-input-method] menu-bar-separator)
(bindings--define-key map [describe-input-method] (bindings--define-key map [activate-transient-input-method]
'(menu-item "Describe Input Method" describe-input-method)) '(menu-item "Transient Input Method" activate-transient-input-method))
(bindings--define-key map [set-input-method] (bindings--define-key map [set-input-method]
'(menu-item "Select Input Method..." set-input-method)) '(menu-item "Select Input Method..." set-input-method))
(bindings--define-key map [toggle-input-method] (bindings--define-key map [toggle-input-method]
@ -1345,10 +1345,10 @@ This is the input method activated automatically by the command
mule-input-method-string) mule-input-method-string)
:set-after '(current-language-environment)) :set-after '(current-language-environment))
(defcustom transient-input-method nil (defcustom default-transient-input-method nil
"Default transient input method. "Default transient input method.
This is the input method activated by the command This is the input method activated by the command
`transient-input-method' (\\[transient-input-method])." `activate-transient-input-method' (\\[activate-transient-input-method])."
:link '(custom-manual "(emacs)Input Methods") :link '(custom-manual "(emacs)Input Methods")
:group 'mule :group 'mule
:type '(choice (const nil) :type '(choice (const nil)
@ -1356,6 +1356,18 @@ This is the input method activated by the command
:set-after '(current-language-environment) :set-after '(current-language-environment)
:version "28.1") :version "28.1")
(defvar current-transient-input-method nil
"The current input method temporarily enabled by `activate-transient-input-method'.
If nil, that means no transient input method is active now.")
(make-variable-buffer-local 'current-transient-input-method)
(put 'current-transient-input-method 'permanent-local t)
(defvar previous-transient-input-method nil
"The input method that was active before enabling the transient input method.
If nil, that means no previous input method was active.")
(make-variable-buffer-local 'previous-transient-input-method)
(put 'previous-transient-input-method 'permanent-local t)
(put 'input-method-function 'permanent-local t) (put 'input-method-function 'permanent-local t)
(defvar input-method-history nil (defvar input-method-history nil
@ -1490,7 +1502,8 @@ If INPUT-METHOD is nil, deactivate any current input method."
(defun deactivate-input-method () (defun deactivate-input-method ()
"Turn off the current input method." "Turn off the current input method."
(when current-input-method (when current-input-method
(add-to-history 'input-method-history current-input-method) (unless current-transient-input-method
(add-to-history 'input-method-history current-input-method))
(unwind-protect (unwind-protect
(progn (progn
(setq input-method-function nil (setq input-method-function nil
@ -1531,36 +1544,6 @@ To deactivate it programmatically, use `deactivate-input-method'."
(defvar toggle-input-method-active nil (defvar toggle-input-method-active nil
"Non-nil inside `toggle-input-method'.") "Non-nil inside `toggle-input-method'.")
(defun transient-input-method (&optional arg interactive)
"Enable a transient input method for the current buffer.
If `transient-input-method' was not yet defined, prompt for it."
(interactive "P\np")
(when (or arg (not transient-input-method))
(let* ((default (or (car input-method-history) default-input-method))
(input-method
(read-input-method-name
(if default "Transient input method (default %s): " "Transient input method: ")
default t)))
(setq transient-input-method input-method)
(when interactive
(customize-mark-as-set 'transient-input-method))))
(let* ((previous-input-method current-input-method)
(history input-method-history)
(clearfun (make-symbol "clear-transient-input-method"))
(exitfun
(lambda ()
(deactivate-input-method)
(when previous-input-method
(activate-input-method previous-input-method))
(setq input-method-history history)
(remove-hook 'input-method-after-insert-chunk-hook clearfun))))
(fset clearfun (lambda () (funcall exitfun)))
(add-hook 'input-method-after-insert-chunk-hook clearfun)
(when previous-input-method
(deactivate-input-method))
(activate-input-method transient-input-method)
exitfun))
(defun toggle-input-method (&optional arg interactive) (defun toggle-input-method (&optional arg interactive)
"Enable or disable multilingual text input method for the current buffer. "Enable or disable multilingual text input method for the current buffer.
Only one input method can be enabled at any time in a given buffer. Only one input method can be enabled at any time in a given buffer.
@ -1582,7 +1565,9 @@ which marks the variable `default-input-method' as set for Custom buffers."
(if toggle-input-method-active (if toggle-input-method-active
(error "Recursive use of `toggle-input-method'")) (error "Recursive use of `toggle-input-method'"))
(if (and current-input-method (not arg)) (if (and current-input-method (not arg))
(deactivate-input-method) (if current-transient-input-method
(deactivate-transient-input-method)
(deactivate-input-method))
(let ((toggle-input-method-active t) (let ((toggle-input-method-active t)
(default (or (car input-method-history) default-input-method))) (default (or (car input-method-history) default-input-method)))
(if (and arg default (equal current-input-method default) (if (and arg default (equal current-input-method default)
@ -1601,6 +1586,42 @@ which marks the variable `default-input-method' as set for Custom buffers."
(when interactive (when interactive
(customize-mark-as-set 'default-input-method))))))) (customize-mark-as-set 'default-input-method)))))))
(defun activate-transient-input-method (&optional arg interactive)
"Select and enable a transient input method for the current buffer.
If `default-transient-input-method' was not yet defined, prompt for it."
(interactive "P\np")
(when (or arg (not default-transient-input-method))
(let* ((default (or (car input-method-history) default-input-method))
(input-method
(read-input-method-name
(format-prompt "Transient input method" default)
default t)))
(setq default-transient-input-method input-method)
(when interactive
(customize-mark-as-set 'default-transient-input-method))))
(let* ((clearfun (make-symbol "clear-transient-input-method"))
(exitfun
(lambda ()
(deactivate-transient-input-method)
(remove-hook 'input-method-after-insert-chunk-hook clearfun))))
(fset clearfun (lambda () (funcall exitfun)))
(add-hook 'input-method-after-insert-chunk-hook clearfun)
(setq previous-transient-input-method current-input-method)
(when previous-transient-input-method
(deactivate-input-method))
(activate-input-method default-transient-input-method)
(setq current-transient-input-method default-transient-input-method)
exitfun))
(defun deactivate-transient-input-method ()
"Disable currently active transient input method for the current buffer."
(when current-transient-input-method
(deactivate-input-method)
(when previous-transient-input-method
(activate-input-method previous-transient-input-method)
(setq previous-transient-input-method nil))
(setq current-transient-input-method nil)))
(autoload 'help-buffer "help-mode") (autoload 'help-buffer "help-mode")
(defun describe-input-method (input-method) (defun describe-input-method (input-method)

View file

@ -565,6 +565,10 @@ This is like `describe-bindings', but displays only Isearch keys."
:help "Highlight all matches for current search string")) :help "Highlight all matches for current search string"))
(define-key map [isearch-search-replace-separator] (define-key map [isearch-search-replace-separator]
'(menu-item "--")) '(menu-item "--"))
(define-key map [isearch-transient-input-method]
'(menu-item "Turn on transient input method"
isearch-transient-input-method
:help "Turn on transient input method for search"))
(define-key map [isearch-toggle-specified-input-method] (define-key map [isearch-toggle-specified-input-method]
'(menu-item "Turn on specific input method" '(menu-item "Turn on specific input method"
isearch-toggle-specified-input-method isearch-toggle-specified-input-method
@ -747,6 +751,7 @@ This is like `describe-bindings', but displays only Isearch keys."
;; For searching multilingual text. ;; For searching multilingual text.
(define-key map "\C-\\" 'isearch-toggle-input-method) (define-key map "\C-\\" 'isearch-toggle-input-method)
(define-key map "\C-^" 'isearch-toggle-specified-input-method) (define-key map "\C-^" 'isearch-toggle-specified-input-method)
(define-key map "\C-x\\" 'isearch-transient-input-method)
;; People expect to be able to paste with the mouse. ;; People expect to be able to paste with the mouse.
(define-key map [mouse-2] #'isearch-mouse-2) (define-key map [mouse-2] #'isearch-mouse-2)
@ -1078,6 +1083,8 @@ To use a different input method for searching, type \
\\[isearch-toggle-specified-input-method], \\[isearch-toggle-specified-input-method],
and specify an input method you want to use. and specify an input method you want to use.
To activate a transient input method, type \\[isearch-transient-input-method].
The above keys, bound in `isearch-mode-map', are often controlled by The above keys, bound in `isearch-mode-map', are often controlled by
options; do \\[apropos] on search-.* to find them. options; do \\[apropos] on search-.* to find them.
Other control and meta characters terminate the search Other control and meta characters terminate the search
@ -3263,7 +3270,7 @@ the word mode."
"over") "over")
(if isearch-wrapped "wrapped ") (if isearch-wrapped "wrapped ")
(if (and (not isearch-success) (buffer-narrowed-p) widen-automatically) (if (and (not isearch-success) (buffer-narrowed-p) widen-automatically)
"narrowed-buffer " "") "narrowed " "")
(if (and (not isearch-success) (not isearch-case-fold-search)) (if (and (not isearch-success) (not isearch-case-fold-search))
"case-sensitive ") "case-sensitive ")
(let ((prefix "")) (let ((prefix ""))