Skip to content

Commit 7be2cca

Browse files
fbriconsnjeza
authored andcommitted
Use custom paste action instead of overriding the native one. (#1116)
Signed-off-by: Fred Bricon <[email protected]>
1 parent 470114d commit 7be2cca

File tree

7 files changed

+68
-99
lines changed

7 files changed

+68
-99
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ The following settings are supported:
117117
* `java.codeGeneration.toString.limitElements`: Limit number of items in arrays/collections/maps to list, if 0 then list all. Defaults to `0`.
118118
* `java.selectionRange.enabled`: Enable/disable Smart Selection support for Java. Disabling this option will not affect the VS Code built-in word-based and bracket-based smart selection.
119119

120-
New in 0.51.0:
121-
* `java.actionsOnPaste.organizeImports`: [Experimental] Triggers "Organize imports" when code is pasted into a java file. This overrides VS Code's default paste action, thus might cause some issues. Disabled by default.
120+
New in 0.52.0:
121+
* "Organize imports" is triggered when pasting code into a java file with `Ctrl+Shift+v` (`Cmd+Shift+v` on Mac).
122122

123123
Troubleshooting
124124
===============

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -394,12 +394,6 @@
394394
"default": true,
395395
"description": "Enable/disable Smart Selection support for Java. Disabling this option will not affect the VS Code built-in word-based and bracket-based smart selection.",
396396
"scope": "window"
397-
},
398-
"java.actionsOnPaste.organizeImports": {
399-
"type": "boolean",
400-
"description": "[Experimental] Triggers 'Organize imports' when code is pasted into a Java file. This overrides VS Code's default paste action, thus might cause some issues. Disabled by default.",
401-
"default": false,
402-
"scope": "window"
403397
}
404398
}
405399
},
@@ -469,6 +463,12 @@
469463
{
470464
"command": "java.workspace.compile",
471465
"key": "shift+alt+b"
466+
},
467+
{
468+
"command": "java.action.clipboardPasteAction",
469+
"key": "ctrl+shift+v",
470+
"mac": "cmd+shift+v",
471+
"when": "javaLSReady && editorLangId == java"
472472
}
473473
],
474474
"menus": {

src/commands.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export namespace Commands {
8282
/**
8383
* Open Java log files side by side
8484
*/
85-
export const OPEN_LOGS = 'java.open.logs';
85+
export const OPEN_LOGS = 'java.open.logs';
8686

8787
/**
8888
* Open Java formatter settings
@@ -132,6 +132,10 @@ export namespace Commands {
132132
* Organize imports silently.
133133
*/
134134
export const ORGANIZE_IMPORTS_SILENTLY = "java.edit.organizeImports";
135+
/**
136+
* Custom paste action (triggers auto-import)
137+
*/
138+
export const CLIPBOARD_ONPASTE = 'java.action.clipboardPasteAction';
135139
/**
136140
* Choose type to import.
137141
*/

src/extension.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ import * as buildpath from './buildpath';
1818
import * as hoverAction from './hoverAction';
1919
import * as sourceAction from './sourceAction';
2020
import * as refactorAction from './refactorAction';
21+
import * as pasteAction from './pasteAction';
2122
import * as net from 'net';
2223
import { getJavaConfiguration } from './utils';
23-
import { onConfigurationChange, excludeProjectSettingsFiles, initializeSettings } from './settings';
24+
import { onConfigurationChange, excludeProjectSettingsFiles } from './settings';
2425
import { logger, initializeLogFile } from './log';
2526
import glob = require('glob');
2627

@@ -388,7 +389,7 @@ export function activate(context: ExtensionContext): Promise<ExtensionAPI> {
388389
buildpath.registerCommands(context);
389390
sourceAction.registerCommands(languageClient, context);
390391
refactorAction.registerCommands(languageClient, context);
391-
initializeSettings(languageClient, context); // may need to move in the future
392+
pasteAction.registerCommands(languageClient, context);
392393

393394
context.subscriptions.push(window.onDidChangeActiveTextEditor((editor) => {
394395
toggleItem(editor, item);

src/pasteAction.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
'use strict';
2+
3+
import { commands, env, ExtensionContext, Range, TextEditor, window } from 'vscode';
4+
import { LanguageClient } from 'vscode-languageclient';
5+
import { Commands } from './commands';
6+
7+
export function registerCommands(languageClient: LanguageClient, context: ExtensionContext) {
8+
context.subscriptions.push(commands.registerCommand(Commands.CLIPBOARD_ONPASTE, () => {
9+
registerOrganizeImportsOnPasteCommand();
10+
}));
11+
}
12+
13+
export async function registerOrganizeImportsOnPasteCommand(): Promise<void> {
14+
const clipboardText: string = await env.clipboard.readText();
15+
const editor: TextEditor = window.activeTextEditor;
16+
const documentText: string = editor.document.getText();
17+
const numCursors = editor.selections.length;
18+
let bits: string[] = [];
19+
if (numCursors > 1) {
20+
bits = clipboardText.split(/\r?\n/);
21+
}
22+
const action = editor.edit(textInserter => {
23+
for (let i = 0; i < numCursors; i++) {
24+
const selection = editor.selections[i];
25+
const isCursorOnly = selection.isEmpty;
26+
const text = bits.length === numCursors ? bits[i] : clipboardText;
27+
if (isCursorOnly) {
28+
textInserter.insert(selection.start, text);
29+
}
30+
else {
31+
const start = selection.start;
32+
const end = selection.end;
33+
textInserter.replace(new Range(start, end), text);
34+
}
35+
}
36+
});
37+
38+
action.then((wasApplied) => {
39+
const fileURI = editor.document.uri.toString();
40+
if (wasApplied && fileURI.endsWith(".java")) {
41+
const hasText: boolean = documentText !== null && /\S/.test(documentText);
42+
if (hasText) {
43+
// Organize imports silently to avoid surprising the user
44+
commands.executeCommand(Commands.ORGANIZE_IMPORTS_SILENTLY, fileURI);
45+
} else {
46+
commands.executeCommand(Commands.ORGANIZE_IMPORTS, { textDocument: { uri: fileURI } });
47+
}
48+
}
49+
});
50+
}

src/settings.ts

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ const changeItem = {
1515

1616
const EXCLUDE_FILE_CONFIG = 'configuration.checkProjectSettingsExclusions';
1717
export const ORGANIZE_IMPORTS_ON_PASTE = 'actionsOnPaste.organizeImports'; // java.actionsOnPaste.organizeImports
18-
// index of the paste disposable in the subscriptions array
19-
let pasteSubscriptionIndex;
2018

2119
let oldConfig: WorkspaceConfiguration = getJavaConfiguration();
2220

@@ -39,21 +37,11 @@ export function onConfigurationChange(languageClient: LanguageClient, context: E
3937
}
4038
});
4139
}
42-
handleJavaPasteConfigurationChange(languageClient, context, newConfig);
4340
// update old config
4441
oldConfig = newConfig;
4542
});
4643
}
4744

48-
/**
49-
* Starting point for any settings that need to be handled when the server starts
50-
* @param languageClient
51-
* @param context
52-
*/
53-
export function initializeSettings(languageClient: LanguageClient, context: ExtensionContext) {
54-
handleInitialConfigurations(languageClient, context, getJavaConfiguration());
55-
}
56-
5745
export function excludeProjectSettingsFiles() {
5846
if (workspace.workspaceFolders && workspace.workspaceFolders.length) {
5947
workspace.workspaceFolders.forEach((folder) => {
@@ -128,78 +116,3 @@ export function getJavaEncoding(): string {
128116
}
129117
return javaEncoding;
130118
}
131-
132-
export function handleInitialConfigurations(languageClient: LanguageClient, context: ExtensionContext, newConfig: WorkspaceConfiguration) {
133-
// organize imports on paste registration
134-
if (newConfig.get(ORGANIZE_IMPORTS_ON_PASTE)) {
135-
registerOverridePasteCommand(languageClient, context);
136-
}
137-
}
138-
139-
export function handleJavaPasteConfigurationChange(languageClient: LanguageClient, context: ExtensionContext, newConfig: WorkspaceConfiguration) {
140-
const oldOrganizeImportsOnPaste = oldConfig.get(ORGANIZE_IMPORTS_ON_PASTE);
141-
const newOrganizeImportsOnPaste = newConfig.get(ORGANIZE_IMPORTS_ON_PASTE);
142-
if (oldOrganizeImportsOnPaste !== newOrganizeImportsOnPaste) {
143-
if (newOrganizeImportsOnPaste === true) {
144-
registerOverridePasteCommand(languageClient, context);
145-
}
146-
else {
147-
unregisterOverridePasteCommand(languageClient, context);
148-
}
149-
}
150-
}
151-
152-
export function registerOverridePasteCommand(languageClient: LanguageClient, context: ExtensionContext): void {
153-
// referencing https://github.com/gazugafan/vscode-indent-on-paste/blob/master/src/extension.ts
154-
const length = context.subscriptions.push(commands.registerCommand('editor.action.clipboardPasteAction', async () => {
155-
156-
const clipboardText: string = await env.clipboard.readText();
157-
const editor: TextEditor = window.activeTextEditor;
158-
const documentText: string = editor.document.getText();
159-
const numCursors = editor.selections.length;
160-
let bits: string[] = [];
161-
if (numCursors > 1) {
162-
bits = clipboardText.split(/\r?\n/);
163-
}
164-
const action = editor.edit(textInserter => {
165-
for (let i = 0; i < numCursors; i++) {
166-
const selection = editor.selections[i];
167-
const isCursorOnly = selection.isEmpty;
168-
const text = bits.length === numCursors ? bits[i] : clipboardText;
169-
if (isCursorOnly) {
170-
textInserter.insert(selection.start, text);
171-
}
172-
else {
173-
const start = selection.start;
174-
const end = selection.end;
175-
textInserter.replace(new Range(start, end), text);
176-
}
177-
}
178-
});
179-
180-
action.then((wasApplied) => {
181-
const fileURI = editor.document.uri.toString();
182-
if (wasApplied && fileURI.endsWith(".java")) {
183-
const hasText: boolean = documentText !== null && /\S/.test(documentText);
184-
if (hasText) {
185-
// Organize imports silently to avoid surprising the user
186-
commands.executeCommand(Commands.ORGANIZE_IMPORTS_SILENTLY, fileURI);
187-
} else {
188-
commands.executeCommand(Commands.ORGANIZE_IMPORTS, { textDocument: { uri: fileURI } });
189-
}
190-
}
191-
});
192-
}));
193-
194-
pasteSubscriptionIndex = length - 1;
195-
languageClient.info(`Registered 'java.${ORGANIZE_IMPORTS_ON_PASTE}' command.`);
196-
}
197-
198-
export function unregisterOverridePasteCommand(languageClient: LanguageClient, context: ExtensionContext) {
199-
if (pasteSubscriptionIndex !== null) {
200-
const pasteDisposable: Disposable = context.subscriptions[pasteSubscriptionIndex];
201-
pasteDisposable.dispose();
202-
pasteSubscriptionIndex = null;
203-
languageClient.info(`Unregistered 'java.${ORGANIZE_IMPORTS_ON_PASTE}' command.`);
204-
}
205-
}

test/extension.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ suite('Java Language Extension', () => {
5454
Commands.GENERATE_DELEGATE_METHODS_PROMPT,
5555
Commands.APPLY_REFACTORING_COMMAND,
5656
Commands.RENAME_COMMAND,
57-
Commands.NAVIGATE_TO_SUPER_IMPLEMENTATION_COMMAND
57+
Commands.NAVIGATE_TO_SUPER_IMPLEMENTATION_COMMAND,
58+
Commands.CLIPBOARD_ONPASTE
5859
];
5960
const foundJavaCommands = commands.filter((value) => {
6061
return JAVA_COMMANDS.indexOf(value)>=0 || value.startsWith('java.');

0 commit comments

Comments
 (0)