ideanew对象后自动补全_从零开始写文本编辑器(二十八):自动补全(上)

6c0e7454a7216c2b24f7a60348c74594.png

前言

我本没打算这么早就写“自动补全”功能的。

但是在写XML资源编辑时,为了实现自动引用已有资源@string/xxx,需要一个合适的列表来让我选择。这样能防止拼写错误。

也就是说,初衷是为了防止拼写错误,结果分析了性价比,还是上自动补全功能吧。

XML自动补全是一个较大的模块,它分为多个子模块,本篇发稿时,全部模块还远没完成。在本篇中只讲述自动补全的GUI模块,并演示 java 关键字代码补全作结尾。

调研自动补全 Auto Complete

“自动补全”是一个宽泛的说法,具体到代码编辑器,就是“代码补全”,本篇统称为“自动补全”。

自动补全的好处:

  • 自动匹配已知输入字符串,猜测完整字符串
    • 简单如:从首字符开始连续匹配
    • 高级如:不连续匹配
  • 自动弹出选择列表
    • 用简单的 UP/DOWN 按键,浏览选择项
    • 用简单的 ENTER 键,选择补全项,并自动插入光标位置。

“自动补全”的流程图

182c54bf92fe5132b89672b97c8a6493.png

这是一张粗糙的流程图,还有小细节,用代码更直观表述。但在上代码之前,先总体说下功能类。

类清单

2cdf51dc4b272cef535f74926d01a04b.png
  • Complete:补全。提供“补全”的列表数据
  • EatEnter:“吃掉回车”。因为回车符与退出符不同,回车符是可显示字符,当用于确认插入操作时,要主动吃掉。
  • Focus:焦点。当显示弹出菜单列表时,要把焦点交还给编辑器,否则无法持续编辑。
  • FrameCode:代码窗口。这是我个人习惯用Frame前缀表示某窗口类。
  • Insert:插入。完成代码插入,内部记忆了插入的光标位置。
  • ListComplete:补全列表。同Frame一样,List前缀表示它是一个JList,是显示补全数据的容器。
  • Location:位置。它计算出补全列表弹出的坐标x, y位置,让左上角临近光标。
  • PopupMenuComplete:补全弹出菜单。同Frame一样,PopupMenu前缀表示,它是一个JPopupMenu,它是ListComplete的容器,自动处理了 Escape 等逻辑。
  • TextEditor:编辑器。这是不是前些篇中的编辑,它没有行号等功能。只是我在“自动补全”中临时编写的。

OK,全部类就是这些了。

用例:弹出菜单显示补全列表

public 

当用户输入后,侦听到可见字符输入,编辑器从光标处向前搜索已知输入字符串 headString。

为了方便记忆,我把补全字符串分解为:头部(head string)和 尾部(tail string),这是headString命名的由来。

/**

比如:输入'p',则返回 "p"。

然后弹出菜单(此时不可见),开始接收已知字符串,进行匹配。

public 

本篇中匹配数据集为 java 关键字,使用简单的起始字符串匹配。

public 

返回的字符串向量送给列表显示,并默认选中第1项(index=0)。

返回窗口领空后,把焦点还给编辑器(JTextPane textEditor)。

package 

用例:弹出菜单的位置计算

package 

这段逻辑主要是控件坐标API的使用,invoker 的目标容器会影响显示的父位置,进而会影响总的坐标计算,为了灵活性,我不想写“死“,所以只好加注释说明。

Point point = location.getLocation();
popupMenuComplete.show(textEditor, point.x, point.y);  

上述的 show(textEditor, ...,如果把 textEditor换成了窗口等父控件,则显示坐标就会计算偏离。

用例:浏览列表

if 

此处可以写成循环浏览,eclipse 就是可循环浏览,我这里就不复杂化。

用例:取消补全

} else if (keyCode == KeyEvent.VK_ESCAPE) {
    popupMenuComplete.setVisible(false);
    popupMenuComplete.clean();

用例:插入补全

package 

记得要“吃掉回车符”哦!

package 

看看效果

7d6459a0c77782760cb6313baf081ae3.gif

在演示中,好像在第二行处有BUG,in的前缀怎么会出现 if 关键字。这些BUG我后续再迭代修正,本篇主要逻辑就是这些。

这是一个非常粗糙的胶水式模块,后续慢慢会演变成一个自动补全框架。

以上~

参考资料

  • stackoverflow 搜索 "auto complete" 若干文章

工具

  • Gif录制软件:ScreenToGif