写在前面

在很多时候,我们想用一个支持高亮的WEB编辑器来做规则配置、代码编辑等,此时ACE应该是一个不错的选择,简单的用法如下:

<!DOCTYPE html>
<html lang="cn">
<head>
<title>ACE in Action</title>
<style type="text/css" media="screen">
#editor {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
</style>
</head>
<body> <div id="editor">function foo(items) {
var x = "All this is syntax highlighted";
return x;
}</div> <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.3/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
var editor = ace.edit("editor");
editor.setTheme("ace/theme/monokai");
</script>
</body>
</html>

打开这个网页会发现整个网页都是一个编辑器,不过此时没有任何高亮效果,需要自己来编辑(当然大部分情况下可以用现成的)。

个性化

在ACE中设置个性化时需要考虑三个方面:

  1. 高亮
  2. 折叠
  3. 缩进
  4. 代码提示

这三块在ACE中保存在一个Mode中,这里是一个JavaScript的例子,如果想在代码中使用那么需要:

editor.getSession().setMode("ace/mode/javascript");

那么接下来的任务就是学习如何设置了。

高亮

在ACE中通过状态机来配置高亮,而高亮的实现则是将文本放在<span class="ace_token_name">标签中,文字展示成什么样子可以自己来进行修改:

执行过程中不断地从当前状态的规则集中找到匹配的regex,之后会跳转到next状态,如果要将多个token合并处理可以用merge:true来实现。在大部分的语言中有N多的关键字,如果一个一个写的话会比较辛苦,此时可以考虑使用createKeywordMapper来做。在ACE中没有Drools现成的模板,自己定义一个如下:

ace.define("ace/mode/drools_highlight_rules", function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var DroolsHighlightRules = function(){
var keywordMapper = this.createKeywordMapper({
"keyword":
"when|then|rule|end|salience"
}, "identifier");
this.$rules = {
"start" :[{
token : keywordMapper,
regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
}]
};
};
oop.inherits(DroolsHighlightRules, TextHighlightRules);
exports.DroolsHighlightRules = DroolsHighlightRules;
}); ace.define("ace/mode/drools", function(require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var DroolsHighlightRules = require("./drools_highlight_rules").DroolsHighlightRules;
var DroolsMode = function(){
this.HighlightRules = DroolsHighlightRules;
};
oop.inherits(DroolsMode, TextMode);
(function() {
this.$id = "ace/mode/drools"
}).call(DroolsMode.prototype),
exports.Mode = DroolsMode;
});

在HTML代码中引入写的文件(当然也可以使用require来做),如果想要关键字加粗在页头加入.ace_keyword{font-weight:bold}即可,效果如下:

这里有一个完整的JSON的高亮配置。

缩进

