monaco-editor不提供全局搜索,只提供单个文件内的搜索,那么如何实现全局搜索呢?
环境:Nodejs + React + Dva + monaco-editor + react-monaco-editor + antd
一、绑定快捷键
调用editor.addCommand方法绑定快捷键,通过monaco.KeyMod和monaco.KeyCode选择快捷键
快捷键要在编辑器创建完成时创建,故这段代码要写在editorDidMount里面
全局搜索要有一个搜索框供输入关键字,故在触发快捷键的时候让搜索框显示,默认是不显示。代码如下:
1 | editorDidMount = (editor, monaco) => { |
二、搜索框实现
搜索框样式主要看自己的需求,我这里只写个简单的搜索框
如何实现搜索框根据内容多少滚动显示列表是我们要考虑的一个问题,经过一番搜索,我锁定了react-infinite-scroller,通过InfiniteScroll API实现滚动下拉效果。代码如下:
1 | <div style={{height:'400px', overflow:'auto'}}> |
三、关键字搜索功能
monaco-editor不提供全局搜索功能,如果要在monaco-editor基础上实现全局搜索,我们可以借助单个文件的搜索功能,然后遍历业务系统的所有文件,对每个文件的搜索结果进行汇总实现全局搜索。
这里需要考虑几个问题:
(1) monaco-editor单个文件搜索是基于创建model的基础上,而通过编辑器点击打开某个文件时才会创建model,我们怎么能获取业务系统所有文件的model?
(2) 业务系统有.git,node_modules等不需要遍历的文件,还有文件夹里的子文件夹及子文件,那么如何实现遍历?
首先针对第一个问题做出解答:
如果对monaco-editor没有经过一番研究可能不会发现这个规律,通过查看官网的api,发现monaco-editor提供createModel方法,我们可以手动创建model
针对第二个问题做出解答
其实.git ,node_modules文件很好排除,只要遍历的时候加个if判断就行;
遍历到文件夹时,我们可以通过nodejs提供的fs.Stats类里面的isDirectory()方法判断,如果是文件夹,就进入文件夹里继续遍历,这里用到递归遍历
在单个文件中搜索关键字可以使用model.findMatches(keyword)实现
再建一个全局的变量用于保存遍历到的结果就行。
代码如下:
1 | let result = new Map(); |
四、搜索结果列表展示
先看效果图
在展示列表中,我们希望看到关键字所在的文件名,行号,甚至是路径,只要我们保存展示结果时将这些信息都保存进去,然后react渲染时渲染出来,代码如上面arr变量所示
五、关键字高亮显示
在上图我们可以看到展示结果中所有的登录关键字都是黄色背景显示的,这里调用antd的Typography 实现高亮。
代码如下:
1 | // ev为result,全局搜索的结果 |
从代码中可以看出,我这里使用的是字符串截取找到关键字然后给关键字添加
六、goto点击跳转
实现差不多了,怎么能少掉点击展示列跳转到对应文件即编辑器打开对应文件
从标题五可以看出,我给每一行加了onClick点击调用goto方法。
代码如下:
1 | //这里range和model,对应findAllMatches返回结果集合里面对象的range和model属性 |
1 |
|
1 | /** |
1 | /** |
七 全局文件搜索
文件搜索比关键字搜索简单一点,在遍历业务系统时遍历所有文件,将和关键字匹配的所有文件保存到result中, 其他的操作一样
结束
部分源码请到Github上:https://github.com/griabcrh/global-search
到这里就结束了,恭喜你学会了怎么实现全局搜索,如果觉得本问对你有帮助,欢迎关注公众号:java开发高级进阶,get到跟多知识。