NSKK is a Japanese input method for Emacs based on SKK (Simple Kana to Kanji).
Type a reading in romaji, start conversion with SPC, and select a candidate
from an SKK dictionary.
Requires Emacs 29.1 or later. No external ELPA packages are required.
- Hiragana, katakana, half-width katakana, and Latin input
- SKK-JISYO dictionaries, user dictionary registration, and skkserv lookup
- Standard romaji and AZIK input
- Conversion markers: ▽ for a reading, ▼ for candidate selection
Clone this repository and add its src directory to load-path.
Replace the example path with your checkout’s location:
(add-to-list 'load-path "/path/to/nskk.el/src")(require 'nskk)
(nskk-global-mode 1)
;; After nskk-global-mode is enabled:
;; C-j → switch to hiragana input (from ascii mode)
;; C-x C-j → toggle nskk-mode on/off in current bufferBy default, NSKK searches system locations for SKK-JISYO files and falls back
to Emacs’s built-in ja-dic if none are found.
To choose dictionaries explicitly, use this configuration instead of the minimal configuration. Replace the paths with existing dictionary files before enabling NSKK.
(require 'nskk)
(setopt nskk-dict-system-dictionary-files
'("/usr/share/skk/SKK-JISYO.L"
"/usr/share/skk/SKK-JISYO.jinmei"
"/usr/share/skk/SKK-JISYO.geo"))
(nskk-global-mode 1)(use-package nskk
:custom
;; Start in hiragana mode (optional, default is ascii)
(nskk-state-default-mode 'hiragana)
(nskk-dict-system-dictionary-files
'("/usr/share/skk/SKK-JISYO.L"))
(nskk-dict-user-dictionary-file "~/.nskk/jisyo")
;; Show candidate list after 2nd SPC (default: 5)
(nskk-henkan-show-candidates-nth 2)
(nskk-henkan-number-to-display-candidates 7)
:config
(nskk-global-mode 1))| From | Key | To | Indicator |
|---|---|---|---|
| Any | C-x C-j | Toggle on/off | |
| ascii | C-j | hiragana | かな |
| hiragana | q | katakana | カナ |
| hiragana | l | latin | SKK |
| hiragana | L | full-width | 全英 |
| hiragana | / | abbrev | aA |
In hiragana mode, type Kanji to enter the reading ▽かんじ.
The uppercase K starts the conversion reading.
Press SPC to look up candidates and display the first one.
While a single candidate is displayed inline, use SPC (next) or x
(previous), then press C-j to commit without a newline, or RET to
commit and insert a newline.
C-g returns from candidate selection to the reading; another C-g
cancels the reading.
Once the candidate list opens, select a visible candidate with its labeled
key. SPC advances a page; x, C-p, or DEL returns to the previous
page. From the first page, they return to the previous inline candidate,
or to the reading when nskk-henkan-show-candidates-nth is 1. RET and
C-j leave the list open, and unrecognized keys are consumed without
changing the reading or input mode. A configured selection key for a
visible candidate takes precedence over these controls.
If no candidate is found, or you advance past the available candidates,
NSKK prompts for a word to register in the user dictionary. Enter the word
in the minibuffer and press RET, or press C-g to cancel.
To use NSKK kana input inside this prompt, set nskk-use-kana-in-registration
to t; it is disabled by default.
| Key | Command | Description |
|---|---|---|
C-x C-j | nskk-toggle-mode | Toggle NSKK in current buffer |
C-j | nskk-kakutei | Commit reading or inline candidate; switch direct input to hiragana |
q | nskk-handle-q | Toggle hiragana ↔ katakana |
l | nskk-handle-l | Switch to Latin input |
L | nskk-handle-upper-l | Switch to full-width latin (JIS X 0208) |
/ | nskk-handle-slash | Enter abbrev mode |
| Key | Command | Description |
|---|---|---|
SPC | nskk-handle-space | Start conversion / next candidate |
x | nskk-handle-x | Previous candidate |
X | nskk-handle-upper-x | Purge candidate from user dictionary |
RET | nskk-handle-return | Commit inline candidate or reading and insert a newline |
C-g | nskk-handle-cancel | Cancel conversion or preedit |
a s d f j k l | direct select | Select candidate in list mode (default keys) |
C-n | nskk-handle-ctrl-n | Next inline candidate; ignored in candidate list unless configured as a visible selection key; otherwise commit any reading and move down |
C-p | nskk-handle-ctrl-p | Previous candidate during selection; otherwise commit any reading and move up |
C-/ | nskk-undo | Undo input or candidate selection; ordinary Emacs Undo after commit |
Ordinary Undo does not resume conversion: a restored ▼ is ordinary buffer
text, not an active conversion marker. Continue Undo to remove that text.
To reopen the last committed conversion at the next candidate, use
M-x nskk-undo-kakutei. Moving the cursor or typing after the committed
word does not prevent this command from reopening it. This command has no
default key binding and cannot be repeated consecutively or during conversion.
| Key | Behavior |
|---|---|
↑ / C-p | Select previous candidate |
↓ / C-n | Select next candidate |
← / C-b | Commit candidate + move backward |
→ / C-f | Commit candidate + move forward |
These bindings leave an open candidate list unchanged unless configured to select a visible candidate.
| Key | Behavior |
|---|---|
C-a / <home> | Commit any candidate or reading, then go to beginning of line |
C-e / <end> | Commit any candidate or reading, then go to end of line |
| Key | Command | Description |
|---|---|---|
; | nskk-handle-semicolon-key | Sticky shift: start a reading when idle, or mark the okurigana boundary in preedit. Small っ in AZIK |
# | nskk-handle-hash | Start numeric input; dictionary keys beginning with # expand numeric candidates |
DEL | nskk-handle-backspace | Delete last preedit char / cancel inline conversion / go back in candidate list |
TAB | nskk-handle-tab | Dynamic completion (preedit) / indent-for-tab-command |
| Mode | Indicator | Description |
|---|---|---|
ascii | SKK | Direct ASCII input (pass-through) |
latin | SKK | Direct input selected with l |
hiragana | かな | Hiragana input |
katakana | カナ | Katakana input |
katakana-半角 | カナ | Half-width katakana input |
jisx0208-latin | 全英 | Full-width latin (JIS X 0208) |
abbrev | aA | Literal dictionary key input: /word SPC looks up word |
Half-width katakana has no default switching key. In an NSKK buffer, evaluate
(nskk-set-mode 'katakana-半角) or bind a command that calls it.
(setopt nskk-server-enable t)
(setopt nskk-server-host "localhost")
(setopt nskk-server-portnum 1178)(setopt nskk-converter-romaji-style 'azik)
;; Keyboard layout (us101 or jp106, default: jp106)
(setopt nskk-azik-keyboard-type 'jp106)AZIK adds shortened input sequences:
kz→ かんsz→ さんkh→ くう
These modules are included in this repository and loaded when NSKK starts. The display and integration settings below are disabled by default. Region commands can be called without enabling an option.
| Feature | Module | Enable with |
|---|---|---|
| Annotation display | nskk-annotation | (setopt nskk-show-annotation t) |
| Inline mode display | nskk-show-mode | (setopt nskk-show-mode-show t) |
| Inline candidate display | nskk-inline | (setopt nskk-show-inline t) |
| Context auto-mode | nskk-context | (nskk-context-global-mode 1) |
| Isearch integration | nskk-isearch | (setopt nskk-isearch-enable t) |
| Region operations | nskk-region | For example, M-x nskk-hiragana-region or M-x nskk-katakana-region |
| Program dictionaries | nskk-program-dictionary | (setopt nskk-program-dict-enable t) |
Context auto-mode switches to Latin input outside strings and comments in programming modes. It does not automatically switch back to kana input.
nskk-study ships with NSKK but is not loaded automatically. Require it before
the first nskk-mode activation so that activation loads its saved learning
data. Contextual learning reorders candidates based on the previously
confirmed word:
(require 'nskk-study);; How completion is presented in preedit.
;; capf -- completion-at-point-functions (default)
;; cycle -- DDSKK-style TAB cycling, replacing preedit text directly
(setopt nskk-dcomp-style 'capf)
;; In cycle style, show a list below preedit while cycling
(setopt nskk-dcomp-multiple-activate t)A program dictionary answers lookups by running an external command or an Emacs Lisp function instead of reading an SKK-JISYO file.
(setopt nskk-program-dict-enable t)
;; Each entry is a command template or a function. In a template the
;; whitespace-delimited token %s becomes one argv element; without it the
;; reading is sent on stdin. No shell interpolation is performed.
(setopt nskk-program-dicts '("/usr/local/bin/my-dict %s"))
;; Wait budget in seconds per external command (default 1.0)
(setopt nskk-program-dict-timeout 1.0)A function entry is called with the reading and must return nil or a list of
candidate strings. Commands run through make-process; stdout is capped at
1 MiB and parsed as SKK, skkserv, or one-candidate-per-line output, and a
command that times out, exceeds the cap, or exits nonzero counts as a miss.
nskk-program-dict-enable and nskk-program-dicts are marked :risky, so
Emacs will not accept them from a file-local variable without confirmation.
Entries name a command or function NSKK will execute; only add sources you
trust. With nskk-program-dict-enable nil, the default, lookups fail
immediately and nskk-program-dicts is never consulted.
Require nskk before evaluating these examples. Input rules, key bindings,
and presentation can be changed with ordinary Emacs Lisp; extensions do not
need to call the internal Prolog or continuation APIs.
Edit nskk-mode-map directly, including after nskk-mode is enabled.
nskk-current-key-state returns normal, preedit, or converting.
This command switches to hiragana only outside preedit and conversion:
(require 'nskk)
(defun my-nskk-hiragana ()
(interactive)
(when (eq (nskk-current-key-state) 'normal)
(nskk-set-mode 'hiragana)))
(define-key nskk-mode-map (kbd "C-c j") #'my-nskk-hiragana)nskk-converter-user-rules adds or replaces exact romaji rules. These rules
take precedence over the selected style, including nskk-azik-conversion-table, and
survive style changes and reloads.
(require 'nskk)
(setopt nskk-converter-user-rules '(("qa" . "くぁ")
("ka" . "ヵ")))setopt rebuilds the conversion table immediately. After using setq,
call (nskk-converter-reload-style nskk-converter-romaji-style) to apply the value.
A failed rebuild keeps the previous working table.
Remove an entry and reload to restore the style’s
rule; this option does not delete built-in rules. nskk-converter-add-rule
and nskk-converter-remove-rule remain temporary edits to the current table.
The show hook receives the full candidate list and its zero-based page start.
The hide hook takes no arguments. The selector receives a key character, the
full list, and the page start; it returns an absolute candidate index or nil.
This example replaces the list overlay with echo-area output and reuses the
standard selector:
(require 'nskk)
(defun my-nskk-show-candidates (candidates start)
(message "%s"
(mapconcat #'identity
(cl-mapcar (lambda (key candidate)
(format "%c:%s" key candidate))
nskk-henkan-show-candidates-keys
(seq-take (nthcdr start candidates)
nskk-henkan-number-to-display-candidates))
" ")))
(defun my-nskk-hide-candidates ()
(message nil))
(setq nskk-henkan-show-candidates-functions '(my-nskk-show-candidates)
nskk-henkan-hide-candidates-functions '(my-nskk-hide-candidates)
nskk-henkan-select-candidate-by-key-function
#'nskk-candidate-list-select-by-key)These variables have standard UI defaults; setting them to nil disables
their respective callbacks. Use setq-local for a buffer-specific UI.
Changes take effect at the next candidate operation: NSKK hides the old UI
before showing and selecting through the new one. Cleanup uses the hide
callbacks captured for the UI that was shown, even if settings change again.
Hide callbacks must release resources after a partially failed show as well
as after a completed show. NSKK attempts all hide callbacks on cleanup and
preserves the original error or quit condition.
The following example is an alternative to the replacement UI above.
For text-only changes, keep the standard UI and set
nskk-candidate-format-function instead. It receives page candidates,
selection key characters, and the remaining candidate count, and must return
the overlay’s after-string. nskk-henkan-show-candidates-keys controls both
the displayed labels and standard key selection without re-enabling NSKK.
(require 'nskk)
(defun my-nskk-candidate-text (candidates keys remaining)
(concat (nskk-candidate-format candidates keys remaining) " [選択]"))
(setopt nskk-candidate-format-function #'my-nskk-candidate-text)nskk-mode-display-alist entries have the form
(MODE LABEL FACE HELP CURSOR-FACE). Mode-line text, transient mode labels,
and cursor colors read this same table. nskk-mode-display-properties returns
the four properties for a mode, or nil when it has no entry.
This changes the hiragana label without replacing the other modes:
(require 'nskk)
(setf (alist-get 'hiragana nskk-mode-display-alist)
'("あ" nskk-modeline-hiragana-face "ひらがな" nskk-cursor-hiragana))
(nskk-modeline-update)Changes are read on the next display update even if the input mode has not
changed. Call nskk-modeline-update to refresh the current buffer immediately.
For buffer-local changes, first copy the table with
(setq-local nskk-mode-display-alist (copy-tree nskk-mode-display-alist)).
nskk-inline-format-function receives a candidate string and the current
nskk-show-inline style, and must return an after-string. NSKK still owns
the overlay and its cleanup. Styles t and horizontal place text beside
preedit; vertical places it below. Set nskk-show-inline to nil to disable it.
(require 'nskk)
(defun my-nskk-inline-text (candidate style)
(concat (if (eq style 'vertical) "\n" " ") "[" candidate "]"))
(setopt nskk-inline-format-function #'my-nskk-inline-text
nskk-show-inline t)M-x customize-group RET nskk RET
| Command | Description |
|---|---|
make compile | Byte-compile all modules |
make test | Run all tests |
make test-unit | Run unit tests only |
make test-integration | Run integration tests only |
make test-e2e | Run end-to-end tests only |
make lint | Run checkdoc |
make package-lint | Run package-lint |
make bench | Run the benchmark suite |
make clean | Remove *.elc files |
CI gates on make compile, make test, make lint and make package-lint
across Emacs 29.1, 29.4, 30.1 and snapshot.
See CHANGELOG.md.
See CONTRIBUTING.md for development and pull request guidelines.
- DDSKK
- All SKK dictionary contributors