Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 41 additions & 10 deletions extensionBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as vscode from 'vscode';

import { ExCommandLine, SearchCommandLine } from './src/cmd_line/commandLine';
import { configuration } from './src/configuration/configuration';
import { isLiteralMode } from './src/configuration/langmap';
import { Notation } from './src/configuration/notation';
import { Globals } from './src/globals';
import { Jump } from './src/jumps/jump';
Expand All @@ -15,6 +16,7 @@ import { StatusBar } from './src/statusBar';
import { taskQueue } from './src/taskQueue';
import { Logger } from './src/util/logger';
import { SpecialKeys } from './src/util/specialKeys';
import { interruptIMEComposition } from './src/util/util';
import { VSCodeContext } from './src/util/vscodeContext';
import { exCommandParser } from './src/vimscript/exCommandParser';

Expand Down Expand Up @@ -68,6 +70,23 @@ export async function getAndUpdateModeHandler(
return curHandler;
}

/**
* A synchronous and quick way to check the current vim mode.
*/
export function peek_mode(): Mode | undefined {
const activeTextEditor = vscode.window.activeTextEditor;
if (activeTextEditor === undefined || activeTextEditor.document.isClosed) {
return undefined;
}

const editorId = activeTextEditor.document.uri;
const curHandler = ModeHandlerMap.get(editorId);
if (curHandler == null) {
return undefined;
}
return curHandler.vimState.currentMode;
}

