codemirror 5前端代码编辑器资料整理。

news/2024/7/2 23:29:14

CodeMirror 是基于js的源代码编辑器组件,它支持javascript等多种高级语言,tampermonkey内置的代码编辑器就是基于它。它的按键组合方式兼容vim,emacs等,调用者还可自定义”自动完成“的列表窗口,自由度极高,相当成熟。

但是这个库也是问题多多,很需要深度配置、改良优化。

前排提示:由于信息闭塞,所以才研究了 codemirror 5。研究完才发现, codemirror 5官方基本处于弃坑状态,issue没人理。最新版本是 codemirror 6,仍在开发当中,但各方面效果已经,明显优于 codemirror 5。

0. 入门

入门很简单,可以F12观察官方demo是怎么实现的:

https://codemirror.net/ (codemirror 6

https://codemirror.net/examples/

https://codemirror.net/5/

关键代码:

<!-- Create a simple CodeMirror instance -->
<link rel="stylesheet" href="lib/codemirror.css">
<script src="lib/codemirror.js"></script>
<script>
  var editor = CodeMirror.fromTextArea(myTextarea, {
    lineNumbers: true
  });
  v
</script>

官方demo都是直接运行在文档页面上的。而且在编辑框内,显示的是demo自身的代码。有许多这样的小例子。

附本地运行方式:

  1. 从GitHub下载整个仓库,里面有些(比如核心库codemirror.js)是需要编译后才能运行,但有些就是普通的js代码(比如各种addon、mode),以及样式文件 codemirror.css。
  2. 从cdn或官方的demo示例中查找核心库地址:codemirror.js,这虽然是多模块编译出来的,但未经混淆,直接用vscode阅读修改并无不可,甚至效率更高。
  3. 编辑并预览 demo.html。

1. 需求:用任意键触发自动完成

https://stackoverflow.com/questions/13744176/codemirror-autocomplete-after-any-keyup

关键代码:

editor.on("keyup", function (cm, event) {
//  …… 判断条件,过滤一些按键,过滤某些上下文情况。
            CodeMirror.commands.autocomplete(cm, null, {completeSingle: false});
    });

如果只要ctrl+space触发自动完成的话,是这样配置的:

var editor=CodeMirror.fromTextArea(document.getElementById("code"),{
		……
		, extraKeys:{"Ctrl-Space":"autocomplete"}
		// 或者 :
		, extraKeys:{"Ctrl-Space":'Ctrl-Space': (cm) => 				 
			{
				cm.showHint()
			}}
		}	
	});

2. 让自动完成窗口同时 ① 包含 buffer 中提取的上下文关键词(anyword)②包含 javascript 语言的关键词。

https://discuss.codemirror.net/t/anyword-hinting-while-in-javascript-mode/1506/7

关键代码:

	function hintingFunction(cm) {
		const anyhint = CodeMirror.hint.anyword(cm, options)
		const jshint = CodeMirror.hint.javascript(cm, options)
		const words = new Set([...anyhint.list, ...jshint.list])
		if (words.size > 0) {
			return {
				list: Array.from(words), 
				from: jshint.from, 
				to: jshint.to
			}
		}
	}
	
	…… { completeSingle: false, hint: hintingFunction } …… 

如果只学习官方的短demo:

	CodeMirror.commands.autocomplete = function(cm) {
		CodeMirror.showHint(cm, CodeMirror.hint.anyword);
	}

,这样是不行的,因为只返回了anyword分析出的上下文关键词,导致javascript关键词被覆盖!

而 gpt 给的答案则更是搞笑:

	CodeMirror.commands.autocomplete = function(cm) {
		CodeMirror.showHint(cm, CodeMirror.hint.anyword);
		CodeMirror.showHint(cm, CodeMirror.hint.javascript);
	}

整天瞎编,机器人这会儿的鼻子已经到达银河系中心了吧!

注意需要正确引入 “codemirror5-master/mode/javascript/javascript.js”,不然没有 CodeMirror.hint.javascript(自动完成),还要引入 “codemirror5-master/addon/hint/javascript-hint.js”,不然也没有 mode:"application/javascript" (语法高亮)!

3. 换行回车时,保持原有缩进。

这是 tampermonkey 编辑器最让我不爽的一点:每次在方法之间换行,都把缩进吃了。后来干脆换用vscode + @require file:///本地文件.user.js 的方式,不再用它的内置编辑器。现在,我几乎站在了同一起点,自然要比前辈做得好!

