This package is similar to emacs-smart-input-source, but it uses dynamic module to switch input source.
- macOS 10.15 or later
- Emacs 29.1 or later, built with dynamic module support (use
--with-modules
during compilation)
If you enable macim-mode
and the module cannot be found, it will prompt whether to automatically download it from GitHub. Or you can manually retrieve the pre-built module from the releases section and place the dylib
file in the emacs-macos-tokenizer-lib-path
(by default, it is located at modules/libMacIM.dylib
within your personal configuration folder, normally ~/.emacs.d/modules/libMacIM.dylib
).
Current version of the dynamic module is v0.0.1, make sure you have updated to latest module.
- Install Xcode.
- Build the module using
macim-compile-module
, which compiles and copies the module tomacim-lib-path
.
If you enconter the folloing error:
No such module “PackageDescription”
run the following command and try again:
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
Install with straight
and use-package
:
(use-package macim
:straight (:host github :repo "roife/emt"
:files ("*.el" "module/*" "module"))
:hook (after-init . emt-mode))
For simplicity, Macim does not come with most customizations preset. You can use the configurations in this section as presets.
If you are using use-package
, you can put the following configurations into :config
.
Select ascii input source when exiting meow-insert-mode
.
(add-hook 'meow-insert-exit-hook #'macim-select-ascii)
Detect by predicates when entering meow-insert-mode
.
(add-hook 'meow-insert-enter-hook #'macim-context-switch)
(advice-add 'select-window :after #'(lambda (&rest _) (macim-context-switch)))
Here takes pdf-view-mode
as an example.
(defun +macim-context-ignore-modes ()
(when (derived-mode-p 'pdf-view-mode)
'ascii))
(add-to-list 'macim-context-early-predicates #'+macim-context-ignore-modes)
(setq +macim-chinese-punc-chars (mapcar #'string-to-char macim--chinese-punc-list))
(defun +macim-remove-head-space-after-cc-punc (_)
(when (or (memq (char-before) +macim-chinese-punc-chars)
(bolp))
(delete-char 1)))
(setq macim-inline-head-handler #'+macim-remove-head-space-after-cc-punc)
(defun +macim-remove-tail-space-before-cc-punc (tighten-back-to)
(when (> (point) tighten-back-to)
(backward-delete-char (1- (- (point) tighten-back-to))))
(when (and (eq (char-before) ? )
(memq (char-after) +macim-chinese-punc-chars))
(backward-delete-char 1)))
(setq macim-inline-tail-handler #'+macim-remove-tail-space-before-cc-punc)
(defun +macim-line-set-last-space-pos ()
(when (eq (char-before) ?\s)
(setq +macim-inline-english-last-space-pos (point))))
(add-hook 'macim-inline-deactivated-hook #'+macim-line-set-last-space-pos)
(defun +macim-inline-remove-redundant-space ()
(when (eq +macim-inline-english-last-space-pos (1- (point)))
(when (and (memq (char-before) +macim-chinese-punc-chars)
(eq (char-before (1- (point))) ?\s))
(save-excursion
(backward-char 2)
(delete-char 1)
(setq-local +macim-inline-english-last-space-pos nil)))
(remove-hook 'post-self-insert-hook #'+macim-inline-remove-redundant-space t))
)
(defun +macim-inline-add-post-self-insert-hook ()
(add-hook 'post-self-insert-hook #'+macim-inline-remove-redundant-space nil t))
(add-hook 'macim-inline-deactivated-hook #'+macim-inline-add-post-self-insert-hook)
macim-inline-face
: Face of the overlay forinline-mode
region
macim-lib-path
: The path to the directory of dynamic library for macim.macim-ascii
: The ASCII input source (i.e. English input source). Default:com.apple.keylayout.ABC
.macim-other
: Theother
input source (e.g. Chinese input source). Default:com.apple.inputmethod.SCIM.Shuangpin
Each predicate for context-mode should return on the of following values:
nil
: left the determination to later predicatesascii
: switch to ASCII input sourceother
: switch toother
input source
Once any of the predicates returns a non-nil results, the rest of predicates are not evaluated.
macim-context-early-predicates
: Predicate to detect the context. It is called before computations ofmacim--back-detect-chars
andmacim--fore-detect-chars
. So predicates that do not need context can be put here.macim-context-predicates
: Predicate to detect the context. Each predicate have two arguments:back-detect
andfore-detect
.
The back-detect
is a struct that contains the following fields:
to
: The position of the first non-blank char before the current position in current linechar
: The first non-blank char before the current position in current linecross-line-to
: Same as `to’, but cross linescross-line-char
: Same as `char’, but cross lines
Similarly, the fore-detect
is a struct that contains four fields which are the same as back-detect
, but for the positions and chars after the current position.
macim-inline-head-handler
: Function to delete head spaces. The cursor will be moved to the beginning of the inline region, and the function will be called with the end position of the leading whitespaces in region.macim-inline-tail-handler
: Function to delete tail spaces. The cursor will be moved to the end of the inline region, and the function will be called with the start position of the trailing whitespaces in region.macim-inline-activated-hook
,macim-inline-deactivated-hook
: Hook run when inline mode is activated/deactivated.
This package is inspired by emacs-smart-input-source which is a awesome package for input method switching.
The dynamic module uses emacs-swift-module, which provides an interface for writing Emacs dynamic modules in Swift.