macOSXのVim/Neovimで日本語を入力してみたった

# Summary

Vim / Neovim / MacVim

ノーマルモードに戻るときに自動的に英語モードにする

```
              insert      normal
------------------------------
Input Source  any     ->  en
```

## 結論

`Python(PyObjC)` でかいた  
Neovim / MacVim では普通にストレスなくできるようになった  
Vim では遅すぎて実際には使用できない  

## 作成したプラグイン

[switcher.nvim](https://github.com/callmekohei/switcher.nvim)


## 作成した関数

```
: SwitchEnglish('')
```

Python にて作成  
Neovim の Remote pluginにて使用する  
MacVim, Vimのばあいはnvim-yarpを併用して使用する  

## 使い方

1) Pythonのライブラリをダウンロード

```
$ pip3 install pyobjc-core
$ pip3 install pyobjc-framework-Cocoa
```

2) vimのプラグインをダウンロード他 (ここはお好みのダウンローダーで）

```
$ git clone --depth 1 https://github.com/callmekohei/switcher.nvim

$ nvim .vimrc
  set runtimepath+=/path/to/switcher.nvim
```

3) プラグインを登録する

```
$ nvim
    :UpdateRemotePlugins
```

4) vimrcに下記を書く

```
autocmd InsertLeave * :call SwitchEnglish('')
```

## 課題

```

現在のインプットソース ( current input sources ) を確認する方法を見つけたい

理由；すべてを en にしてるが、Japanese のときだけ en にする処理をしたいから

```

`carbon.foo`で現在のインプットソースを見ようとしてもうまくいかない。。。

```python
# import Carbon by now
# これはうまくいかない！
carbon = ctypes.cdll.LoadLibrary(ctypes.util.find_library('Carbon'))
print(carbon.TISGetInputSourceProperty(carbon.TISCopyCurrentKeyboardInputSource() , carbon.kTISPropertyInputModeID) )
```

`HITool.h`を利用すると現在のインプットソースを見れるが、`carbon.foo`と混ぜると２回目以降？効かなくなる。

```python
# use HITToolbox's functions
HIToolbox_bundle = NSBundle.bundleWithIdentifier_("com.apple.HIToolbox")

# bundle many...
HIToolbox_functions = [ ('TISGetInputSourceProperty', b'@@@'), ('TISCopyCurrentKeyboardInputSource', b'@') ]
HIToolbox_constants = [('kTISPropertyInputModeID', b'@') ]

objc.loadBundleFunctions(HIToolbox_bundle, globals(), HIToolbox_functions)
objc.loadBundleVariables(HIToolbox_bundle, globals(), HIToolbox_constants)

print(TISGetInputSourceProperty(TISCopyCurrentKeyboardInputSource() , kTISPropertyInputModeID))
```

## どうでもいいこと

