Skip to content

Commit ca07fc8

Browse files
committed
<add>:1、增加手动提示的快捷键[Alt+\];2、取消光标移动的自动提示;3、增加取消提示的快捷键[Esc];4、readme文档内容调整
1 parent 9701018 commit ca07fc8

File tree

9 files changed

+248
-50
lines changed

9 files changed

+248
-50
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ docker run --gpus 'all' --shm-size 1g -p 9090:80 -v $HOME/models:/data \
134134

135135
- 自动触发代码建议
136136

137-
在编码时,当您停止输入时,代码建议将自动触发(可在插件设置中配置延迟时间为1到3秒)
137+
在编码时,当您停止输入时,代码建议将自动触发。
138138

139139
当插件提供代码建议时,建议内容以灰色显示在编辑器光标位置,您可以按下Tab键来接受该建议,或者继续输入以忽略该建议。
140140

README_EN.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ Note: Different model runtime environments can be configured within the plugin.
135135

136136
- Automatic Code Suggestions
137137

138-
During coding, when you stop typing, code suggestions will automatically trigger (configurable with a delay of 1 to 3 seconds in the plugin settings).
138+
During coding, when you stop typing, code suggestions will automatically trigger.
139139

140140
When the plugin provides code suggestions, they are displayed in gray at the editor's cursor location. You can press the Tab key to accept the suggestion or continue typing to ignore it.
141141

build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
}
55

66
group = "com.codeshell.intellij"
7-
version = "0.0.2"
7+
version = "0.0.3"
88