/**
* Loads and validates the user's configuration
*/
Expand Down Expand Up @@ -319,11 +338,19 @@ export async function activate(context: vscode.ExtensionContext, handleLocal: bo
const compositionState = new CompositionState();

// Override VSCode commands
overrideCommand(context, 'type', async (args: { text: string }) => {
overrideCommand(context, 'type', (args: { text: string }) => {
taskQueue.enqueueTask(async () => {
const mh = await getAndUpdateModeHandler();
if (mh) {
if (compositionState.isInComposition) {
if (configuration.mapIMEComposition.enable && !isLiteralMode(mh.vimState.currentMode)) {
for (let key of args.text) {
if (key in configuration.mapIMEComposition.map) {
compositionState.reset();
key = configuration.mapIMEComposition.map[key];
}
await mh.handleKeyEvent(key);
}
} else if (compositionState.isInComposition) {
compositionState.composingText += args.text;
if (mh.vimState.currentMode === Mode.Insert) {
compositionState.insertedText = true;
Expand All @@ -339,7 +366,7 @@ export async function activate(context: vscode.ExtensionContext, handleLocal: bo
overrideCommand(
context,
'replacePreviousChar',
async (args: { replaceCharCnt: number; text: string }) => {
(args: { replaceCharCnt: number; text: string }) => {
taskQueue.enqueueTask(async () => {
const mh = await getAndUpdateModeHandler();
if (mh) {
Expand Down Expand Up @@ -368,13 +395,17 @@ export async function activate(context: vscode.ExtensionContext, handleLocal: bo
},
);

overrideCommand(context, 'compositionStart', async () => {
overrideCommand(context, 'compositionStart', () => {
const mode = peek_mode();
if (configuration.mapIMEComposition.enable && mode != null && !isLiteralMode(mode)) {
void interruptIMEComposition();
}
taskQueue.enqueueTask(async () => {
compositionState.isInComposition = true;
});
});

overrideCommand(context, 'compositionEnd', async () => {
overrideCommand(context, 'compositionEnd', () => {
taskQueue.enqueueTask(async () => {
const mh = await getAndUpdateModeHandler();
if (mh) {
Expand Down Expand Up @@ -416,7 +447,7 @@ export async function activate(context: vscode.ExtensionContext, handleLocal: bo
}
});

registerCommand(context, 'vim.remap', async (args: ICodeKeybinding) => {
registerCommand(context, 'vim.remap', (args: ICodeKeybinding) => {
taskQueue.enqueueTask(async () => {
const mh = await getAndUpdateModeHandler();
if (mh === undefined) {
Expand Down Expand Up @@ -452,7 +483,7 @@ export async function activate(context: vscode.ExtensionContext, handleLocal: bo
});
});

registerCommand(context, 'toggleVim', async () => {
registerCommand(context, 'toggleVim', () => {
configuration.disableExtension = !configuration.disableExtension;
void toggleExtension(configuration.disableExtension, compositionState);
});
Expand All @@ -471,7 +502,7 @@ export async function activate(context: vscode.ExtensionContext, handleLocal: bo
await mh.handleKeyEvent(`${boundKey.key}`);
}
};
registerCommand(context, boundKey.command, async () => {
registerCommand(context, boundKey.command, () => {
taskQueue.enqueueTask(command);
});
}
Expand Down Expand Up @@ -535,7 +566,7 @@ function overrideCommand(
command: string,
callback: (...args: any[]) => any,
) {
const disposable = vscode.commands.registerCommand(command, async (args) => {
const disposable = vscode.commands.registerCommand(command, (args) => {
if (configuration.disableExtension) {
return vscode.commands.executeCommand('default:' + command, args);
}
Expand All @@ -562,7 +593,7 @@ export function registerCommand(
callback: (...args: any[]) => any,
requiresActiveEditor: boolean = true,
) {
const disposable = vscode.commands.registerCommand(command, async (args) => {
const disposable = vscode.commands.registerCommand(command, (args) => {
if (requiresActiveEditor && !vscode.window.activeTextEditor) {
return;
}
Expand Down
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1156,6 +1156,16 @@
"vim.langmap": {
"type": "string",
"description": "Language map for alternate keyboard layouts. When you are typing text in Insert (or Replace, etc.) mode, the characters are inserted derectly. Otherwise, they are translated based on the provided map."
},
"vim.mapIMEComposition.enable": {
"type": "boolean",
"markdownDescription": "If enabled, In all modes outside of insert mode, the composition input of the IME is mapped based on the `#vim.mapIMEComposition.map#`.",
"default": false
},
"vim.mapIMEComposition.map": {
"type": "object",
"markdownDescription": "The IME composition to ASCII map. `#vim.mapIMEComposition.enable#` must be enabled.",
"default": {}
}
}
},
Expand Down
7 changes: 7 additions & 0 deletions src/configuration/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
IConfiguration,
IHighlightedYankConfiguration,
IKeyRemapping,
IMapIMEComposition,
IModeSpecificStrings,
ITargetsConfiguration,
} from './iconfiguration';
Expand Down Expand Up @@ -514,6 +515,12 @@ class Configuration implements IConfiguration {
}
return result;
}

// mapIMEComposition
mapIMEComposition: IMapIMEComposition = {
enable: false,
map: {},
};
}

// handle mapped settings between vscode to vim
Expand Down
10 changes: 10 additions & 0 deletions src/configuration/iconfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export interface IAutoSwitchInputMethod {
obtainIMCmd: string;
}

export interface IMapIMEComposition {
enable: boolean;
map: Record<string, string>;
}

export interface IHighlightedYankConfiguration {
/**
* Boolean indicating whether yank highlighting should be enabled.
Expand Down Expand Up @@ -447,4 +452,9 @@ export interface IConfiguration {
shell: string;

langmap: string;

/**
* MapIMEComposition
*/
mapIMEComposition: IMapIMEComposition;
}
10 changes: 10 additions & 0 deletions src/util/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,13 @@ export function findTabInActiveTabGroup(name: string): [number, vscode.Tab] {
}
return foundBuffers[0];
}

/**
* VSCode does not provide the ability to interrupt IME composition,
* so here some trick techniques are used to achieve this
* by switching the current focus target to interrupt the IME composition state.
*/
export async function interruptIMEComposition() {
await vscode.commands.executeCommand('workbench.action.focusTitleBar');
await vscode.commands.executeCommand('workbench.action.focusPreviousGroup');
}
4 changes: 4 additions & 0 deletions test/testConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,8 @@ export class Configuration implements IConfiguration {
'<C-d>': true,
};
langmap = '';
mapIMEComposition = {
enable: false,
map: {},
};
}