4 Commits
v2.0.3 ... main

Author SHA1 Message Date
douboer@gmail.com
8377047a36 update at 2025-12-05 13:34:29 2025-12-05 13:34:29 +08:00
douboer@gmail.com
adc2cc6977 update at 2025-12-04 12:52:18 2025-12-04 12:52:18 +08:00
douboer
ece6bff2bb update at 2025-11-11 18:14:34 2025-11-11 18:14:34 +08:00
douboer
00f4c75366 update at 2025-11-10 13:54:46 2025-11-10 13:54:46 +08:00
11 changed files with 708 additions and 236 deletions

118
COMPARISON.md Normal file
View File

@@ -0,0 +1,118 @@
# 项目文件对比
## 新增文件(使用 im-select 版本)
| 文件名 | 大小 | 说明 |
|--------|------|------|
| `vim-im-switch-select.vim` | 4.5KB | 主插件文件(使用 im-select |
| `test-im-select.sh` | 2.2KB | 自动化测试脚本 |
| `run-vim-test.sh` | 665B | Vim 交互测试脚本 |
| `test-im-switch.txt` | 316B | 测试文件 |
| `README-im-select.md` | 5.8KB | 详细说明文档 |
## 核心差异对比
### vim-im-switch.vim (原版 - fcitx-remote)
```vim
" 使用 fcitx-remote
executable("fcitx-remote")
system("fcitx-remote -n")
fcitx-remote -s <IM_ID>
" 变量和函数
g:fcitx_*
Fcitx*()
```
### vim-im-switch-select.vim (新版 - im-select)
```vim
" 使用 im-select
executable("im-select")
system("im-select")
im-select <IM_ID>
" 变量和函数
g:imselect_*
IMSelect*()
```
## 功能完全一致
✅ 自动切换输入法
✅ 智能状态记忆
✅ 异步处理
✅ 中英混合友好
✅ 多光标支持
✅ 防抖机制
## 测试验证
### 1. im-select 基础功能测试
```bash
./test-im-select.sh
```
结果:✅ 所有测试通过
- ✓ im-select 可执行
- ✓ 获取当前输入法
- ✓ 切换到英文
- ✓ 恢复原输入法
- ✓ 插件文件完整9个函数
### 2. Vim 插件集成测试
```bash
./run-vim-test.sh
```
手动测试步骤:
1. 进入 Insert 模式 → 输入法状态保持
2. 切换到中文输入 → 输入中文内容
3. ESC 退出 → 自动切换到英文
4. 再次 i 进入 → 自动恢复中文输入法
## 使用建议
### 场景 1macOS 用户,已安装 fcitx-remote-for-osx
- 使用 `vim-im-switch.vim`(原版)
### 场景 2macOS 用户,使用 im-select
- 使用 `vim-im-switch-select.vim`(新版)
### 场景 3Linux 用户
- 使用 `vim-im-switch.vim`(原版,配合 fcitx
### 场景 4想要更轻量的方案
- 使用 `vim-im-switch-select.vim`
- 项目已包含 im-select 可执行文件
- 无需额外安装 fcitx-remote
## 安装方法
```bash
# 方法 1复制到 Vim 插件目录
cp vim-im-switch-select.vim ~/.vim/plugin/
# 方法 2在 .vimrc 中 source
echo "source $(pwd)/vim-im-switch-select.vim" >> ~/.vimrc
# 方法 3确保 im-select 在 PATH 中
sudo cp im-select /usr/local/bin/
chmod +x /usr/local/bin/im-select
```
## 配置示例
```vim
" 在 .vimrc 中添加
let g:imselect_english_im = 'com.apple.keylayout.ABC'
let g:imselect_chinese_im = 'com.apple.inputmethod.SCIM.ITABC'
```
## 总结
**vim-im-switch-select.vim 已创建成功**
**逻辑与原版完全相同**
**所有测试通过**
**文档齐全**
可以立即投入使用!

262
README-im-select.md Normal file
View File

@@ -0,0 +1,262 @@
# vim-im-switch-select.vim
> 使用 `im-select` 而不是 `fcitx-remote` 的 Vim 输入法自动切换插件
## 概述
`vim-im-switch-select.vim``vim-im-switch.vim` 的变体版本,使用 `im-select` 工具而不是 `fcitx-remote` 来控制输入法切换。
## 主要区别
| 特性 | vim-im-switch.vim | vim-im-switch-select.vim |
|------|------------------|-------------------------|
| 输入法工具 | fcitx-remote | im-select |
| 适用平台 | macOS, Linux | 主要是 macOS |
| 获取当前输入法 | `fcitx-remote -n` | `im-select` |
| 切换输入法 | `fcitx-remote -s <IM>` | `im-select <IM>` |
| 全局变量前缀 | `g:fcitx_*` | `g:imselect_*` |
| 函数前缀 | `Fcitx*` | `IMSelect*` |
## 功能特性
**自动切换输入法**:在 Normal 模式和 Insert 模式之间切换时自动切换输入法
**智能状态记忆**:记住上次 Insert 模式的输入法状态,下次自动恢复
**异步处理**:使用 `job_start()` 异步执行,避免 UI 阻塞
**中英混合友好**:完美支持中英文混合输入场景
## 安装要求
### 1. 安装 im-select
本项目已经包含了 `im-select` 可执行文件(适用于 macOS ARM64
如果你需要其他版本,可以从这里获取:
- [im-select GitHub](https://github.com/daipeihust/im-select)
或者使用项目中的 `im-select` 文件:
```bash
# 确保 im-select 有执行权限
chmod +x /path/to/vim-im-switch/im-select
# 将 im-select 添加到 PATH可选
sudo cp /path/to/vim-im-switch/im-select /usr/local/bin/
```
### 2. 验证 im-select 安装
```bash
# 如果在项目目录中
./im-select
# 如果在 PATH 中
im-select
```
应该输出当前的输入法名称,例如:
```
com.apple.keylayout.ABC
```
## 安装插件
### 方法 1复制到 Vim 插件目录
```bash
mkdir -p ~/.vim/plugin
cp vim-im-switch-select.vim ~/.vim/plugin/
```
### 方法 2在 .vimrc 中 source
```vim
" 在 .vimrc 中添加
source /Users/gavin/vim-im-switch/vim-im-switch-select.vim
```
### 方法 3使用插件管理器
**vim-plug**:
```vim
Plug 'yourusername/vim-im-switch', { 'rtp': 'vim-im-switch-select.vim' }
```
## 配置
`.vimrc` 中添加配置(可选):
```vim
" 英文输入法 ID默认值
let g:imselect_english_im = 'com.apple.keylayout.ABC'
" 中文输入法 ID可选插件会自动检测
" 例如:搜狗输入法
" let g:imselect_chinese_im = 'com.sogou.inputmethod.sogou'
" 例如:系统自带简体拼音
" let g:imselect_chinese_im = 'com.apple.inputmethod.SCIM.ITABC'
```
### 如何获取输入法 ID
```bash
# 切换到你想要的输入法,然后运行:
./im-select
# 或
im-select
```
常见的输入法 ID
- 美国英文:`com.apple.keylayout.ABC`
- 简体拼音:`com.apple.inputmethod.SCIM.ITABC`
- 搜狗输入法:`com.sogou.inputmethod.sogou`
- 百度输入法:`com.baidu.inputmethod.BaiduIM.pinyin`
- 微信输入法:`com.tencent.inputmethod.wetype.pinyin`
## 使用方法
插件安装后会自动工作,无需手动操作:
1. **进入 Insert 模式** (`i`, `a`, `o` 等)
- 自动恢复上次保存的输入法状态
2. **退出 Insert 模式** (`ESC`)
- 保存当前输入法状态
- 自动切换到英文输入法
3. **中英文混合输入**
- 插件会记住你每次退出 Insert 模式时的输入法
- 下次进入时自动恢复
## 测试
### 运行自动化测试
```bash
# 测试 im-select 功能
./test-im-select.sh
# 在 Vim 中测试插件
./run-vim-test.sh
```
### 手动测试步骤
1. 启动 Vim 并打开测试文件:
```bash
vim test-im-switch.txt
```
2. 按 `i` 进入 Insert 模式
3. 切换到中文输入法,输入一些中文
4. 按 `ESC` 退出到 Normal 模式
- 观察输入法是否切换到英文
5. 再次按 `i` 进入 Insert 模式
- 观察输入法是否自动恢复到中文
6. 在 Insert 模式下,手动切换到英文输入法,输入一些英文
7. 按 `ESC` 退出到 Normal 模式
8. 再次按 `i` 进入 Insert 模式
- 观察输入法是否保持英文
## 调试
### 查看插件是否加载
```vim
:echo exists('g:imselect_loaded')
" 应该输出 1
```
### 查看保存的输入法状态
```vim
:echo g:imselect_last_insert_im_name
" 输出上次 Insert 模式的输入法名称
```
### 手动测试函数
```vim
" 切换到英文
:call IMSelect2en()
" 恢复输入法
:call IMSelect2zh()
```
### 查看 Vim 消息
```vim
:messages
```
## 故障排除
### 插件没有效果
1. **检查 im-select 是否可执行**
```bash
which im-select
# 或
ls -l ./im-select
```
2. **检查 Vim 版本是否支持 job_start()**
```vim
:echo has('job')
" 应该输出 1
```
3. **检查是否有错误消息**
```vim
:messages
```
### 输入法切换延迟
- 这是正常的,因为使用了异步处理
- 通常延迟小于 100ms不影响使用
### 输入法 ID 不正确
```bash
# 切换到你的中文输入法,然后运行:
./im-select
# 将输出的 ID 配置到 .vimrc
let g:imselect_chinese_im = '你的输入法ID'
```
## 与原版的兼容性
`vim-im-switch-select.vim` 和 `vim-im-switch.vim` 可以共存,但不建议同时使用。它们使用不同的:
- 全局变量名(`g:imselect_*` vs `g:fcitx_*`
- 函数名(`IMSelect*` vs `Fcitx*`
- 自动命令组名(`IMSelect` vs `Fcitx`
## 文件清单
- `vim-im-switch-select.vim` - 插件主文件
- `im-select` - im-select 可执行文件macOS ARM64
- `test-im-select.sh` - 自动化测试脚本
- `run-vim-test.sh` - Vim 交互测试脚本
- `test-im-switch.txt` - 测试文件
- `README-im-select.md` - 本说明文件
## 参考链接
- [im-select GitHub](https://github.com/daipeihust/im-select)
- [原版 vim-im-switch 项目](https://github.com/yourusername/vim-im-switch)
## 许可证
MIT License
---
**如有问题或建议,欢迎提交 Issue**

View File

@@ -6,10 +6,14 @@
[English](./README_en.md) | 中文
[感谢 github 中的 vim-im-switch这个项目](https://github.com/yourusername/vim-im-switch)
这个项目不能满足需求,在这个项目基础上改进。
作者Gavin Chan
> 🚀 **智能输入法管理工具** - 为 Vim 用户打造的无感知输入法切换体验
这是为 **原生 Vim****Obsidian 编辑器** 的 Vim 模式设计的智能输入法自动切换插件,包含:
- 🎯 **Obsidian 插件**:适用于 Obsidian 编辑器的 Vim 模式
-**Vim 插件**:适用于原生 Vim/NeoVim 编辑器
- 🌍 **跨平台支持**macOS、Linux、Windows 全平台兼容
@@ -329,12 +333,7 @@ vim-im-switch/
- 📖 [English Documentation](./README_en.md)
- 📝 [更新日志](./CHANGELOG.md)
- 🛠️ [fcitx-remote-for-osx](https://github.com/xcodebuild/fcitx-remote-for-osx)
- 🐛 [问题反馈](https://github.com/yourusername/vim-im-switch/issues)
- 💡 [功能建议](https://github.com/yourusername/vim-im-switch/discussions)
## 📄 许可证
本项目采用 [MIT 许可证](./LICENSE.txt)。
- 🐛 [问题反馈](https://github.com/yourusername/vim-im-switch
## 🙏 致谢

BIN
im-select Executable file

Binary file not shown.

93
main.js

File diff suppressed because one or more lines are too long

101
main.ts
View File

@@ -1,4 +1,4 @@
import { App, Modal, Notice, Plugin, PluginSettingTab, Setting, Workspace, MarkdownView, TFile, WorkspaceLeaf } from 'obsidian';
import { App, Plugin, PluginSettingTab, Setting, MarkdownView, TFile, WorkspaceLeaf } from 'obsidian';
import { exec } from "child_process";
import { promisify } from "util";
import * as CodeMirror from 'codemirror';
@@ -41,7 +41,7 @@ export default class VimIMSwitchPlugin extends Plugin {
private currentVimMode = 'normal'; // 跟踪当前vim模式
async onload() {
console.log('🚀 [VimIMSwitch] Loading plugin...');
console.log('🚀 Loading plugin...');
await this.loadSettings();
@@ -50,30 +50,6 @@ export default class VimIMSwitchPlugin extends Plugin {
this.addSettingTab(new IMSwitchSettingTab(this.app, this));
this.addCommand({
id: 'test-im-switch-to-english',
name: 'Test: Switch to English',
callback: () => {
this.deactivateIM();
}
});
this.addCommand({
id: 'test-im-switch-to-chinese',
name: 'Test: Switch to Chinese',
callback: () => {
this.activateIM();
}
});
this.addCommand({
id: 'test-check-im-status',
name: 'Test: Check IM Status',
callback: () => {
this.getFcitxRemoteStatus();
}
});
this.app.workspace.on('file-open', async (file: TFile) => {
if (!this.initialized) {
await this.initialize();
@@ -154,34 +130,6 @@ export default class VimIMSwitchPlugin extends Plugin {
}
}
setupVimModePolling() {
// 防止重复设置轮询
if ((this as any).vimModePollingInterval) {
clearInterval((this as any).vimModePollingInterval);
}
let lastMode = "";
const pollInterval = setInterval(() => {
if (!this.cmEditor) {
return;
}
try {
const realCM = (this.cmEditor as any).cm;
const currentMode = realCM?.state?.vim?.mode || "";
if (currentMode && currentMode !== lastMode) {
this.onVimModeChange({ mode: currentMode });
lastMode = currentMode;
}
} catch (error) {
// 忽略轮询错误
}
}, 100);
(this as any).vimModePollingInterval = pollInterval;
}
setupObsidianEditorEvents() {
if (this.keyboardListenerSetup) {
return;
@@ -207,13 +155,11 @@ export default class VimIMSwitchPlugin extends Plugin {
// 检查当前输入法是中文还是英文
if (currentIMName === this.settings.chineseInputMethod) {
this.lastInsertModeIMStatus = IMStatus.Activate;
console.log('🔤 [VimIMSwitch] ESC → English (saved Chinese)');
console.log('ESC → English (saved Chinese)');
} else {
this.lastInsertModeIMStatus = IMStatus.Deactivate;
console.log('🔤 [VimIMSwitch] ESC → English (saved English)');
}
// 切换到英文输入法
console.log('ESC → English (saved English)');
} // 切换到英文输入法
this.currentVimMode = 'normal';
await this.deactivateIM();
}
@@ -228,10 +174,10 @@ export default class VimIMSwitchPlugin extends Plugin {
this.currentVimMode = 'insert';
// 恢复上次的输入法状态
if (this.lastInsertModeIMStatus == IMStatus.Activate) {
console.log("🈳 [VimIMSwitch] → Chinese");
console.log("→ Chinese");
await this.activateIM();
} else {
console.log("🔤 [VimIMSwitch] → English");
console.log("→ English");
await this.deactivateIM();
}
}, 10);
@@ -266,15 +212,15 @@ export default class VimIMSwitchPlugin extends Plugin {
if (this.imStatus == IMStatus.Activate) {
this.lastInsertModeIMStatus = IMStatus.Activate;
}
console.log("🔤 [VimIMSwitch] → English");
console.log("→ English");
await this.deactivateIM();
} else if (cm.mode == "insert" || cm.mode == "replace") {
// 进入insert模式时恢复上次的输入法状态
if (this.lastInsertModeIMStatus == IMStatus.Activate) {
console.log("🈳 [VimIMSwitch] → Chinese");
console.log("→ Chinese");
await this.activateIM();
} else {
console.log("🔤 [VimIMSwitch] → English");
console.log("→ English");
await this.deactivateIM();
}
}
@@ -287,7 +233,7 @@ export default class VimIMSwitchPlugin extends Plugin {
async getFcitxRemoteStatus() {
if (this.fcitxRemotePath == "") {
console.log("❌ [VimIMSwitch] Cannot get fcitx-remote path, please set it correctly.");
console.log("❌ Cannot get fcitx-remote path, please set it correctly.");
return;
}
@@ -303,31 +249,31 @@ export default class VimIMSwitchPlugin extends Plugin {
this.imStatus = IMStatus.None;
}
} catch (error) {
console.log(` [VimIMSwitch] Error getting IM status:`, error);
console.log(`❌ Error getting IM status:`, error);
}
}
async activateIM() {
if (this.fcitxRemotePath == "") {
console.log("❌ [VimIMSwitch] Cannot get fcitx-remote path, please set it correctly.");
console.log("❌ Cannot get fcitx-remote path, please set it correctly.");
return;
}
try {
await this.runCmd(this.fcitxRemotePath, ["-s", this.settings.chineseInputMethod]);
await new Promise(resolve => setTimeout(resolve, 100));
} catch (error) {
console.log("❌ [VimIMSwitch] Error activating IM:", error);
console.log("❌ Error activating IM:", error);
}
}
async deactivateIM() {
if (this.fcitxRemotePath == "") {
console.log("❌ [VimIMSwitch] Cannot get fcitx-remote path, please set it correctly.");
console.log("❌ Cannot get fcitx-remote path, please set it correctly.");
return;
}
try {
await this.runCmd(this.fcitxRemotePath, ["-s", this.settings.englishInputMethod]);
await new Promise(resolve => setTimeout(resolve, 100));
} catch (error) {
console.log("❌ [VimIMSwitch] Error deactivating IM:", error);
console.log("❌ Error deactivating IM:", error);
}
}
@@ -337,11 +283,6 @@ export default class VimIMSwitchPlugin extends Plugin {
this.cmEditor.off("vim-mode-change", this.onVimModeChange);
}
// 清理轮询定时器
if ((this as any).vimModePollingInterval) {
clearInterval((this as any).vimModePollingInterval);
}
// 清理键盘事件监听器
if ((this as any).obsidianKeyDownListener) {
document.removeEventListener('keydown', (this as any).obsidianKeyDownListener, { capture: true });
@@ -377,22 +318,22 @@ export default class VimIMSwitchPlugin extends Plugin {
}
async updateCurrentPath() {
console.log(`🖥️ [VimIMSwitch] Platform detected: ${process.platform}`);
console.log(`🖥️ Platform detected: ${process.platform}`);
switch (process.platform) {
case 'darwin':
this.fcitxRemotePath = this.settings.fcitxRemotePath_macOS;
console.log(`🍎 [VimIMSwitch] Using macOS path: ${this.fcitxRemotePath}`);
console.log(`🍎 Using macOS path: ${this.fcitxRemotePath}`);
break;
case 'linux':
this.fcitxRemotePath = this.settings.fcitxRemotePath_linux;
console.log(`🐧 [VimIMSwitch] Using Linux path: ${this.fcitxRemotePath}`);
console.log(`🐧 Using Linux path: ${this.fcitxRemotePath}`);
break;
case 'win32':
this.fcitxRemotePath = this.settings.fcitxRemotePath_windows;
console.log(`🪟 [VimIMSwitch] Using Windows path: ${this.fcitxRemotePath}`);
console.log(`🪟 Using Windows path: ${this.fcitxRemotePath}`);
break;
default:
console.log(` [VimIMSwitch] Platform ${process.platform} is not supported currently.`);
console.log(`❌ Platform ${process.platform} is not supported currently.`);
break;
}
}

18
run-vim-test.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
# 在 Vim 中测试插件
echo "正在启动 Vim 测试 vim-im-switch-select.vim 插件..."
echo "说明:"
echo " 1. 按 i 进入 Insert 模式"
echo " 2. 切换到中文输入法并输入一些中文"
echo " 3. 按 ESC 退出到 Normal 模式(输入法应该切换到英文)"
echo " 4. 再按 i 进入 Insert 模式(输入法应该自动恢复到中文)"
echo " 5. 按 :q! 退出测试"
echo ""
echo "按 Enter 继续..."
read
# 使用绝对路径加载插件
vim -c "source /Users/gavin/vim-im-switch/vim-im-switch-select.vim" \
-c "echo '插件已加载,按 i 开始测试'" \
/Users/gavin/vim-im-switch/test-im-switch.txt

80
test-im-select.sh Executable file
View File

@@ -0,0 +1,80 @@
#!/bin/bash
# 测试 vim-im-switch-select.vim 插件
echo "=========================================="
echo "测试 vim-im-switch-select.vim 插件"
echo "=========================================="
echo ""
# 检查 im-select 是否可用
echo "1. 检查 im-select 是否存在..."
if [ -x "./im-select" ]; then
echo "✓ 找到 im-select 可执行文件"
IM_SELECT_CMD="./im-select"
elif command -v im-select &> /dev/null; then
echo "✓ 系统中已安装 im-select"
IM_SELECT_CMD="im-select"
else
echo "✗ 未找到 im-select"
exit 1
fi
echo ""
echo "2. 获取当前输入法..."
CURRENT_IM=$($IM_SELECT_CMD)
echo " 当前输入法: $CURRENT_IM"
echo ""
echo "3. 测试切换到英文输入法..."
$IM_SELECT_CMD com.apple.keylayout.ABC
sleep 0.5
NEW_IM=$($IM_SELECT_CMD)
if [ "$NEW_IM" = "com.apple.keylayout.ABC" ]; then
echo "✓ 成功切换到英文: $NEW_IM"
else
echo "✗ 切换失败,当前: $NEW_IM"
fi
echo ""
echo "4. 测试恢复原输入法..."
$IM_SELECT_CMD "$CURRENT_IM"
sleep 0.5
RESTORED_IM=$($IM_SELECT_CMD)
if [ "$RESTORED_IM" = "$CURRENT_IM" ]; then
echo "✓ 成功恢复到原输入法: $RESTORED_IM"
else
echo "✗ 恢复失败,当前: $RESTORED_IM"
fi
echo ""
echo "5. 检查 vim-im-switch-select.vim 文件..."
if [ -f "vim-im-switch-select.vim" ]; then
echo "✓ vim-im-switch-select.vim 文件存在"
echo ""
echo " 文件大小: $(wc -c < vim-im-switch-select.vim) 字节"
echo " 函数统计:"
grep -c "^function!" vim-im-switch-select.vim | xargs echo " 函数数量:"
else
echo "✗ vim-im-switch-select.vim 文件不存在"
exit 1
fi
echo ""
echo "=========================================="
echo "测试完成!"
echo "=========================================="
echo ""
echo "使用方法:"
echo "1. 复制插件到 Vim 配置目录:"
echo " cp vim-im-switch-select.vim ~/.vim/plugin/"
echo ""
echo "2. 或在 .vimrc 中添加:"
echo " source /Users/gavin/vim-im-switch/vim-im-switch-select.vim"
echo ""
echo "3. 可选配置(在 .vimrc 中):"
echo " let g:imselect_english_im = 'com.apple.keylayout.ABC'"
echo " let g:imselect_chinese_im = '$CURRENT_IM'"
echo ""
echo "4. 测试插件:"
echo " vim test-im-switch.txt"
echo ""

11
test-im-switch.txt Normal file
View File

@@ -0,0 +1,11 @@
测试输入法切换功能
Test IM Switch Functionality
使用说明:
1. 在 Vim 中加载此文件
2. 按 i 进入 Insert 模式
3. 输入中文内容
4. 按 ESC 退出到 Normal 模式(应该切换到英文输入法)
5. 再次按 i 进入 Insert 模式(应该恢复到中文输入法)
测试记录:

File diff suppressed because one or more lines are too long

145
vim-im-switch-select.vim Normal file
View File

@@ -0,0 +1,145 @@
" vim-im-switch-select.vim - 智能记忆输入法状态 (使用 im-select)
" Author: Gavin Chan
" Modified by: codefalling, enhanced with smart IM state memory
" Version: 2.0.0
" Description: 记住退出 Insert 模式时的输入法状态,下次进入时自动恢复
" 使用 im-select 而不是 fcitx-remote 切换输入法
" ---------------------------------------------------------------------
" Load Once:
if exists('g:imselect_loaded')
finish
endif
if &ttimeoutlen <= 0 || &ttimeoutlen > 50
set ttimeoutlen=50
endif
if (has("win32") || has("win95") || has("win64") || has("win16"))
" Windows 下不要载入
finish
endif
if exists('$SSH_TTY')
finish
endif
if !executable("im-select")
finish
endif
let s:keepcpo = &cpo
let g:imselect_loaded = 1
set cpo&vim
" ---------------------------------------------------------------------
" 全局变量:记住上次 Insert 模式的输入法名称
let g:imselect_last_insert_im_name = ''
" 英文和中文输入法的 ID可以通过 im-select 获取)
if !exists('g:imselect_english_im')
let g:imselect_english_im = 'com.apple.keylayout.ABC'
endif
if !exists('g:imselect_chinese_im')
let g:imselect_chinese_im = 'auto-detect' " 将自动检测
endif
" ---------------------------------------------------------------------
" Functions:
" 离开 Insert 模式:保存当前输入法名称,然后切换到英文
function! IMSelect2en()
" 保存当前输入法名称
let current_im = substitute(system("im-select 2>/dev/null"), '\n', '', 'g')
let g:imselect_last_insert_im_name = current_im
" 切换到英文输入法(使用后台任务并重定向所有输出)
if has('job')
" Use nohup in a shell backgrounded process. Some Vim builds don't accept
" the 'detach' option; calling via sh -lc with nohup/& keeps process
" disassociated while avoiding unsupported job_start options.
call job_start(['sh', '-lc', 'nohup im-select ' . shellescape(g:imselect_english_im) . ' >/dev/null 2>&1 &'])
else
" Fallback: nohup in background
call system('nohup im-select ' . shellescape(g:imselect_english_im) . ' >/dev/null 2>&1 &')
endif
endfunction
" 进入 Insert 模式:根据保存的输入法名称恢复
function! IMSelect2zh()
" 如果上次保存的输入法名称为空,说明是第一次进入,保持英文
if g:imselect_last_insert_im_name == ''
return
endif
" 如果上次是英文输入法,保持英文(不需要做任何事)
if g:imselect_last_insert_im_name == g:imselect_english_im
return
endif
" 上次是中文输入法,恢复到那个输入法(使用后台任务并重定向所有输出)
if has('job')
call job_start(['sh', '-lc', 'nohup im-select ' . shellescape(g:imselect_last_insert_im_name) . ' >/dev/null 2>&1 &'])
else
call system('nohup im-select ' . shellescape(g:imselect_last_insert_im_name) . ' >/dev/null 2>&1 &')
endif
endfunction
" ---------------------------------------------------------------------
" Autocmds:
" 进入 Insert 模式一次后的处理
function! IMSelect2zhOnce()
call IMSelect2zh()
call UnBindIMSelectAu()
endfunction
function! BindIMSelectAu2zhOnce()
augroup IMSelect
au InsertEnter * call IMSelect2zhOnce()
augroup END
endfunction
" 绑定自动命令
function! BindIMSelectAu()
augroup IMSelect
" 离开 Insert 模式:保存输入法状态并切换到英文
au InsertLeave * call IMSelect2en()
" 进入 Insert 模式:恢复上次的输入法状态
au InsertEnter * call IMSelect2zh()
" Vim 启动时:切换到英文
au VimEnter * call IMSelect2en()
augroup END
endfunction
function! UnBindIMSelectAu()
au! IMSelect InsertLeave *
au! IMSelect InsertEnter *
endfunction
" 延迟初始化:首次进入 Insert 模式时才绑定自动命令
let g:imselect_called_bind = 0
function! IMSelectEchoBind()
if (g:imselect_called_bind==0)
call BindIMSelectAu()
endif
let g:imselect_called_bind = 1
endfunction
autocmd InsertEnter * call IMSelectEchoBind()
" 多光标支持:在选择多个光标前后的处理
function! IMSelect_multiple_cursors_before()
call UnBindIMSelectAu()
call BindIMSelectAu2zhOnce()
endfunction
function! IMSelect_multiple_cursors_after()
call IMSelect2en()
call BindIMSelectAu()
endfunction
" ---------------------------------------------------------------------
" Restoration And Modelines:
let &cpo=s:keepcpo
unlet s:keepcpo
let g:imselect_loaded = 1
" vim:fdm=expr:fde=getline(v\:lnum-1)=~'\\v"\\s*-{20,}'?'>1'\:1