99
repositories {
1010
mavenCentral()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.codeshell.intellij.actions.complete;
2+
3+
import com.codeshell.intellij.utils.CodeGenHintRenderer;
4+
import com.codeshell.intellij.widget.CodeShellWidget;
5+
import com.intellij.openapi.actionSystem.CommonDataKeys;
6+
import com.intellij.openapi.actionSystem.DataContext;
7+
import com.intellij.openapi.editor.Caret;
8+
import com.intellij.openapi.editor.Editor;
9+
import com.intellij.openapi.editor.Inlay;
10+
import com.intellij.openapi.editor.InlayModel;
11+
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
12+
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
13+
import com.intellij.openapi.vfs.VirtualFile;
14+
import org.jetbrains.annotations.NotNull;
15+
import org.jetbrains.annotations.Nullable;
16+
17+
import java.util.Objects;
18+
19+
public class CodeGenEscAction extends EditorWriteActionHandler {
20+
protected final EditorActionHandler handler;
21+
22+
public CodeGenEscAction(EditorActionHandler actionHandler) {
23+
handler = actionHandler;
24+
}
25+
26+
@Override
27+
public void executeWriteAction(@NotNull Editor editor, @Nullable Caret caret, DataContext dataContext) {
28+
cancelCodeCompletion(editor, caret, dataContext);
29+
}
30+
31+
private void cancelCodeCompletion(Editor editor, Caret caret, DataContext dataContext) {
32+
VirtualFile file = dataContext.getData(CommonDataKeys.VIRTUAL_FILE);
33+
if (Objects.isNull(file)) {
34+
return;
35+
}
36+
InlayModel inlayModel = editor.getInlayModel();
37+
inlayModel.getInlineElementsInRange(0, editor.getDocument().getTextLength()).forEach(this::disposeInlayHints);
38+
inlayModel.getBlockElementsInRange(0, editor.getDocument().getTextLength()).forEach(this::disposeInlayHints);
39+
CodeShellWidget.enableSuggestion = false;
40+
}
41+
42+
private void disposeInlayHints(Inlay<?> inlay) {
43+
if (inlay.getRenderer() instanceof CodeGenHintRenderer) {
44+
inlay.dispose();
45+
}
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package com.codeshell.intellij.actions.complete;
2+
3+
import com.codeshell.intellij.services.CodeShellCompleteService;
4+
import com.codeshell.intellij.utils.CodeShellUtils;
5+
import com.codeshell.intellij.utils.EditorUtils;
6+
import com.codeshell.intellij.widget.CodeShellWidget;
7+
import com.intellij.codeInsight.intention.IntentionAction;
8+
import com.intellij.codeInspection.util.IntentionFamilyName;
9+
import com.intellij.codeInspection.util.IntentionName;
10+
import com.intellij.openapi.actionSystem.AnActionEvent;
11+
import com.intellij.openapi.actionSystem.CommonDataKeys;
12+
import com.intellij.openapi.application.ApplicationManager;
13+
import com.intellij.openapi.diagnostic.Logger;
14+
import com.intellij.openapi.editor.Editor;
15+
import com.intellij.openapi.editor.InlayModel;
16+
import com.intellij.openapi.fileEditor.FileDocumentManager;
17+
import com.intellij.openapi.project.DumbAwareAction;
18+
import com.intellij.openapi.project.Project;
19+
import com.intellij.openapi.vfs.VirtualFile;
20+
import com.intellij.psi.PsiFile;
21+
import com.intellij.util.IncorrectOperationException;
22+
import org.jetbrains.annotations.NotNull;
23+
24+
import java.util.Objects;
25+
import java.util.concurrent.CompletableFuture;
26+
27+
public class CodeTriggerCompletionAction extends DumbAwareAction implements IntentionAction {
28+
29+
@SafeFieldForPreview
30+
private Logger logger = Logger.getInstance(this.getClass());
31+
32+
@Override
33+
@IntentionName
34+
@NotNull
35+
public String getText() {
36+
return "Trigger Completion";
37+
}
38+
39+
@Override
40+
@NotNull
41+
@IntentionFamilyName
42+
public String getFamilyName() {
43+
return "CodeShell";
44+
}
45+
46+
@Override
47+
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
48+
return false;
49+
}
50+
51+
@Override
52+
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
53+
54+
}
55+
56+
@Override
57+
public boolean startInWriteAction() {
58+
return true;
59+
}
60+
61+
@Override
62+
public void actionPerformed(@NotNull AnActionEvent e) {
63+
Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
64+
updateInlayHints(editor);
65+
// Project project = e.getData(LangDataKeys.PROJECT);
66+
// if (Objects.isNull(project)) {
67+
// return;
68+
// }
69+
// ApplicationManager.getApplication().invokeLater(() -> {
70+
// VirtualFile vf = e.getRequiredData(CommonDataKeys.VIRTUAL_FILE);
71+
// Editor editor = e.getRequiredData(CommonDataKeys.EDITOR);
72+
// if (EditorUtils.isNoneTextSelected(editor)) {
73+
// return;
74+
// }
75+
// PsiFile psiFile = e.getRequiredData(CommonDataKeys.PSI_FILE);
76+
// JsonObject jsonObject = EditorUtils.getFileSelectionDetails(editor, psiFile, true, PrefixString.CLEAN_CODE);
77+
// JsonObject result = new JsonObject();
78+
// ToolWindowManager tool = ToolWindowManager.getInstance(project);
79+
// Objects.requireNonNull(tool.getToolWindow("CodeShell")).activate(() -> {
80+
// if(logger.isDebugEnabled()){
81+
// logger.debug("******************* CleanCode Enabled CodeShell window *******************");
82+
// }
83+
// }, true, true);
84+
// jsonObject.addProperty("fileName", vf.getName());
85+
// jsonObject.addProperty("filePath", vf.getCanonicalPath());
86+
// result.addProperty("data", jsonObject.toString());
87+
// (project.getService(CodeShellSideWindowService.class)).notifyIdeAppInstance(result);
88+
// }, ModalityState.NON_MODAL);
89+
}
90+
91+
private void updateInlayHints(Editor focusedEditor) {
92+
if (Objects.isNull(focusedEditor) || !EditorUtils.isMainEditor(focusedEditor)) {
93+
return;
94+
}
95+
VirtualFile file = FileDocumentManager.getInstance().getFile(focusedEditor.getDocument());
96+
if (Objects.isNull(file)) {
97+
return;
98+
}
99+
100+
String selection = focusedEditor.getCaretModel().getCurrentCaret().getSelectedText();
101+
if (Objects.nonNull(selection) && !selection.isEmpty()) {
102+
String[] existingHints = file.getUserData(CodeShellWidget.SHELL_CODER_CODE_SUGGESTION);
103+
if (Objects.nonNull(existingHints) && existingHints.length > 0) {
104+
file.putUserData(CodeShellWidget.SHELL_CODER_CODE_SUGGESTION, null);
105+
file.putUserData(CodeShellWidget.SHELL_CODER_POSITION, focusedEditor.getCaretModel().getOffset());
106+
107+
InlayModel inlayModel = focusedEditor.getInlayModel();
108+
inlayModel.getInlineElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(CodeShellUtils::disposeInlayHints);
109+
inlayModel.getBlockElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(CodeShellUtils::disposeInlayHints);
110+
}
111+
return;
112+
}
113+
114+
Integer codeShellPos = file.getUserData(CodeShellWidget.SHELL_CODER_POSITION);
115+
int currentPosition = focusedEditor.getCaretModel().getOffset();
116+
117+
InlayModel inlayModel = focusedEditor.getInlayModel();
118+
inlayModel.getInlineElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(CodeShellUtils::disposeInlayHints);
119+
inlayModel.getBlockElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(CodeShellUtils::disposeInlayHints);
120+
file.putUserData(CodeShellWidget.SHELL_CODER_POSITION, currentPosition);
121+
CodeShellCompleteService codeShell = ApplicationManager.getApplication().getService(CodeShellCompleteService.class);
122+
CharSequence editorContents = focusedEditor.getDocument().getCharsSequence();
123+
CompletableFuture<String[]> future = CompletableFuture.supplyAsync(() -> codeShell.getCodeCompletionHints(editorContents, currentPosition));
124+
future.thenAccept(hintList -> CodeShellUtils.addCodeSuggestion(focusedEditor, file, currentPosition, hintList));
125+
}
126+
}

src/main/java/com/codeshell/intellij/utils/CodeShellUtils.java

+40-1
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,19 @@
44
import com.codeshell.intellij.constant.PrefixString;
55
import com.codeshell.intellij.model.GenerateModel;
66
import com.codeshell.intellij.settings.CodeShellSettings;
7+
import com.codeshell.intellij.widget.CodeShellWidget;
78
import com.google.gson.Gson;
89
import com.google.gson.JsonObject;
910
import com.intellij.openapi.application.ApplicationInfo;
11+
import com.intellij.openapi.command.WriteCommandAction;
1012
import com.intellij.openapi.diagnostic.Logger;
13+
import com.intellij.openapi.editor.Editor;
14+
import com.intellij.openapi.editor.Inlay;
15+
import com.intellij.openapi.editor.InlayModel;
16+
import com.intellij.openapi.vfs.VirtualFile;
1117
import org.apache.commons.lang3.StringUtils;
1218

19+
import java.util.Objects;
1320
import java.util.regex.Matcher;
1421
import java.util.regex.Pattern;
1522

@@ -87,7 +94,7 @@ public static String parseHttpResponseContentForGPU(CodeShellSettings settings,
8794
return generatedText.replace(PrefixString.RESPONSE_END_TAG, "");
8895
}
8996

90-
public static String getIDEAVersion(String whichVersion) {
97+
public static String getIDEVersion(String whichVersion) {
9198
ApplicationInfo applicationInfo = ApplicationInfo.getInstance();
9299
String version = "";
93100
try {
@@ -102,4 +109,36 @@ public static String getIDEAVersion(String whichVersion) {
102109
return version;
103110
}
104111

112+
public static void addCodeSuggestion(Editor focusedEditor, VirtualFile file, int suggestionPosition, String[] hintList) {
113+
WriteCommandAction.runWriteCommandAction(focusedEditor.getProject(), () -> {
114+
if (suggestionPosition != focusedEditor.getCaretModel().getOffset()) {
115+
return;
116+
}
117+
if (Objects.nonNull(focusedEditor.getSelectionModel().getSelectedText())) {
118+
return;
119+
}
120+
121+
file.putUserData(CodeShellWidget.SHELL_CODER_CODE_SUGGESTION, hintList);
122+
file.putUserData(CodeShellWidget.SHELL_CODER_POSITION, suggestionPosition);
123+
124+
InlayModel inlayModel = focusedEditor.getInlayModel();
125+
inlayModel.getInlineElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(CodeShellUtils::disposeInlayHints);
126+
inlayModel.getBlockElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(CodeShellUtils::disposeInlayHints);
127+
if (Objects.nonNull(hintList) && hintList.length > 0) {
128+
if (!hintList[0].trim().isEmpty()) {
129+
inlayModel.addInlineElement(suggestionPosition, true, new CodeGenHintRenderer(hintList[0]));
130+
}
131+
for (int i = 1; i < hintList.length; i++) {
132+
inlayModel.addBlockElement(suggestionPosition, false, false, 0, new CodeGenHintRenderer(hintList[i]));
133+
}
134+
}
135+
});
136+
}
137+
138+
public static void disposeInlayHints(Inlay<?> inlay) {
139+
if (inlay.getRenderer() instanceof CodeGenHintRenderer) {
140+
inlay.dispose();
141+
}
142+
}
143+
105144
}

src/main/java/com/codeshell/intellij/widget/CodeShellWidget.java

+16-43
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import com.codeshell.intellij.settings.CodeShellSettings;
66
import com.codeshell.intellij.utils.CodeGenHintRenderer;
77
import com.codeshell.intellij.utils.CodeShellIcons;
8+
import com.codeshell.intellij.utils.CodeShellUtils;
89
import com.codeshell.intellij.utils.EditorUtils;
910
import com.intellij.openapi.application.ApplicationManager;
10-
import com.intellij.openapi.command.WriteCommandAction;
1111
import com.intellij.openapi.editor.*;
1212
import com.intellij.openapi.editor.event.*;
1313
import com.intellij.openapi.editor.impl.EditorComponentImpl;
@@ -42,7 +42,7 @@ public class CodeShellWidget extends EditorBasedWidget
4242

4343
public static final Key<String[]> SHELL_CODER_CODE_SUGGESTION = new Key<>("CodeShell Code Suggestion");
4444
public static final Key<Integer> SHELL_CODER_POSITION = new Key<>("CodeShell Position");
45-
45+
public static boolean enableSuggestion = false;
4646
protected CodeShellWidget(@NotNull Project project) {
4747
super(project);
4848
}
@@ -181,6 +181,7 @@ public void caretRemoved(@NotNull CaretEvent event) {
181181

182182
@Override
183183
public void afterDocumentChange(@NotNull Document document) {
184+
enableSuggestion = true;
184185
if (ApplicationManager.getApplication().isDispatchThread()) {
185186
EditorFactory.getInstance().editors(document)
186187
.filter(this::isFocusedEditor)
@@ -190,7 +191,7 @@ public void afterDocumentChange(@NotNull Document document) {
190191
}
191192

192193
private void updateInlayHints(Editor focusedEditor) {
193-
if (Objects.isNull(focusedEditor)) {
194+
if (Objects.isNull(focusedEditor) || !EditorUtils.isMainEditor(focusedEditor)) {
194195
return;
195196
}
196197
VirtualFile file = FileDocumentManager.getInstance().getFile(focusedEditor.getDocument());
@@ -206,8 +207,8 @@ private void updateInlayHints(Editor focusedEditor) {
206207
file.putUserData(SHELL_CODER_POSITION, focusedEditor.getCaretModel().getOffset());
207208

208209
InlayModel inlayModel = focusedEditor.getInlayModel();
209-
inlayModel.getInlineElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(this::disposeInlayHints);
210-
inlayModel.getBlockElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(this::disposeInlayHints);
210+
inlayModel.getInlineElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(CodeShellUtils::disposeInlayHints);
211+
inlayModel.getBlockElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(CodeShellUtils::disposeInlayHints);
211212
}
212213
return;
213214
}
@@ -229,8 +230,9 @@ private void updateInlayHints(Editor focusedEditor) {
229230
}
230231
if (inlineHint.startsWith(modifiedText)) {
231232
inlineHint = inlineHint.substring(modifiedText.length());
233+
enableSuggestion = false;
232234
if (inlineHint.length() > 0) {
233-
inlayModel.getInlineElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(this::disposeInlayHints);
235+
inlayModel.getInlineElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(CodeShellUtils::disposeInlayHints);
234236
inlayModel.addInlineElement(currentPosition, true, new CodeGenHintRenderer(inlineHint));
235237
existingHints[0] = inlineHint;
236238

@@ -239,7 +241,7 @@ private void updateInlayHints(Editor focusedEditor) {
239241
return;
240242
} else if (existingHints.length > 1) {
241243
existingHints = Arrays.copyOfRange(existingHints, 1, existingHints.length);
242-
addCodeSuggestion(focusedEditor, file, currentPosition, existingHints);
244+
CodeShellUtils.addCodeSuggestion(focusedEditor, file, currentPosition, existingHints);
243245
return;
244246
} else {
245247
file.putUserData(SHELL_CODER_CODE_SUGGESTION, null);
@@ -248,47 +250,18 @@ private void updateInlayHints(Editor focusedEditor) {
248250
}
249251
}
250252

251-
inlayModel.getInlineElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(this::disposeInlayHints);
252-
inlayModel.getBlockElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(this::disposeInlayHints);
253+
inlayModel.getInlineElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(CodeShellUtils::disposeInlayHints);
254+
inlayModel.getBlockElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(CodeShellUtils::disposeInlayHints);
253255

254256
file.putUserData(SHELL_CODER_POSITION, currentPosition);
255-
257+
if(!enableSuggestion || currentPosition < lastPosition){
258+
enableSuggestion = false;
259+
return;
260+
}
256261
CodeShellCompleteService codeShell = ApplicationManager.getApplication().getService(CodeShellCompleteService.class);
257262
CharSequence editorContents = focusedEditor.getDocument().getCharsSequence();
258263
CompletableFuture<String[]> future = CompletableFuture.supplyAsync(() -> codeShell.getCodeCompletionHints(editorContents, currentPosition));
259-
future.thenAccept(hintList -> this.addCodeSuggestion(focusedEditor, file, currentPosition, hintList));
260-
}
261-
262-
private void disposeInlayHints(Inlay<?> inlay) {
263-
if (inlay.getRenderer() instanceof CodeGenHintRenderer) {
264-
inlay.dispose();
265-
}
266-
}
267-
268-
private void addCodeSuggestion(Editor focusedEditor, VirtualFile file, int suggestionPosition, String[] hintList) {
269-
WriteCommandAction.runWriteCommandAction(focusedEditor.getProject(), () -> {
270-
if (suggestionPosition != focusedEditor.getCaretModel().getOffset()) {
271-
return;
272-
}
273-
if (Objects.nonNull(focusedEditor.getSelectionModel().getSelectedText())) {
274-
return;
275-
}
276-
277-
file.putUserData(SHELL_CODER_CODE_SUGGESTION, hintList);
278-
file.putUserData(SHELL_CODER_POSITION, suggestionPosition);
279-
280-
InlayModel inlayModel = focusedEditor.getInlayModel();
281-
inlayModel.getInlineElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(this::disposeInlayHints);
282-
inlayModel.getBlockElementsInRange(0, focusedEditor.getDocument().getTextLength()).forEach(this::disposeInlayHints);
283-
if (Objects.nonNull(hintList) && hintList.length > 0) {
284-
if (!hintList[0].trim().isEmpty()) {
285-
inlayModel.addInlineElement(suggestionPosition, true, new CodeGenHintRenderer(hintList[0]));
286-
}
287-
for (int i = 1; i < hintList.length; i++) {
288-
inlayModel.addBlockElement(suggestionPosition, false, false, 0, new CodeGenHintRenderer(hintList[i]));
289-
}
290-
}
291-
});
264+
future.thenAccept(hintList -> CodeShellUtils.addCodeSuggestion(focusedEditor, file, currentPosition, hintList));
292265
}
293266

294267
}

src/main/java/com/codeshell/intellij/window/CodeShellSideWindow.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public synchronized JBCefBrowser jbCefBrowser() {
4242

4343
private JBCefBrowser lazyLoad() {
4444
try {
45-
String ideaVersion = CodeShellUtils.getIDEAVersion("major");
45+
String ideaVersion = CodeShellUtils.getIDEVersion("major");
4646
if (!this.webLoaded) {
4747
boolean isOffScreenRendering = true;
4848
if (SystemInfo.isMac) {

0 commit comments

Comments
 (0)