自定义缩进是通过自定义Mode中的getNextLineIndent方法来实现的,如果要实现类似C/C++/JAVA这种在后面有{的时候下面缩进,那么加上下面这段即可:

	(function(){
this.getNextLineIndent = function(state, line, tab) {// 状态、当前行、缩进符号
var indent = this.$getIndent(line);
if (state == "start") {
var match = line.match(/^.*[\{\(\[]\s*$/); // 如果是{[(结尾的,那么下一行的缩进加一
if (match) {
indent += tab;
}
}
return indent;
};
}).call(DroolsMode.prototype);

每次有新的一行产生getNextLineIndent的返回值会被放在前面,从而形成缩进的效果。

折叠

在ACE中定义了一个对象Range用来标记范围:new Range(Number startRow, Number startColumn, Number endRow, Number endColumn)。其中:

  1. startRow、startColumn:开始位置。
  2. endRow、endColumn:结束位置。

那么在实现折叠方法的时候只要实现两个方法即可:getFoldWidget(折叠开始的地方)和getFoldWidgetRange(折叠范围),在drools中比较简单的一种折叠是将rule....end之间的部分隐藏掉,那么可以创建一个FoldMode如下:

ace.define("ace/mode/folding/drools_fold", function(require, exports, module) {
"use strict";
var Range = require("../../range").Range;
var FoldMode = exports.FoldMode = function() {};
(function() {
this.getFoldWidget = function(session, foldStyle, row) {
var line = session.getLine(row);
if (line == "rule")
return "start";
return "";
};
this.getFoldWidgetRange = function(session, foldStyle, row) {
var startRow = row, startColumn = 4;
var endRow = row+1, endColumn = 3;
while(session.getLine(endRow) != "end"){
endRow += 1;
}
return new Range(startRow, startColumn, endRow, endColumn);
};
}).call(FoldMode.prototype);
});

然后要让其生效的话需要drools对应的总Mode中设置其为foldingRules即可,如下:

var DroolsFoldMode = require("ace/mode/folding/drools_fold").FoldMode;
var DroolsMode = function(){
this.foldingRules = new DroolsFoldMode();
};

在ace中提供了一个基本的折叠模块:fold_mode支持折叠相同的缩进部分等,如果需要直接继承即可。

代码提示

----- update -----

用ACE来写代码的更多相关文章

  1. 使用 .NET WinForm 开发所见即所得的 IDE 开发环境,实现不写代码直接生成应用程序

    直接切入正题,这是我09年到11年左右业余时间编写的项目,最初的想法很简单,做一个能拖拖拽拽就直接生成应用程序的工具,不用写代码,把能想到的业务操作全部封装起来,通过配置的方式把这些业务操作组织起来运 ...

  2. ClownFish:比手写代码还快的通用数据访问层

    http://www.cnblogs.com/fish-li/archive/2012/07/17/ClownFish.html 阅读目录 开始 ClownFish是什么? 比手写代码还快的执行速度 ...

  3. Markdown: 用写代码的思维写文档

    作者:吴香伟 发表于 2014/08/07 版权声明:可以任意转载,转载时务必以超链接形式标明文章原始出处和作者信息以及版权声明 本文不讲解Markdown的语法规则,只关注它带来的好处以及我使用的方 ...

  4. 【腾讯Bugly干货分享】深入理解 ButterKnife,让你的程序学会写代码

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/578753c0c9da73584b025875 0.引子 话说我们做程序员的,都 ...

  5. 不需要写代码,文件夹右键cmd定位指定目录

    引子 这篇文章其实本来不是这样的,因为我用C#的代码实现了一个程序,后面才突然发现,我太傻太天真了,明明不需要写程序和写代码的,结果自己把自己二住了. 我们来看看效果图. 由于,我自己的原因,这个功能 ...

  6. [No000008]发工资不仅仅是让你写代码的

    这是我对团队每个新进员工说的第一件事情.这句话的意思是,我并不关心你是如何快速完成任务的,哪怕代码很差,只要它像救生艇通气门一样管用就行.这句话也是我最喜欢的座右铭之一. 这个说法其实很合理:我们的工 ...

  7. 手写代码自动实现自动布局,即Auto Layout的使用

    手写代码自动实现自动布局,即Auto Layout的使用,有需要的朋友可以参考下. 这里要注意几点: 对子视图的约束,若是基于父视图,要通过父视图去添加约束. 对子视图进行自动布局调整,首先对UIVi ...

  8. jQuery 之父:每天写代码

    去年秋天我的支线代码项目 遇到了一些问题,项目进展不足,而且我没法找到一个完成更多代码的方法(在不影响我在Khan Academy方面的工作的前提下). 我主要在周末进行我的支线,当然有时候也在晚上进 ...

  9. 如果选择构建ui界面方式,手写代码,xib和StoryBoard间的博弈

    代码手写UI这种方法经常被学院派的极客或者依赖多人合作的大型项目大规模使用. 大型多人合作项目使用代码构建UI,主要是看中纯代码在版本管理时的优势,检查追踪改动以及进行代码合并相对容易一些. 另外,代 ...

随机推荐

  1. WP评论系统更换小结(转)

    第三方评论插件 多说 多说是一款追求极致体验的社会化评论框,可以用微博.QQ.人人.豆瓣等帐号登录并评论. 多说具备优质用户体验.速度和稳定性.社会化推荐.建站程序审核整合.垃圾评论过滤等特性. 自定 ...

  2. JDBC连接执行mysql存储过程报权限错误:User does not have access to metadata required to determine stored procedure parameter types. If rights can not be granted,

    分析:JDBC在调用存储过程时不光用户要有execute的权限,还需要对mysql.proc具有访问权限.否则它无法访问metadata 解决方案:给数据库用户赋权,赋执行mysql.proc表的se ...

  3. 最短路-Floyd

    简介: 算法的特点:  弗洛伊德算法是解决任意两点间的最短路径的一种算法,可以正确处理有向图或有向图或负权(但不可存在负权回路)的最短路径问题,同时也被用于计算有向图的传递闭 包. 算法思想: 通过F ...

  4. QTextCodec中的setCodecForTr等终于消失了 (Qt5)

    原文请看:http://www.cnblogs.com/lexus/archive/2012/05/01/2478150.html QT牛博 QTextCodec中的setCodecForTr等终于消 ...

  5. 洛谷P1120 小木棍 [搜索]

    题目传送门 题目描述乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50. 现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度. 给出每段小木棍 ...

  6. STM32通用定时器实现LED灯闪烁

    刚才看了一下STM32通用定时器的教程,其实和51的定时器使用差不多.只是因为32的时钟更复杂,可操控的寄存器更多,所以写的时候可能更复杂. 使用通用定时器中断的一般步骤:1.使能定时器时钟 这个需要 ...

  7. go chapter 7 - 类型

    任意类型 interface{} 遍历并判断类型 func MyPrintf(args ...interface{}) { for _, arg := range args { switch arg. ...

  8. 07.C#中如何排除/过滤/清空/删除掉字符串数组中的空字符串

    方式一:使用lambda表达式筛选过滤掉数组中空字符串         1 /// <summary> /// 使用lambda表达式排除/过滤/清空/删除掉字符串数组中的空字符串 /// ...

  9. 【BZOJ 1815】【SHOI 2006】color 有色图

    http://www.lydsy.com/JudgeOnline/problem.php?id=1815 这道题好难啊,组合数学什么根本不会啊qwq 题解详见08年的Pólya计数论文. 主要思想是只 ...

  10. 【tarjan+缩点】POJ1236[IOI1996]-Network of Schools

    [题意] 见:http://blog.csdn.net/ascii991/article/details/7466278 [思路] 缩点+tarjan,思路也可以到上面的博客去看.(吐槽:这道题其实我 ...