This package provide several modes to switch OS-native or Emacs-native input source smartly:
- A global mode:
smart-input-source-global-respect-mode
to respect buffer/mode by proper input source- Respect start: start Emacs with specified language.
- Respect
evil
: switch to English when leavingevil
insert
mode. - Respect
minibuffer
: switch to English when enterminibuffer
. - Respect prefix key: switch to English for
C-c
/C-x
/C-h
and more. - Respect buffer: recover buffer input source when it regain focus.
- A buffer local mode:
smart-input-source-follow-context-mode
to switch input source smarted according to context. It also has a global versionsmart-input-source-global-follow-context-mode
to enable the mode for all buffers. When to switch input source by following context can be configured easily by a variable, whose default value indicates when entering evil insert mode. - A buffer local mode:
smart-input-source-inline-mode
to enable the automatically triggering of a temporary overlay to input English/other language and then back to original input source without switching input sources manually. It also has a global versionsmart-input-source-global-inline-mode
to enable the mode for all buffers. - A global mode:
smart-input-source-global-cursor-color-mode
to automatically change cursor color according to current input source.
- Ease the use of OS-native input source, no need to change use experience.
- Ease the use of Emacs-native input source, for further compatibility.
- Support GUI Emacs, as well as Terminal Emacs.
- Easy to install and configure. No further configuration for
GUI Emacs Mac Port
withSogou Input
. - Automatically change cursor color according to current input source.
- Respect buffer/mode by proper input source:
- Respect start: start Emacs with specified language.
- Respect
evil
: switch to English when leavingevil
insert
mode. - Respect
minibuffer
: switch to English when enterminibuffer
. - Respect prefix key: switch to English for
C-c
/C-x
/C-h
and more. - Respect buffer: recover buffer input source when it regain focus.
- Support
inline English
andinline other language
region. Features of the inline region (inline english
as an example):- Inserting space around none-English characters triggers the region (two
consecutive spaces for
inline other language
region). - In this mode, English will be sticked.
- Region is closed when:
a. Cursor leaves the region
b.
Return
is pressed. c. Two consecutivespace
are input (can be configured to onespace
). - If the region ends with space, none-English input source will be selected, otherwise English input source is retained.
- After the close of the region, one space (can be configured) in the head and tail respectively (if exists) of the region will be deleted. But if the whole region is blank, the no character will be deleted.
- Inserting space around none-English characters triggers the region (two
consecutive spaces for
- Switch input source according to context:
- Pre-configured for entering evil insert mode.
- For native emacs user, you can configure by easily set a variable.
- Input source switching rules are designed carefully, for pure English editing, input source will never be switched to other languages.
Just install smart-input-source
from melpa
.
Here uses rime
as an example:
(smart-input-source-ism-lazyman-config nil "rime" 'emacs)
The default MacOS input sources are shown in the following.
;; Not needed if your input sources are the same with the default values
(smart-input-source-ism-lazyman-config
"com.apple.keylayout.US"
"com.sogou.inputmethod.sogou.pinyin")
Note:
- Your English input source MAY NOT be the default one. Use command
smart-input-source-get
in Emacs to get the correct one. - According to your use case,
EMP
ormacism
should be installed.
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:
brew tap railwaycat/emacsmacport
brew install emacs-mac --with-modules --with-rsvg --with-imagemagick --with-natural-title-bar
If your Emacs is not GUI EMP, the pre-configured macism
should be installed.
brew tap laishulu/macism
brew install macism
Note:
- The first time when you use
macism SOME_INPUT_SOURCE_ID
in your app, MacOS will popup a window asking you to grant permission of Accessibility, you can also grant the permission manually following the instructions in macism. - On a slow computer,
macism
needs sleep time (in micro seconds) longer than default to work with Accessibility. The default can be overwritten by the following codes.(setq smart-input-source-do-set (lambda(source) (start-process "set-input-source" nil "macism" source "50000")))
- Don’t use
Alacritty
for TUI Emacs, because it can’t handle deleting as well asOption
andCommand
key properly when input method is on. I just recommendkitty
untilAlacirtty
fixed those long existing bugs. - If you have problems on granting permission of Accessibility for Emacs, see
below:
Some Emacs “distributions” package together a number of Emacs binaries for various macOS versions in a single folder, and dynamically at runtime chooses the right one for your system. This means that the icon you click to start the program is really a “placeholder” that is not Emacs itself, but rather just starts up Emacs. This “placeholder” often takes the form of a Ruby script. If this is the case, you’ll need to drag the Ruby program on to the list. Ruby comes with macOS by default. You can find the program by opening Finder, and then from the “Go” menu choose “Go to Folder”. Enter “/usr/bin” and you’ll get that folder opened in Finder. In the folder, you’ll find the ruby program that you can drag on to the Accessibility list.
im-select can be used as a drop-in replacement of macism
in Microsoft Windows.
(smart-input-source-ism-lazyman-config "1033" "2052" 'im-select)
However, because 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.
(smart-input-source-ism-lazyman-config nil nil 'fcitx)
(smart-input-source-ism-lazyman-config nil nil 'fcitx5)
(smart-input-source-ism-lazyman-config "xkb:us::eng" "OTHER_INPUT_SOURCE" 'ibus)
The core of the configuring of ISM is the two variables :
(setq smart-input-source-do-get
#'YOUR_DO_GET_INPUT_SOURCE_FUNCTION)
(setq smart-input-source-do-set
#'YOUR_DO_SET_INPUT_SOURCE_FUNCTION)
They are provided for EMP
and macism
by default.
If you have a ISM YOUR_ISM
:
- Run
YOUR_ISM
will output the current input source - Run
YOUR_ISM INPUT_SOURCE_ID
will selectINPUT_SOURCE_ID
.
Then you can simply use YOUR_ISM
as a drop in replacement for macism
:
(setq smart-input-source-external-ism "YOUR_ISM")
You can configure ISM by yourself, but a convenient command
smart-input-source-ism-lazyman-config
is also provided for common ISMs.
The mode is designed carefully, so it’s safe to enable for all buffers even its all in English.
(use-package smart-input-source
;; :hook
;; enable the /follow context/ and /inline region/ mode for specific buffers
;; (((text-mode prog-mode) . smart-input-source-follow-context-mode)
;; ((text-mode prog-mode) . smart-input-source-inline-mode))
:config
(smart-input-source-ism-lazyman-config
;; "com.apple.keylayout.ABC"
"com.apple.keylayout.US"
;; "im.rime.inputmethod.Squirrel.Rime"
"com.sogou.inputmethod.sogou.pinyin")
;; enable the /cursor color/ mode
(smart-input-source-global-cursor-color-mode t)
;; enable the /respect/ mode
(smart-input-source-global-respect-mode t)
;; enable the /follow context/ mode for all buffers
(smart-input-source-global-follow-context-mode t)
;; enable the /inline english/ mode for all buffers
(smart-input-source-global-inline-mode t)
)
Tips:
- For
spacemacs
user, if you config it with thehybrid
mode, Some of theevil
related features may not work. Change it tovim
mode instead.
You can change some of the behaviors by configuring related variables, note:
inline other language
feature is turned off by default.
Variable | Description | Default |
---|---|---|
smart-input-source-english | Input source for English | com.apple.keylayout.US |
smart-input-source-other | Input source for other language | com.sogou.inputmethod.sogou.pinyin |
smart-input-source-external-ism | External input resource manager | macism |
smart-input-source-do-get | Function to get the current input source | determined from the environment |
smart-input-source-do-set | Function to set the input source | determined from the environment |
smart-inpu-source-change-hook | Hook to run after input source changes | nil |
smart-input-source-auto-refresh-seconds | Idle interval to auto refresh input source from OS | 0.2 , nil to disable |
Note:
- To save energy, actual interval to refresh input source from OS in a long idle period is increased automatically.
Command Name | Description |
---|---|
smart-input-source-ism-lazyman-config | Configure input source manager |
smart-input-source-get | Get the input source |
smart-input-source-set-english | Set the input source to English |
smart-input-source-set-other | Set the input source to other language |
smart-input-source-switch | Switch the input source between English and other language |
Variable | Description | Default |
---|---|---|
smart-input-source-default-cursor-color | Default cursor color, also used for English | nil (from envrionment) |
smart-input-source-other-cursor-color | Cursor color for other input source | green |
Variable | Description | Default |
---|---|---|
smart-input-source-respect-start | Switch to specific input source when mode enabled | ~’english~ |
smart-input-source-respect-evil-normal-escape | esc to English from evil normal sate | t |
smart-input-source-respect-prefix-and-buffer | Handle prefix key and buffer | t |
smart-input-source-respect-go-english-triggers | Additional trigger to save input source and go English | t |
smart-input-source-respect-restore-trigger | Additional trigger to restore input source | nil |
smart-input-source-prefix-override-keys | Prefix keys to be respected | ~’(“C-c” “C-x” “C-h”)~ |
smart-input-source-prefix-override-recap-triggers | Functions trigger the recap of the prefix override | see variable doc |
smart-input-source-prefix-override-buffer-disable-predicates | Predicates on buffers to disable prefix overriding | see variable doc |
Variable | Description | Default |
---|---|---|
smart-input-source-english-pattern | Pattern to identify a character as English | [a-zA-Z] |
smart-input-source-other-pattern | Pattern to identify a character as other | \cc , see emacs manual |
smart-input-source-blank-pattern | Pattern to identify a character as blank | [:blank:] |
Variable | Description | Default |
---|---|---|
smart-input-source-follow-context-fixed | Context is fixed to a specific language | nil |
smart-input-source-follow-context-aggressive-line | Aggressively detect context across blank lines | t |
smart-input-source-follow-context-hooks | Hooks trigger the context following | see variable doc |
Face Name | Description | Default |
---|---|---|
smart-input-source-inline-face | Face for the inline region overlay | |
smart-input-source-inline-not-max-point | Insert new line when the whole buffer ends with the region | t |
smart-input-source-inline-tighten-head-rule | Rule to delete the head spaces | 1 |
smart-input-source-inline-tighten-tail-rule | Rule to delete the tail spaces | 1 |
smart-input-source-inline-single-space-close | 1 space to close the region, default is 2 spaces/return | t |
smart-input-source-inline-with-english | enable the inline english region feature | t |
smart-input-source-inline-with-other | enable the inline other language region feature | nil |
smart-inpu-source-inline-english-activated-hook | Hook to run after inline english region activated | nil |
smart-inpu-source-inline-english-deactivated-hook | Hook to run after inline english region deactivated | nil |
smart-inpu-source-inline-other-activated-hook | Hook to run after inline other language region activated | nil |
smart-inpu-source-inline-other-deactivated-hook | Hook to run after inline other language region deactivated | nil |
After input source manager is configured, you can get your current
input source id by the command smart-input-source-get
.
- If your input source is switched from
smart-input-source
, then everything should be OK naturally. And yoursmart-input-source-auto-refresh-seconds
can even be set tonil
. - If your input source is switched from OS, to detect the switch timely,
smart-input-source-auto-refresh-seconds
should not be too large. - 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
smart-input-source-get
directly.