用ACE來寫代碼


寫在前面

在很多時候,我們想用一個支持高亮的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 -----


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM