laishulu / emacs-smart-input-source

Less manual switch for native or OS input source (input method).
GNU General Public License v3.0
254 stars 16 forks source link
emacs evil fcitx input-method linux macos windows

+TITLE: README

[[https://melpa.org/#/sis][file:https://melpa.org/packages/sis-badge.svg]]

[[./README.zh.org][中文版]]

** MacOS The default MacOS input sources are shown in the following.

+BEGIN_SRC lisp

;; Not needed if your input sources are the same with the default values (sis-ism-lazyman-config "com.apple.keylayout.US" "com.sogou.inputmethod.sogou.pinyin")

+END_SRC

Note:

  1. Your English input source MAY NOT be the default one. Use command ~sis-get~ in Emacs to get the correct one.
  2. According to your use case, ~EMP~ or ~macism~ should be installed.

*** GUI Emacs Mac Port (EMP) EMP is a Emacs distribution enhanced for MacOS. It has builtin native API to interact with MacOS input sources efficiently. EMP can be installed by the following commands:

+BEGIN_SRC bash

brew tap railwaycat/emacsmacport brew install emacs-mac --with-modules --with-rsvg --with-imagemagick --with-natural-title-bar

+END_SRC

*** ~macism~ If your Emacs is not GUI EMP, the pre-configured ~macism~ should be installed.

+BEGIN_SRC bash

brew tap laishulu/macism brew install macism

+END_SRC

Note:

** Microsoft Windows *** ~w32~ ~Emacs 28+~ in Windows provide APIs to switch imput method directly without emploring external tools. ~sis~ has builtin support for those APIs under the ISM type of ~w32~, which is auto detected and configured. So the follow codes are not required actually.

+BEGIN_SRC lisp

; (sis-ism-lazyman-config nil t 'w32)

+END_SRC

*** ~im-select~ [[https://github.com/daipeihust/im-select][im-select]] can be used as a drop-in replacement of ~macism~ in Microsoft Windows.

+BEGIN_SRC lisp

(sis-ism-lazyman-config "1033" "2052" 'im-select)

+END_SRC

  1. Even though ~im-select~ supports switching different input languages, it does not support multiple input methods in the same lanuage, thus you should ensure that in each input language there is only one input method, just like the following screenshot.

    +CAPTION: Smart input source

    [[./screenshots/windows-im-select.jpg]]

  2. If you are using ~win~ key as ~super~ key, you may also need [[https://github.com/laishulu/winsuper][winsuper]].

** Linux *** ~fcitx~

+BEGIN_SRC lisp

(sis-ism-lazyman-config "1" "2" 'fcitx)

+END_SRC

*** ~fcitx5~

+BEGIN_SRC lisp

(sis-ism-lazyman-config "1" "2" 'fcitx5)

+END_SRC

*** ~ibus~

+BEGIN_SRC lisp

(sis-ism-lazyman-config "xkb:us::eng" "OTHER_INPUT_SOURCE" 'ibus)

+END_SRC

** Internals for configuring ISM The core of the configuring of ISM is the two variables :

+BEGIN_SRC lisp

(setq sis-do-get

'YOUR_DO_GET_INPUT_SOURCE_FUNCTION)

(setq sis-do-set

'YOUR_DO_SET_INPUT_SOURCE_FUNCTION)

+END_SRC

They are provided for ~EMP~ and ~macism~ by default.

If you have a ISM ~YOUR_ISM~:

Then you can simply use ~YOUR_ISM~ as a drop in replacement for ~macism~:

+BEGIN_SRC lisp

(setq sis-external-ism "YOUR_ISM")

+END_SRC

You can configure ISM by yourself, but a convenient command ~sis-ism-lazyman-config~ is also provided for common ISMs.

+BEGIN_SRC lisp

(use-package sis ;; :hook ;; enable the /context/ and /inline region/ mode for specific buffers ;; (((text-mode prog-mode) . sis-context-mode) ;; ((text-mode prog-mode) . sis-inline-mode))

:config ;; For MacOS (sis-ism-lazyman-config

;; English input source may be: "ABC", "US" or another one. ;; "com.apple.keylayout.ABC" "com.apple.keylayout.US"

;; Other language input source: "rime", "sogou" or another one. ;; "im.rime.inputmethod.Squirrel.Rime" "com.sogou.inputmethod.sogou.pinyin")

;; enable the /cursor color/ mode (sis-global-cursor-color-mode t) ;; enable the /respect/ mode (sis-global-respect-mode t) ;; enable the /context/ mode for all buffers (sis-global-context-mode t) ;; enable the /inline english/ mode for all buffers (sis-global-inline-mode t) )

+END_SRC

Tips:

  1. For ~spacemacs~, if it works in the ~hybrid~ mode, some of the ~evil~ related features may not work. Change to ~vim~ mode instead.
  2. Make sure your ISM is availabe (in your ~$PATH~) before call ~sis~ command.

** About /inline english mode/

For example final result ~中文 some english text 中文~, just input ~中文some english text中文~, and no need to switch ISM manually.

Note:

| Command Name | Description | |--------------------------+------------------------------------------------------------| | ~sis-ism-lazyman-config~ | Configure input source manager | | ~sis-get~ | Get the input source | | ~sis-set-english~ | Set the input source to English | | ~sis-set-other~ | Set the input source to other language | | ~sis-switch~ | Switch the input source between English and other language | |--------------------------+------------------------------------------------------------|

** About /cursor color mode/ | Variable | Description | Default | |----------------------------+---------------------------------------------+--------------------------| | ~sis-default-cursor-color~ | Default cursor color, also used for English | ~nil~ (from envrionment) | | ~sis-other-cursor-color~ | Cursor color for other input source | ~green~ | |----------------------------+---------------------------------------------+--------------------------|

** About /respect mode/ | Variable | Description | Default | |-------------------------------------------------+--------------------------------------------------------+------------------------| | ~sis-respect-start~ | Switch to specific input source when mode enabled | ~'english~ | | ~sis-respect-evil-normal-escape~ | esc to English even in evil normal state | ~t~ | | ~sis-respect-prefix-and-buffer~ | Handle prefix key and buffer | ~t~ | | ~sis-respect-go-english-triggers~ | Additional trigger to save input source and go English | ~t~ | | ~sis-respect-restore-triggers~ | Additional trigger to restore input source | ~nil~ | | ~sis-respect-minibuffer-triggers~ | Commands trigger to set input source in minibuffer | see variable doc | | ~sis-prefix-override-keys~ | Prefix keys to be respected | ~'("C-c" "C-x" "C-h")~ | | ~sis-prefix-override-recap-triggers~ | Functions trigger the recap of the prefix override | see variable doc | | ~sis-prefix-override-buffer-disable-predicates~ | Predicates on buffers to disable prefix overriding | see variable doc | |-------------------------------------------------+--------------------------------------------------------+------------------------|

** About language pattern | Variable | Description | Default | |-----------------------+--------------------------------------------+--------------------------| | ~sis-english-pattern~ | Pattern to identify a character as English | ~[a-zA-Z]~ | | ~sis-other-pattern~ | Pattern to identify a character as other | ~\cc~ , see [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Regexp-Backslash.html][emacs manual]] | | ~sis-blank-pattern~ | Pattern to identify a character as blank | ~[:blank:]~ | |-----------------------+--------------------------------------------+--------------------------|

** About /context mode/ | Variable | Description | Default | |-------------------------------+------------------------------------------------+------------------| | ~sis-context-detectors~ | Detectors to detect the context | see variable doc | | ~sis-context-fixed~ | Context is fixed to a specific language | ~nil~ | | ~sis-context-aggressive-line~ | Aggressively detect context across blank lines | ~t~ | | ~sis-context-hooks~ | Hooks trigger the context following | see variable doc | | ~sis-context-triggers~ | Commands trigger the context following | see variable doc | |-------------------------------+------------------------------------------------+------------------|

** About /inline mode/

| Face Name | Description | Default | |---------------------------------------+------------------------------------------------------------+---------| | ~sis-inline-face~ | Face for the inline region overlay | | | ~sis-inline-not-max-point~ | Insert new line when the whole buffer ends with the region | ~t~ | | ~sis-inline-tighten-head-rule~ | Rule to delete the head spaces | ~'one~ | | ~sis-inline-tighten-tail-rule~ | Rule to delete the tail spaces | ~'one~ | | ~sis-inline-single-space-close~ | 1 space to close the region, default is 2 spaces/return | ~nil~ | | ~sis-inline-with-english~ | enable the ~inline english~ region feature | ~t~ | | ~sis-inline-with-other~ | enable the ~inline other language~ region feature | ~nil~ | | ~sis-inline-english-activated-hook~ | Hook to run after inline english region activated | ~nil~ | | ~sis-inline-english-deactivated-hook~ | Hook to run after inline english region deactivated | ~nil~ | | ~sis-inline-other-activated-hook~ | Hook to run after inline other language region activated | ~nil~ | | ~sis-inline-other-deactivated-hook~ | Hook to run after inline other language region deactivated | ~nil~ | |---------------------------------------+------------------------------------------------------------+---------|

** Inform the package of the input source change

  1. If your input source is switched from ~sis~, then everything should be OK naturally. And your ~sis-auto-refresh-seconds~ can even be set to ~nil~.
  2. If your input source is switched from OS, to detect the switch timely, ~sis-auto-refresh-seconds~ should not be too large.
  3. To save energy, if the input source is switched from OS during a long idle period of Emacs, the package won't be aware in time. Then you can manually inform the package by doing anything in Emacs to exit the long idle period, or invoke the command ~sis-get~ directly.

** Auto set /other/ input source for /org capture/ buffer

+begin_src elisp

(add-hook 'org-capture-mode-hook #'sis-set-other)

+end_src

** Customize my own context detector Customize ~sis-context-detectors~ like the following codes:

+begin_src elisp

(add-to-list 'sis-context-detectors (lambda (&rest _) 'other))

+end_src

** Auto set input source in /minibuffer/ of a specific command. Customize ~sis-respect-minibuffer-triggers~.

Here is an example to automatically switch to /other/ input resource in /minibuffer/ of command:

+begin_src elisp

(add-to-list 'sis-respect-minibuffer-triggers (cons 'org-roam-node-find (lambda () 'other)))

+end_src