查阅资料后发现,原来“把缩进吃了”是特性,而不是bug,关掉即可:

mode : ……
, smartIndent: false

真是杀马特啊。

可关掉之后,function() { 回车后,就不会自动添加应该有的缩进了,伤脑筋……

最后通过修改 codemirror.js,让杀马特indent只自动增、不自动减:

if (how == "smart") {
	……
	indentation = Math.max(state.indented, indentation);

4. 禁止自动滚动

给安卓用,需要禁止在点击屏幕、设置光标的时候,自动发生横向滚动,以便检阅代码。

复述需求:当移动设备用户检阅代码时,很有可能正在查看长代码行,到触碰到代码行底部时,可能意外导致横向滚动归零。

此功能看起来难于实现,实则很简单:新增options.scrollOnClick,未设置时,不触发 ensureCursorVisible 即可:

  function setSelectionNoUndo(doc, sel, options) {
  	……
	if(doc.cm && doc.cm.options.scrollOnClick) // 不自动触发横向滚动,除非打字。
    if (!(options && options.scroll === false) && doc.cm && doc.cm.getOption("readOnly") != "nocursor")
      { ensureCursorVisible(doc.cm); }
  }

5. 重排自动完成列表,使常用关键词前置化

比如 敲v,自动列表为:

请添加图片描述
不合理。

通过进一步修改上面的 hintingFunction 来完成:

 		if (words.size > 0) {
			var list = Array.from(words);
			console.log(list);
			if(list[0][0]=='v'){
				var varIdx = list.indexOf("var");
				if(varIdx>0) { // 如果关键词 var 排位大于零,则交换。
					var tmp = list[0];
					list[0] = "var";
					list[varIdx] = tmp;
				}
			}
			……

方法简单粗暴,但管用:
请添加图片描述

6. 多文档与编辑状态

像scintilla这种,是一个ui呈现,切换多份不同的文件buffer。

CodeMirror 有所不同,可以从多个 TextArea 创建多份 editor 实例,比较方便。

编辑状态:需要知晓当前文档是否可以:保存、撤销、重做等状态。

↳→→ 查看 文档是否被修改:editor.doc.isClean()

↳→→ 设置 文档已保存:editor.doc.markClean()

查看 当前修改堆栈:editor.doc.history

↳→→→ 分为 : editor.doc.history.done 撤销栈、 editor.doc.history.undone 重做栈,是否读取长度就可以了呢?不行,因为修改文本选择也会算入其中。因此需要筛选出其中的 changes:

请添加图片描述

不关键代码:

		function updatePreview() {
			console.log('编辑器状态 需要保存='+!editor.doc.isClean(), "可撤销="+backable(), "可重做="+forwardable())
		}

7. 实战之实现安卓端 用户脚本编辑器

webview-gm 可以让普通的安卓weview也支持运行用户脚本(如via浏览器)。webview-gm-demo 项目中自带的编辑器就是一个 editortext,可以用 codemirror 改进。

实测在安卓端发现一个比较严重的BUG,如果用 \t 缩进,则用输入法打字的时候,会自动删除 \t 后面打出来的字符,而且是持续化删除,不知如何解决,已在github上反馈问题,顺便帮via浏览器出出名,锦上添花。(android 10 chars got deleted automatically & continuously sometimes #7036)

反馈问题后就睡觉了,第二天还是没消息。无奈只好自己下手。有人可能会问, – "为什么不用空格缩进呢? " – 空格缩进 太乱,有的用四个空格,有的用两个,甚至一个,不规范。而且用 tab 缩进还有一个空格缩进无法比拟的好处:如果需要将输入光标移动至行首,tab缩进的,只需点击第一个 tab 的前半部分即可;而多个空格缩进的,则需要精确点击第一个空格之前才行,实为反人类设计。

这种小问题无非是哪处开关问题。我用肉眼稍微扫描一遍代码,就已经定位问题所在:

option("inputStyle", mobile ? "contenteditable" : "textarea", function () {

通过在editor构造参数中传入 inputStyle : “textarea” 似乎即可解决问题。

然而…… 在 textarea 的编辑方式下,安卓上的文本选择没有了,无法选择代码段,这个bug一样严重。

所以……需要继续研究。需要开启打log模式,通过不断地运行、记录,来摸清代码运行路线,来定位问题症结所在。

最终,发现在 inputStyle : “contenteditable” 的编辑模式下,安卓输入法会将文本输入到 tab 元素之中,而tab元素有个 cm-text 属性,导致新输入的文本被忽略:

    function walk(node) {
      if (node.nodeType == 1) {
        var cmText = node.getAttribute("cm-text");
        if (cmText) {
          addText(cmText);
          return
        }
<span class="cm-tab" role="presentation" cm-text="	">    h</span>

可以看到,tab 元素里面其实还是四个空格,只不过用 cm-text=" " 标明了这其实是一个 \t 符号。可以修改相关代码,取消 cm-text 的遮蔽作用。

令人欣慰的是,codemirror 竟然会检测环境中的变量,比如在 via 浏览器中是这样的:
请添加图片描述
打出来后,似乎还能进一步读取对象的属性!

codemirror 6 更进一步,默认配置就是这样的,融合了anyword hints 与 javascript hints,var关键词也处于首位,而且还有方法模板、关键词双击高亮,更像ide了。

不过 codemirror 6 首页demo里的库是混淆过的,github 仓库里代码很少,不知是怎么一个结构。


http://lihuaxi.xjx100.cn/news/1052859.html

相关文章

【测试开发】第一节.测开入门(附常考面试题)

文章目录 前言 一、什么是测试开发 1.1 常考面试题 二、软件测试的基础概念 2.1 需求 2.2 测试用例 3、BUG 三、生命周期 3.1 软件的生命周期 3.2 软件测试的生命周期 四、软件工程中的几种常见的开发模型 4.1 瀑布模型 4.2 螺旋模型 4.3 增量模型和迭代模型 4.4 敏捷…

基于matlab评估机场监控雷达上 5G 新无线电 (NR) 信号的干扰

一、前言 随着5G NR系统的频率范围超出LTE中使用的频段&#xff0c;频谱管理变得更加复杂。对扩大5G覆盖范围的需求是由更高的数据速率和更低的延迟的好处推动的。新5G基站的实施反过来又推动了了解这些信号如何影响在相同频段上运行的已安装系统的需求。其中一个系统是空中交通…

无线洗地机哪款性价比高?高性价比的洗地机分享

虽说现在市面上清洁工具很多&#xff0c;但是要说清洁效果最好的&#xff0c;肯定非洗地机莫属。它集合了吸&#xff0c;洗&#xff0c;拖三大功能&#xff0c;干湿垃圾一次清理&#xff0c;还能根据地面的脏污程度进行清洁&#xff0c;达到极致的清洁效果&#xff0c;省时省力…

【STM32】基础知识 第五课 C 语言基础知识

【STM32】基础知识 第五课 C 语言基础知识 stdint.h 简介位操作寄存器位赋值 宏定义带参数的宏定义条件编译头文件编译代码条件编译extern 声明 类别名 (typedef)结构体 指针指针使用的常见问题代码规范 stdint.h 简介 stdint.h 是从 C99 中引进的一个标准 C 库的文件. 路径: …

前向传播的简单介绍,并给出代码实例

文章目录 前向传播的介绍前向传播的基本概念前向传播的步骤实例代码示例一代码示例二定义模型定义损失函数定义优化器执行前向传播 总结 前向传播的介绍 前向传播是神经网络中的一种基本操作&#xff0c;其作用是将输入数据通过网络中的权重和偏置计算&#xff0c;最终得到输出…

编程能力提升:15个步骤助你成为顶尖程序员

目录 1. 学习新的编程语言2. 熟悉代码规范和最佳实践3. 参加开源项目4. 阅读高质量的代码5. 掌握设计模式6. 使用工具和框架7. 学习软件工程知识8. 不断实践和练习9. 参加技术交流和分享10. 注重自我反思和改进11. 熟悉数据结构和算法12. 学习代码调试和优化13. 关注安全和性能…

从广交会,看懂海尔智家逆势增长的秘密

中国企业的全球化战略应从何处、以何种方式推进&#xff1f;作为行业全球化最彻底的企业&#xff0c;海尔智家是个很好的参考。 4月15日&#xff0c;在第133届中国进出口贸易交易会&#xff08;以下简称“广交会”&#xff09;上&#xff0c;海尔智家展示了其扎根本土&#xf…

unity,物理材质2d

介绍 2D物理材质(Physics Material 2D)是Unity中用于设置2D游戏对象的物理特性的一种方式。2D物理材质可以控制2D游戏对象的摩擦力、弹性系数等物理属性&#xff0c;从而影响其在物理引擎中的运动行为。以下是2D物理材质的详细介绍&#xff1a; 方法 摩擦力 2D物理材质的主要…