Idea插件-自定义提示插件部分 Java版 第一部分

前段时间搞AI代码提示的Idea插件。

我整理了一下idea插件部分的代码,包括监听用户触发调用代码提示、代码提示回显、使用tab采纳,使用esc取消提示等功能。

第一部分 插件监听器

首先,要创建一个监听器,用来监听用户行为。创建一个Listener。(还有很多idea内置的监听器,但我用了ProjectManagerListener )

public class EditorEventListener implements ProjectManagerListener {
	 public void projectOpened(@NotNull Project project) {
	 	//在该位置写入监听的事件
	 }
}

创建完成Listener后,还是需要在插件配置文件plugin.xml中配置监听。

        <listener class="你创建监听器包的位置.EditorEventListener "
                  topic="com.intellij.openapi.project.ProjectManagerListener">
        </listener>

在监听的事件中,我使用了监听光标位置变化、监听文档内容变化、监听用户是否输入结束,这三个监听方式。

下面是监听光标位置和位置变化:

        EditorFactory.getInstance().getEventMulticaster().addSelectionListener(new SelectionListener() {
            @Override
            public void selectionChanged(@NotNull SelectionEvent event) {
                // 获取光标所在行
                CursorEditorEvent.onCursorEditorEvent(event);
            }
        }, project);
        // 监听光标位置变化
        EditorFactory.getInstance().getEventMulticaster().addCaretListener(new CaretListener() {
            @Override
            public void caretPositionChanged(@NotNull CaretEvent event) {
                // 光标位置发生变化
                int line = event.getNewPosition().line;
                int column = event.getNewPosition().column;
               //LOG.info("Caret position changed: line " + line + ", column " + column);
            }
        }, project);

下面是监听文档内容变化:

 EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentListener() {
            @Override
            public void beforeDocumentChange(@NotNull DocumentEvent event) {
                // 文档修改即将发生(暂时没用)
            }
            // 文档修改已经发生
            @Override
            public void documentChanged(@NotNull DocumentEvent event) {
                // 文档修改已经发生
                //LOG.info("Document changed: " + event.getNewFragment());

            }
        }, project);

理论上使用监听用户文档变化就可以作为触发,调用AI续写模型。但只要写一个字或者一个字母他就会调用一次,这个对AI模型的压力过大,也有太多浪费和没必要的请求。所有就有了接下来监听用户是否输入结束(也不是完全能精准监控到用户是否完成,而是在一定时间内,来判读用户是否结束输入了)

     //监听用户是否输入结束
        EditorFactory.getInstance().addEditorFactoryListener(new EditorFactoryListener() {
            @Override
            public void editorCreated(@NotNull EditorFactoryEvent event) {
                Editor editor = event.getEditor();

                Caret primaryCaret = editor.getCaretModel().getPrimaryCaret();
                //添加文档监听器
                editor.getDocument().addDocumentListener(new DocumentListener() {
                    private TimerTask currentTask;

                    @Override
                    public void documentChanged(@NotNull DocumentEvent event) {
                        if (currentTask != null) {
                            currentTask.cancel();
                        }
                        currentTask = new TimerTask() {
                            @Override
                            public void run() {
                                // 输入结束后的逻辑
                                //LOG.info("Input ended!");
                            }
                        };
                        timer.schedule(currentTask, INPUT_IDLE_DELAY_MS);
                    }
                });
            }

            @Override
            public void editorReleased(@NotNull EditorFactoryEvent event) {
            }
        }, project);

完整部分:

public class EditorEventListener implements ProjectManagerListener {
  private static final Logger LOG = Logger.getInstance(EditorEventListener.class);
  private final Timer timer = new Timer();
  //对输入的延迟处理的时间
  private static final long INPUT_IDLE_DELAY_MS = 500;


@Override
    public void projectOpened(@NotNull Project project) {

        /**
         * 监听光标位置变化
         */
        EditorFactory.getInstance().getEventMulticaster().addSelectionListener(new SelectionListener() {
            @Override
            public void selectionChanged(@NotNull SelectionEvent event) {
                // 获取光标所在行
                CursorEditorEvent.onCursorEditorEvent(event);
            }
        }, project);
        // 监听光标位置变化
        EditorFactory.getInstance().getEventMulticaster().addCaretListener(new CaretListener() {
            @Override
            public void caretPositionChanged(@NotNull CaretEvent event) {
                // 光标位置发生变化
                int line = event.getNewPosition().line;
                int column = event.getNewPosition().column;
                LOG.info("Caret position changed: line " + line + ", column " + column);

            }
        }, project);

        // 监听文档内容变化
        EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentListener() {
            @Override
            public void beforeDocumentChange(@NotNull DocumentEvent event) {
                // 文档修改即将发生(暂时没用)
            }
            // 文档修改已经发生
            @Override
            public void documentChanged(@NotNull DocumentEvent event) {
                // 文档修改已经发生
                LOG.info("Document changed: " + event.getNewFragment());
          
            }
        }, project);

        //监听用户是否输入结束
        EditorFactory.getInstance().addEditorFactoryListener(new EditorFactoryListener() {
            @Override
            public void editorCreated(@NotNull EditorFactoryEvent event) {
                Editor editor = event.getEditor();

                Caret primaryCaret = editor.getCaretModel().getPrimaryCaret();
                //添加文档监听器
                editor.getDocument().addDocumentListener(new DocumentListener() {
                    private TimerTask currentTask;

                    @Override
                    public void documentChanged(@NotNull DocumentEvent event) {
                        if (currentTask != null) {
                            currentTask.cancel();
                        }
                        currentTask = new TimerTask() {
                            @Override
                            public void run() {
                                // 输入结束后的逻辑
                                LOG.info("Input ended!");
                                //监听用户短时间不在操作后的逻辑
                            }
                        };
                        timer.schedule(currentTask, INPUT_IDLE_DELAY_MS);
                    }
                });
            }

            @Override
            public void editorReleased(@NotNull EditorFactoryEvent event) {
            }
        }, project);

        // 监听文件编辑器选择变化(暂时没用)
        project.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerListener() {
            @Override
            public void selectionChanged(@NotNull FileEditorManagerEvent event) {
                VirtualFile newFile = event.getNewFile();
                if (newFile != null) {
                    LOG.info("File selection changed: " + newFile.getName());
                }
            }
        });
    }
}

其中使用TimerTask,来创建在主流程之外新的线程来执行,也用来监控用户在INPUT_IDLE_DELAY_MS时间内没有任何操作后,再请求续写模型。用新的线程来执行的时候,不会形象用户正常的输入操作,否则在idea插件的主线程上会形象到用户输入,如果你的后续操作时间很少或者忽略不计,可以在主线程上,但我使用的AI模型的效率比较差,所以为了用户使用插件的感受,我使用了这个。如果有大佬还有其他想法,咱们可以交流一下。

以上就是插件监听器部分的代码,我直接copy的自己工程的代码,可能有遗留的参数,可以留言,我到时候再去整理一下。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万千之喜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值