Skip to content

laishulu/emacs-smart-input-source

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

README

https://melpa.org/packages/sis-badge.svg

About

sis (smart input source) enables less manual switch for native or OS input source (input method):

  • A global mode: sis-global-respect-mode to respect buffer/mode by proper input source
    1. Respect start: start Emacs with specified language.
    2. Respect evil: switch to English when leaving evil insert mode.
    3. Respect minibuffer: switch to English when enter minibuffer.
    4. Respect prefix key: switch to English for C-c / C-x / C-h and more.
    5. Respect buffer: recover buffer input source when it regain focus.
  • A buffer local mode: sis-context-mode to switch input source smarted according to context. It also has a global version sis-global-context-mode to enable the mode for all buffers. When to switch input source according to context can be configured easily by a variable, whose default value indicates when entering evil insert mode.
  • A buffer local mode: sis-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 version sis-global-inline-mode to enable the mode for all buffers.
  • A global mode: sis-global-cursor-color-mode to automatically change cursor color according to current input source.

Features

  1. Ease the use of OS-native input source, no need to change use experience.
  2. Ease the use of Emacs-native input source, for further compatibility.
  3. Support GUI Emacs, as well as Terminal Emacs.
  4. Easy to install and configure. No further configuration for GUI Emacs Mac Port with Sogou Input.
  5. Automatically change cursor color according to current input source.
  6. Respect buffer/mode by proper input source:
    1. Respect start: start Emacs with specified language.
    2. Respect evil: switch to English when leaving evil insert mode.
    3. Respect minibuffer: switch to English when enter minibuffer.
    4. Respect prefix key: switch to English for C-c / C-x / C-h and more.
    5. Respect buffer: recover buffer input source when it regain focus.
  7. Support inline English and inline other language region. Features of the inline region (inline english as an example):
    1. Inserting space around none-English characters triggers the region (two consecutive spaces for inline other language region).
    2. In this mode, English will be sticked.
    3. Region is closed when: a. Cursor leaves the region b. Return is pressed. c. Two consecutive space are input (can be configured to one space).
    4. If the region ends with space, none-English input source will be selected, otherwise English input source is retained.
    5. 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.
  8. Switch input source according to context:
    1. Pre-configured for entering evil insert mode.
    2. For native emacs user, you can configure by easily set a variable.
  9. Input source switching rules are designed carefully, for pure English editing, input source will never be switched to other languages.

Install

Just install sis from melpa.

Prepare input source manager (ISM)

Emacs-native input method

Here uses rime as an example:

(sis-ism-lazyman-config nil "rime" 'native)

MacOS

The default MacOS input sources are shown in the following.

;; 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")

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:

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

macism

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 sis-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 as Option and Command key properly when input method is on. I just recommend kitty until Alacirtty 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.

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.

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

im-select

im-select can be used as a drop-in replacement of macism in Microsoft Windows.

(sis-ism-lazyman-config "1033" "2052" 'im-select)
  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.

    ./screenshots/windows-im-select.jpg

  2. If you are using win key as super key, you may also need winsuper.

Linux

fcitx

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

fcitx5

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

ibus

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

Internals for configuring ISM

The core of the configuring of ISM is the two variables :

(setq sis-do-get
      #'YOUR_DO_GET_INPUT_SOURCE_FUNCTION)
(setq sis-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 select INPUT_SOURCE_ID.

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

(setq sis-external-ism "YOUR_ISM")

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

Configure

The mode is designed carefully, so it’s safe to enable for all buffers even its all in English.

(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)
  )

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.

About inline english mode

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

Variables and commands

About input source

VariableDescriptionDefault
sis-english-sourceInput source for Englishcom.apple.keylayout.US
sis-other-sourceInput source for other languagecom.sogou.inputmethod.sogou.pinyin
sis-external-ismExternal input resource managermacism
sis-do-getFunction to get the current input sourcedetermined from the environment
sis-do-setFunction to set the input sourcedetermined from the environment
sis-change-hookHook to run after input source changesnil
sis-auto-refresh-secondsIdle interval to auto refresh input source from OS0.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 NameDescription
sis-ism-lazyman-configConfigure input source manager
sis-getGet the input source
sis-set-englishSet the input source to English
sis-set-otherSet the input source to other language
sis-switchSwitch the input source between English and other language

About cursor color mode

VariableDescriptionDefault
sis-default-cursor-colorDefault cursor color, also used for Englishnil (from envrionment)
sis-other-cursor-colorCursor color for other input sourcegreen

About respect mode

VariableDescriptionDefault
sis-respect-startSwitch to specific input source when mode enabled~’english~
sis-respect-evil-normal-escapeesc to English even in evil normal statet
sis-respect-prefix-and-bufferHandle prefix key and buffert
sis-respect-go-english-triggersAdditional trigger to save input source and go Englisht
sis-respect-restore-triggersAdditional trigger to restore input sourcenil
sis-respect-minibuffer-triggersCommands trigger to set input source in minibuffersee variable doc
sis-prefix-override-keysPrefix keys to be respected~’(“C-c” “C-x” “C-h”)~
sis-prefix-override-recap-triggersFunctions trigger the recap of the prefix overridesee variable doc
sis-prefix-override-buffer-disable-predicatesPredicates on buffers to disable prefix overridingsee variable doc

About language pattern

VariableDescriptionDefault
sis-english-patternPattern to identify a character as English[a-zA-Z]
sis-other-patternPattern to identify a character as other\cc , see emacs manual
sis-blank-patternPattern to identify a character as blank[:blank:]

About context mode

VariableDescriptionDefault
sis-context-detectorsDetectors to detect the contextsee variable doc
sis-context-fixedContext is fixed to a specific languagenil
sis-context-aggressive-lineAggressively detect context across blank linest
sis-context-hooksHooks trigger the context followingsee variable doc
sis-context-triggersCommands trigger the context followingsee variable doc

About inline mode

Face NameDescriptionDefault
sis-inline-faceFace for the inline region overlay
sis-inline-not-max-pointInsert new line when the whole buffer ends with the regiont
sis-inline-tighten-head-ruleRule to delete the head spaces~’one~
sis-inline-tighten-tail-ruleRule to delete the tail spaces~’one~
sis-inline-single-space-close1 space to close the region, default is 2 spaces/returnnil
sis-inline-with-englishenable the inline english region featuret
sis-inline-with-otherenable the inline other language region featurenil
sis-inline-english-activated-hookHook to run after inline english region activatednil
sis-inline-english-deactivated-hookHook to run after inline english region deactivatednil
sis-inline-other-activated-hookHook to run after inline other language region activatednil
sis-inline-other-deactivated-hookHook to run after inline other language region deactivatednil

How to

Get the input source id

After input source manager is configured, you can get your current input source id by the command sis-get.

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

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

Customize my own context detector

Customize sis-context-detectors like the following codes:

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

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:

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

About

Less manual switch for native or OS input source (input method).

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published