macOSXのAPIの名前が、Carbon(炭火焼き）とかCocoa（ココア）とか美味しそうでお腹へるやん。。。  

OSXのことまったく何も知らない状態で２日でここまでこれるの、本当にインターネットのおかげ〜  

インターネットすごい！  

というか Python よりも Objective-C とか Swift の情報が圧倒的に多くて嫌になっちゃう  

いや別に Python が好きとかそんなことは一切ないですけどねwww  

## Great references

[pudquick/input_sources.py](https://gist.github.com/pudquick/cff1ecdc02b4cabe5aa0dc6919d97c6d)  
[Khande/auto_switch_kb.py](https://gist.github.com/Khande/76f24ba90607fb5d54185bd8e4520de6)  
[How can we reading / coerce CFArray and CFString etc values from within OS X JXA?](https://stackoverflow.com/a/35007079)


------------

<BR>
<BR>
<BR>
<BR>
<BR>

------------

# ここからしたは過去の記事

## 追記 (2018/08/16/07:20 ）
パイソン(objective-c)で書いてみました。`vimrc`から切り出してプラグインにしてみました。というかつらかった。つらかった。２日でここまで書いた僕えらいwww というか`macOSX`はぜんぜんわからない。（他もわからないけど・・・）

速度ですが、`Neovim`はストレスを感じないレベルです。`Vim`はもさっとしてます。切り替えはおさ(`osascript`)をつかってるのでここを`pyobjc(object-c)`で書き直したら結構いい感じになりそうだな〜と思ってます。思ってますが、わかりません！www 調べてわかり次第書き直したいと思います！

[switcher.nvim](https://github.com/callmekohei/switcher.nvim)

(追記ここまでっ）

------------

<BR>
<BR>
<BR>
<BR>
<BR>

------------

## 最初に書いた記事

## こんな感じ

vimとNeovimとではちょっとやり方が変わります

### vimの場合

help通りにやる（ :h japanese )

```vim
function g:ImActivateFunc(active) abort
  if !a:active
    call system( 'osascript -e "tell application \"System Events\" to key code 102" &' )
  endif
endfunction

function! g:ImStatusFunc() abort
  let l:cmd = 'ObjC.import("Carbon") ;var current_source = $.TISCopyCurrentKeyboardInputSource(); ;var cfs = $.TISGetInputSourceProperty(current_source, $.kTISPropertyInputSourceID); ;ObjC.bindFunction("CFMakeCollectable", [ "id", [ "void *" ] ]); ;Ref.prototype.toNS = function () { return $.CFMakeCollectable(this) } ;cfs.toNS()'
  let l:foo = system( 'osascript -l JavaScript -e "' . l:cmd . '" &' )
  if stridx(l:foo, 'Japanese')
    return 1
  endif
endfunction

set iminsert=2
set imsearch=2
set imcmdline
set imstatusfunc=g:ImStatusFunc
set imactivatefunc=g:ImActivateFunc
```

### Neovimの場合

```vim
function! s:imStatusFunc() abort
  let l:cmd = 'ObjC.import("Carbon") ;var current_source = $.TISCopyCurrentKeyboardInputSource(); ;var cfs = $.TISGetInputSourceProperty(current_source, $.kTISPropertyInputSourceID); ;ObjC.bindFunction("CFMakeCollectable", [ "id", [ "void *" ] ]); ;Ref.prototype.toNS = function () { return $.CFMakeCollectable(this) } ;cfs.toNS()'
  let l:foo = system( 'osascript -l JavaScript -e "' . l:cmd . '" &' )
  if stridx(l:foo, 'Japanese')
    return 1
  endif
  return 0
endfunction

function s:imDeactivateFunc() abort
  call system( 'osascript -e "tell application \"System Events\" to key code 102" &' )
endfunction

autocmd callmekohei-vimrc InsertLeave * if s:imStatusFunc() | :call s:imDeactivateFunc() | endif

```

Vim/Neovim共通

```vim
noremap <silent><nowait><ESC><ESC>
\ :nohlsearch<CR><C-l>
\ :<C-u>call <SID>imDeactivateFunc()<CR>
```

## みどころ
IMEの状態を見る関数

１３時間ほどぶっ続けでやって結局は stack overflow に書いてあったみたいな（泣）

JavaScriptもOSXのObjective-Cとかもぜんぜんわからずにアタックしましたよwww

辛すぎ〜

see also:[How can we reading / coerce CFArray and CFString etc values from within OS X JXA?]( https://stackoverflow.com/questions/33961342/how-can-we-reading-coerce-cfarray-and-cfstring-etc-values-from-within-os-x-jxa)

```JavaScript
// Carbonをインポート；古いAPIを使えるようにする
ObjC.import('Carbon')

var current_source = $.TISCopyCurrentKeyboardInputSource();
var cfs = $.TISGetInputSourceProperty(current_source, $.kTISPropertyInputSourceID);

ObjC.bindFunction('CFMakeCollectable', [ 'id', [ 'void *' ] ]);

Ref.prototype.toNS = function () {
        return $.CFMakeCollectable(this)
    }

cfs.toNS()

```

## 動作的に

日本語切り替えを入れると全体的に動作がもさっとします。とくにインサートからノーマルにいくときに、`:w`を押す癖がついてるのですが、これができなくなるのですよ。たぶん0.3秒ほどウエイトがかかるんですけどそこにちょっと、あああな感じですけど慣れるしかないんでしょうね・・・。うん、でもそれ以外は今のところ快適ですね。

### できれば・・・
いまは`IME`の状態チェックでおさを(osascript)。切り替えるときにもおさを（osascript)。もったいないですよね。ここ。なんとか一つにしたいと思ってるところです。どたなたやってみませんか？

### 参考
[⌨️キーボード配列の取得 - みずぴー日記</A>](https://mzp.hatenablog.com/entry/2017/11/24/115718)
[Apple Developer Documentation</A>](https://developer.apple.com/documentation)
[Building OS X Apps with JavaScript by Tyler Gaw</A>](https://tylergaw.com/articles/building-osx-apps-with-js/)
[Cocoaからのライブ変換(LiveConversion)の変更と監視 — MindTo01s</A>](http://www.mindto01s.com/2017/03/27/9f85c2fb_9f90_4e1b_8e5e_8719f57900eb.html)
[Complete list of AppleScript key codes</A>](https://eastmanreference.com/complete-list-of-applescript-key-codes)
[Examples overview — PyObjC - the Python to Objective-C bridge</A>](https://pyobjc.readthedocs.io/en/latest/examples/index.html)
[Home · JXA-Cookbook/JXA-Cookbook Wiki</A>](https://github.com/JXA-Cookbook/JXA-Cookbook/wiki)
[InputMethodKit | Apple Developer Documentation</A>](https://developer.apple.com/documentation/inputmethodkit)
[JavaScript for OSX Automation AppleScriptの代替をJavaScriptでやるサンプル Advent Calendar 2014 - Qiita</A>](http://nullege.com/codes/show/src%40p%40y%40pyobjc-framework-InputMethodKit-2.5.1%40PyObjCTest%40test_inputmethodkit.py/6/InputMethodKit/python)
[Mac : JavaScript for Automation (JXA) 例文辞典</A>](https://qiita.com/advent-calendar/2014/jxa2013)
[Nullege: A Search Engine for Python source code</A>](http://www.openspc2.org/reibun/JXA/Yosemite/)
[objective c - How can we reading / coerce CFArray and CFString etc values from within OS X JXA? - Stack Overflow</A>](https://stackoverflow.com/questions/33961342/how-can-we-reading-coerce-cfarray-and-cfstring-etc-values-from-within-os-x-jxa)
[objective-c - JXA: Доступ к константам CFString из CoreServices</A>](https://stackoverrun.com/ru/q/9180057)
[osx yosemite の入力環境が色々とかったるいので、考えてみた - ばかもりだし</A>](http://baqamore.hatenablog.com/entry/2014/10/26/195451)
[pyobjc-framework-InputMethodKit · PyPI</A>](https://pypi.org/project/pyobjc-framework-InputMethodKit/)
[SubCandidates/main.m at master · dougalg/SubCandidates</A>](https://github.com/dougalg/SubCandidates/blob/master/SubCandidates/main.m)
[Swift uses InputMethodKit to write an input method | R0uter&#39;s Blog</A>](https://www.logcg.com/en/archives/2078.html)
[Working with System Frameworks in Python and Objective-C.key - psumac2015-62-Working_with_System_Frameworks_in_Python_and_Objective-C.pdf</A>](http://macadmins.psu.edu/wp-content/uploads/sites/24696/2015/07/psumac2015-62-Working_with_System_Frameworks_in_Python_and_Objective-C.pdf)
[xkbswitch-macosx/main.m at master · myshov/xkbswitch-macosx</A>](https://github.com/myshov/xkbswitch-macosx/blob/master/xkbswitch/main.m)
[鳶嶋工房 / AppleScript / JavaScript for Automation (JXA)</A>](http://tonbi.jp/AppleScript/JavaScript/)