├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── im-select.m └── plugin ├── im-select └── smartim.vim /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | plugin/*_x86 3 | plugin/*_arm 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Use it for whatever you like :-) 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=/usr/bin/clang 2 | NAME=im-select 3 | OPTS=-framework foundation -framework carbon 4 | 5 | all: x86_target arm_target 6 | lipo -create -output plugin/$(NAME) plugin/$(NAME)_x86 plugin/$(NAME)_arm 7 | 8 | x86_target: $(NAME).m 9 | $(CC) $(OPTS) $(NAME).m -o plugin/$(NAME)_x86 -target x86_64-apple-macos10.12 10 | 11 | arm_target: $(NAME).m 12 | $(CC) $(OPTS) $(NAME).m -o plugin/$(NAME)_arm -target arm64-apple-macos11 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What is this? 2 | 3 | SmartIM is a plugin to make vim stand well with input methods. It switches 4 | the input method to the default keyboard (usually English) when leaving insert mode and 5 | switches back when you enter insert mode again. It consists of 2 tiny programs: 6 | 7 | * `im-select`: a command-line utility to get/set active input method 8 | * `smartim.vim`: a vim plugin to do automatic input method switch, using `im-select` 9 | 10 | It is Mac-only for now. 11 | 12 | # Installation 13 | 14 | ## Vundle 15 | 1. Add this line to your ~/.vimrc file: 16 | ```Plugin 'ybian/smartim'``` 17 | 2. Open vim and run `:PluginInstall` 18 | 19 | ## Pathogen 20 | 1. `cd ~/.vim/bundle` 21 | 2. `git clone git@github.com:ybian/smartim.git` 22 | 23 | ## Others 24 | 1. Clone this repository to your local disk 25 | 2. Copy `im-select` and `smartim.vim` (both are under `plugin` directory) to your vim plugin directory (usually `.vim/plugins`) 26 | 27 | Then, enjoy the convenience! 28 | 29 | # FAQ 30 | 31 | ## Why is it Mac-only? 32 | 33 | Because the command-line utility `im-select` uses Mac specific APIs. It should be easy to develop 34 | equivalents for other platforms but I just don't have the time to do so. 35 | 36 | ## Can I use `im-select` as a standalone utility? 37 | 38 | Sure. The usage is very simple: invoke it with no argument to get the ID string of current active 39 | input method; invoke it with an ID string to set current input method. 40 | 41 | ``` 42 | $ im-select 43 | com.apple.keylayout.US # print the ID string of your active input method 44 | $ im-select com.apple.keylayout.US # change your active input method 45 | ``` 46 | 47 | ## What should I do if my default keyboard is not US English? 48 | 49 | SmartIM assumes your default keyboard is US English (com.apple.keylayout.US). If you want to change this, 50 | please add the following line to your `.vimrc`: 51 | 52 | `let g:smartim_default = ''` 53 | 54 | Replace `` with the ID string of your input method (which can be get via `im-select`) 55 | 56 | 57 | ## Somehow I want to disable this plugin 58 | 59 | For example, some people reported that it is slow while editing with vim-multiple-cursors, to fix this, put this in .vimrc: 60 | 61 | ``` 62 | function! Multiple_cursors_before() 63 | let g:smartim_disable = 1 64 | endfunction 65 | function! Multiple_cursors_after() 66 | unlet g:smartim_disable 67 | endfunction 68 | ``` 69 | 70 | ## I have other problems to debug... 71 | 72 | Follow the following steps: 73 | 74 | 1. Run vim with `vim --cmd 'let g:smartim_debug=1'` 75 | 2. Enter and leave insert mode for a couple of times to reproduce your problem; then exit vim. 76 | 3. Open an issue on github and attach the content of `~/vim_smartim_debug_output` 77 | -------------------------------------------------------------------------------- /im-select.m: -------------------------------------------------------------------------------- 1 | // 2 | // im-select 3 | // 4 | // Created by Ying Bian on 8/21/12. 5 | // Copyright (c) 2012 Ying Bian. All rights reserved. 6 | // 7 | 8 | #import 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 13 | 14 | int returnCode = 0; 15 | 16 | if (argc > 1) { 17 | NSString *imId = [NSString stringWithUTF8String:argv[1]]; 18 | NSDictionary *filter = [NSDictionary dictionaryWithObject:imId forKey:(NSString *)kTISPropertyInputSourceID]; 19 | CFArrayRef keyboards = TISCreateInputSourceList((CFDictionaryRef)filter, false); 20 | if (keyboards) { 21 | TISInputSourceRef selected = (TISInputSourceRef)CFArrayGetValueAtIndex(keyboards, 0); 22 | returnCode = TISSelectInputSource(selected); 23 | CFRelease(keyboards); 24 | } else { 25 | returnCode = 1; 26 | } 27 | } else { 28 | TISInputSourceRef current = TISCopyCurrentKeyboardInputSource(); 29 | NSString *sourceId = (NSString *)(TISGetInputSourceProperty(current, kTISPropertyInputSourceID)); 30 | fprintf(stdout, "%s\n", [sourceId UTF8String]); 31 | CFRelease(current); 32 | } 33 | 34 | [pool release]; 35 | 36 | return returnCode; 37 | } -------------------------------------------------------------------------------- /plugin/im-select: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ybian/smartim/d73dc7b361966762d74254a1ba52d29dd83d5fd3/plugin/im-select -------------------------------------------------------------------------------- /plugin/smartim.vim: -------------------------------------------------------------------------------- 1 | " ============================================================================= 2 | " A plugin to make vim stand well with input methods (Mac only) 3 | " Author: Ying Bian 4 | " Last Change: 2022-09-27 5 | " Version: 1.0.1 6 | " Repository: https://github.com/ybian/smartim 7 | " License: MIT 8 | " ============================================================================= 9 | 10 | if exists('g:smartim_loaded') || &cp 11 | finish 12 | endif 13 | let g:smartim_loaded = 1 14 | 15 | if !exists("g:smartim_default") 16 | let g:smartim_default = "com.apple.keylayout.US" 17 | endif 18 | 19 | if !exists("g:smartim_disable") 20 | let g:smartim_disable = 0 21 | endif 22 | 23 | if !exists("g:smartim_debug") 24 | let g:smartim_debug = 0 25 | endif 26 | 27 | let s:imselect_path = expand(':p:h') . "/im-select" 28 | let s:smartim_debug_output = $HOME . "/vim_smartim_debug_output" 29 | 30 | function! Smartim_debug_print(msg) 31 | if g:smartim_debug == 0 32 | return 33 | endif 34 | 35 | let l:debug_msg = strftime("[%Y-%m-%d_%H:%M:%S]") . ' ' . a:msg 36 | silent call writefile([l:debug_msg], s:smartim_debug_output, "a") 37 | endfunction 38 | 39 | function! Smartim_start_debug() 40 | if g:smartim_debug == 0 41 | return 42 | endif 43 | 44 | let l:start_debug_msg = strftime("[%Y-%m-%d_%H:%M:%S]") . " - Debug Start" 45 | silent call writefile([l:start_debug_msg], s:smartim_debug_output) 46 | 47 | call Smartim_debug_print('g:smartim_loaded = ' . g:smartim_loaded) 48 | call Smartim_debug_print('g:smartim_default = ' . g:smartim_default) 49 | call Smartim_debug_print('g:smartim_disable = ' . g:smartim_disable) 50 | call Smartim_debug_print('g:smartim_debug = ' . g:smartim_debug) 51 | call Smartim_debug_print('s:imselect_path = ' . s:imselect_path) 52 | endfunction 53 | 54 | call Smartim_start_debug() 55 | 56 | function! Smartim_GetInputMethodHandler(channel, msg) 57 | silent let b:saved_im = a:msg 58 | silent call system(s:imselect_path . ' ' .g:smartim_default) 59 | call Smartim_debug_print('b:saved_im = ' . b:saved_im) 60 | call Smartim_debug_print('<<< Smartim_SelectDefault returned ' . v:shell_error) 61 | endfunction 62 | 63 | function! Smartim_SelectDefault() 64 | call Smartim_debug_print('>>> Smartim_SelectDefault') 65 | 66 | if g:smartim_disable == 1 67 | return 68 | endif 69 | 70 | if has('job') 71 | call job_start([s:imselect_path], {'callback': 'Smartim_GetInputMethodHandler'}) 72 | else 73 | silent let b:saved_im = system(s:imselect_path) 74 | silent call system(s:imselect_path . ' ' . g:smartim_default) 75 | call Smartim_debug_print('b:saved_im = ' . b:saved_im) 76 | call Smartim_debug_print('<<< Smartim_SelectDefault returned ' . v:shell_error) 77 | endif 78 | 79 | endfunction 80 | 81 | function! Smartim_SelectSaved() 82 | call Smartim_debug_print('>>> Smartim_SelectSaved') 83 | 84 | if g:smartim_disable == 1 85 | return 86 | endif 87 | 88 | if exists("b:saved_im") && b:saved_im != g:smartim_default 89 | if has('job') 90 | call job_start([s:imselect_path, b:saved_im]) 91 | else 92 | silent call system(s:imselect_path . ' '. b:saved_im) 93 | endif 94 | 95 | call Smartim_debug_print('b:saved_im=' . b:saved_im.'') 96 | call Smartim_debug_print('<<< Smartim_SelectSaved returned ' . v:shell_error) 97 | else 98 | call Smartim_debug_print('<<< Smartim_SelectSaved returned') 99 | endif 100 | endfunction 101 | 102 | augroup smartim 103 | autocmd! 104 | autocmd VimLeavePre * call Smartim_SelectDefault() 105 | autocmd InsertLeave * call Smartim_SelectDefault() 106 | autocmd InsertEnter * call Smartim_SelectSaved() 107 | augroup end 108 | 109 | " vim:ts=2:sw=2:sts=2 110 | --------------------------------------------------------------------------------