hexo流程梳理之别名注册

hexo 命令注册

hexo构造函数中实例化extend.console,在hexo cli中先注册hexo help version命令

核心的注册逻辑:

1
2
3
4
5
var c = this.store[name.toLowerCase()] = fn;
c.options = options;
c.desc = desc;

this.alias = abbrev(Object.keys(this.store));

abbrev模块

abbrev是Isaac Z. Schlueter 创建的一个handy for command-line scripts, or other cases where you want to be able to accept shorthands.(专门为了处理命令行脚本,或者接受速记)

Isaac Z. Schlueter :npm inventor and CEO. Early contributor and former BDFL of Node.js. Author of many JavaScripts. Been making internets for a pretty long time.
(npm的创造者和CEO)

BDFL:Benevolent Dictator For Life (BDFL) is a title given to a small number of open-source software development leaders, typically project founders who retain the final say in disputes or arguments within the community.
是给少数开源软件开发领导者的标题,类似在社区里有说话权的项目创始人

比如以下几位都是nodejs的贡献者
Ryan Dahl(跟PAAS Heroku 有关)
Isaac Schlueter (在Oakland CA 奥克兰(美国加利福尼亚州西部港市))
Bert Belder (为node提供windows支持的主要开发者)
TJ Holowaychuk (大名鼎鼎的TJ,express,jade的作者)
Tim Caswell (connect的作者)
Felix Geisendörfer ( works on projects node-formidable, node-mysql 在Berlin, Germany (德国柏林))
Mikeal Rogers (request的作者,在旧金山 San Francisco)
Alexis Sellier ( less.js, vows 在柏林)
Jeremy Ashkenas ( CoffeeScript, underscore, backbone, docco 的作者 在纽约 NYC)
Jed Schmidt ( fab.js )
Marak Squires (mostly known for pumping out dozens of node.js libraries per month)
Peteris Krumins ( browserling 在拉脱维亚)
James Halliday ( dnode, optimist and browserify的作者)

abbrev是在注册命令时为了存储别名时用的一个模块,比如输入hexo n的时候hexo会识别出是调用了new命令。就像它在readme.md中所说的Just like ruby’s Abbrev.就像ruby中的Abbrev模块。

Usage:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var store = {

'new' : function(){},
'deploy' : function(){},
'publish': function(){}
};

console.log(Object.keys(store));
//print array
//[ 'new', 'deploy', 'publish' ]

var alias = abbrev(Object.keys(store));

console.log(alias);

//print
console.log(alias);

{ d: 'deploy',
de: 'deploy',
dep: 'deploy',
depl: 'deploy',
deplo: 'deploy',
deploy: 'deploy',
n: 'new',
ne: 'new',
new: 'new',
p: 'publish',
pu: 'publish',
pub: 'publish',
publ: 'publish',
publi: 'publish',
publis: 'publish',
publish: 'publish' }

hexo 命令获取

通过存储在Console实例中的alias字典对象中获取实际的命令Key(alias字典对象就是通过调用abbrev生成的),然后去实际的store对象中获取命令。

核心的获取逻辑:

1
2
3
4
	Console.prototype.get = function(name){
name = name.toLowerCase();
return this.store[this.alias[name]];
};

abbrev源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
function abbrev (list) {
//如果参数不等于1 或者参数list不是数组
//那么就调用Array的slice方法
//返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。
if (arguments.length !== 1 || !Array.isArray(list)) {
//返回新的list数组
list = Array.prototype.slice.call(arguments, 0)
}
//放入args数组
for (var i = 0, l = list.length, args = [] ; i < l ; i ++) {
args[i] = typeof list[i] === "string" ? list[i] : String(list[i])
}

//排序,调用lexSort方法
// sort them lexicographically(按字典顺序), so that they're next to their nearest kin
args = args.sort(lexSort)

// walk through each, seeing how much it has in common with the next and previous
var abbrevs = {}
, prev = ""
for (var i = 0, l = args.length ; i < l ; i ++) {
var current = args[i]
, next = args[i + 1] || ""
, nextMatches = true
, prevMatches = true
if (current === next) continue
//循环结束j要么找到不等于前后的字符 要么就是整个当前字符串
for (var j = 0, cl = current.length ; j < cl ; j ++) {
var curChar = current.charAt(j)
//跟next和prev元素内的字符做比较,如果都不相等,那么就直接跳出这个元素的比较循环
nextMatches = nextMatches && curChar === next.charAt(j)
prevMatches = prevMatches && curChar === prev.charAt(j)
if (!nextMatches && !prevMatches) {
j ++
break
}
}
prev = current//把prev指向当前args元素
if (j === cl) {
abbrevs[current] = current
continue
}
//比如abc a ab abc
for (var a = current.substr(0, j) ; j <= cl ; j ++) {
abbrevs[a] = current
a += current.charAt(j)
}
}
return abbrevs
}

function lexSort (a, b) {
return a === b ? 0 : a > b ? 1 : -1
}

可以尝试写个C#的版本。。

欢迎关注我的公众号:沉迷Spring
显示 Gitment 评论
0%