起因
起因是我一個(gè)叫『小龍』的好基友由于某些原因離職去了一家跟阿里一樣有著『花名文化』的公司裙士,于是開(kāi)始為花名犯愁妈候。
結(jié)合之前妹紙『弍紓』在起花名的時(shí)候也遇到了同樣的困擾敞斋,于是決定用 Node.js 寫個(gè)『一本正經(jīng)亂起花名』的程序碍脏。
準(zhǔn)備
Chinese Random Name
首先起花名的原理就是胡亂隨機(jī)一串字出來(lái)胡亂拼膀钠。
于是準(zhǔn)備應(yīng)該有 chinese-random-name弊琴,一個(gè)隨機(jī)生成中文名的包蛤育。
使用它很簡(jiǎn)單荷逞,先把它 require
進(jìn)來(lái):
const randomName = require("chinese-random-name");
基本用法
如果你需要隨機(jī)生成一個(gè)名字只需要 randomName.generate()
就可以了道伟;如果你要隨機(jī)一個(gè)姓那么就 randomName.surnames.getOne()
迹缀;如果你只需要獲得名字使碾,這里面就有點(diǎn)門道了。
高級(jí)用法
你可以隨機(jī)生成一個(gè)名(不帶姓的) randomName.names.get()
祝懂;你也可以指定名字的字?jǐn)?shù)票摇,一二三:
randomName.names.get1();
randomName.names.get2();
randomName.names.get3();
或者!
又或者砚蓬!
然后或者矢门!
你可以指定每個(gè)字的五行哦!
什么意思呢灰蛙?比如你想給孩子起個(gè)名祟剔,然后孩子命里五行缺金,那么就可以:
randomName.names.get2("金金");
然后你就可能得到一個(gè)『紫銓』摩梧,兩個(gè)字都是屬金的物延。那么如果你孩子姓李,就叫李紫銓仅父;如果孩子姓王叛薯,就叫王紫銓;如果姓愛(ài)新覺(jué)羅笙纤,那么就叫愛(ài)新覺(jué)羅·紫銓耗溜。
有木有想給我裝得這個(gè)逼打個(gè) 82 分呢?剩下的就交給 666 吧省容。(? ??_??)?
Nomnom
這個(gè)包是用來(lái)解析命令行參數(shù)的抖拴。雖然市面上有挺多別的的,比如 commander 等腥椒,不過(guò)我還是最習(xí)慣 nomnom城舞,用稱手了就不想換了。
雖然它的 GitHub Repo 下面有這么一段話寞酿。
Nomnom is deprecated. Check out https://github.com/tj/commander.js, which should have most, if not all of the capability that nomnom had. Thank you!
不過(guò)再怎么說(shuō) nomnom 也是當(dāng)年 substack 大神推薦的啊。(?ω?)
Colorful
這個(gè)包是用來(lái)上色的脱柱。
畢竟五行是有顏色的哇伐弹。
const color = require("colorful");
console.log(color.red("(*/?\*)"));
那么在你的終端就好看到一個(gè)紅色的 (*/?\*)
。
Is Chinese
用來(lái)判斷是不是中文的包榨为。
作為一個(gè)起名的命令行程序,你總得好好傳參才行吧随闺,總不能你隨便傳個(gè)咸鴨蛋??我也好好處理吧。
于是就用 is-chinese 來(lái)判斷某個(gè)字符串是不是純中文龄句。
這個(gè)包是由前阿里小伙伴回论,CNode 站長(zhǎng)唐少寫的。
用起來(lái)也很簡(jiǎn)單分歇,只要 isChinese("什么你要判斷什么")
就可以了。
集合
$ npm install --save -d chinese-random-name
$ npm install --save -d nomnom
$ npm install --save -d colorful
$ npm install --save -d is-chinese
- chinese-random-name: https://github.com/XadillaX/chinese-random-name
- nomnom: https://github.com/harthur/nomnom
- colorful: https://github.com/lepture/colorful
- is-chinese: https://github.com/alsotang/is-chinese
開(kāi)工
其結(jié)果在這里葬燎。
解析命令行參數(shù)
首先效果是這樣的:
$ hua --help
Usage: hua [options]
Options:
-p PREFIX, --prefix PREFIX to specify a prefix.
-s SUFFIX, --suffix SUFFIX to specify a suffix.
-5 WUXING, --five-elements WUXING the file elements (Wuxing) of huaming.
-c COUNT, --count COUNT the count of huaming [10]
使用者可以自己想一個(gè)前綴或者后綴,然后自定義(或者也可以不指定)兩個(gè)字的五行缚甩,以及指定一次性生成多少個(gè)花名谱净。
比如想要生成以 龍
字為前綴的花名擅威,就可以 $ hua --prefix 龍
,得到結(jié)果可以是這樣的:
* 龍幼
* 龍巡
* 龍躬
* 龍仇
* 龍錘
* 龍鎰
* 龍拾
* 龍央
* 龍些
* 龍悠
如果想兩個(gè)字分別所屬金和誰(shuí)裕寨,就可以 $ hua --five-elements 金水
來(lái)起花名:
* 倩娥
* 雀效
* 黍棓
* 姹溶
* 馨沙
* 宮閑
* 裕混
* 俗封
* 綢娥
* 瑞淦
想要得到這樣一個(gè)命令行參數(shù)捻艳,我們可以用 nomnom
來(lái)解決庆猫。
var opts = require("nomnom")
.script("hua")
.option("prefix", {
abbr: "p",
help: "to specify a prefix.",
metavar: "PREFIX"
})
.option("suffix", {
abbr: "s",
help: "to specify a suffix.",
metavar: "SUFFIX"
})
.option("five-elements", {
abbr: "5",
help: "the file elements (Wuxing) of huaming.",
metavar: "WUXING"
})
.option("count", {
abbr: "c",
help: "the count of huaming",
metavar: "COUNT",
default: 10
})
.parse();
上面的這段代碼分別指定了腳本名為 hua
,然后指定了 prefix
/ suffix
/ five-elements
和 count
四個(gè)參數(shù)嘁字,并把解析好的參數(shù)賦值給 opts
變量杉畜。
由于我希望這個(gè)包在通常的 Node.js 下都可以跑,所以沒(méi)有用
let
之類的東西此叠。
花名類
接下去要寫一個(gè)花名類,這個(gè)類不只是可以在 CLI 之中使用猬错,也可以讓別人作為一個(gè)包來(lái)引入茸歧。然后實(shí)際上這個(gè)類就是要對(duì) chinese-random-name
進(jìn)行一個(gè)封裝。
構(gòu)造函數(shù)
var Hua = function(options) {
this.options = options;
// Do something...
};
首先這個(gè) options
就是之前由 nomnom
解析出來(lái)的參數(shù)逢唤,當(dāng)然有些參數(shù)是可選的。
接下去我們要在構(gòu)造函數(shù)也就是 Hua
里面格式化前綴或者后綴(如果有的話)智玻,將他們弄成只有一個(gè)漢字的格式遂唧。
if(options.prefix) {
options.prefix = options.prefix[0];
if(!isChinese(options.prefix)) delete options.prefix;
}
if(options.suffix) {
options.suffix = options.suffix[0];
if(!isChinese(options.suffix)) delete options.suffix;
}
前后綴弄好之后要對(duì)五行進(jìn)行分析了。
如果有前后綴那么忽略五行參數(shù)吊奢。
if(options.prefix && options.suffix) {
delete options["file-elements"];
}
如果有前綴,那么忽略傳進(jìn)來(lái)的五行的第一個(gè)五行召边;如果有后綴那么忽略第二個(gè)字的五行裹驰。
var wuxing = "金木水火土";
.
.
.
} else if(options.prefix) {
options["five-elements"] = options["five-elements"].substr(1, 1);
if(-1 === wuxing.indexOf(options["five-elements"])) {
delete options["five-elements"];
}
} else if(options.suffix) {
options["five-elements"] = options["five-elements"].substr(0, 1);
if(-1 === wuxing.indexOf(options["five-elements"])) {
delete options["five-elements"];
}
}
如果前后綴都沒(méi)有,那么要格式化一下該參數(shù)贞盯,使其僅剩兩個(gè)有效的五行漢字沪饺。
} else {
options["five-elements"] = options["five-elements"].substr(0, 2).split("");
for(var i = 0; i < options["five-elements"].length; i++) {
// 如果是無(wú)效五行或者冰沒(méi)有這個(gè)字的話,隨機(jī)一個(gè)五行出來(lái)
if(-1 === wuxing.indexOf(options["five-elements"][i])) {
options["five-elements"][i] = wuxing[Math.floor(Math.random() * 5)];
}
}
// 字?jǐn)?shù)不夠件余,隨機(jī)來(lái)湊
while(options["five-elements"].length < 2) {
options["five-elements"].push(wuxing[Math.floor(Math.random() * 5)]);
}
options["five-elements"] = options["five-elements"].join("");
}
以上的這些邏輯都寫在構(gòu)造函數(shù)里面遭居,如果想要完整的構(gòu)造函數(shù)可以看 hua
的 hua.js 文件。
生成一個(gè)花名
生成一個(gè)花名其實(shí)就是調(diào)用 randomName.names.get
系列函數(shù)們了端壳。
- 有前后綴:直接返回前綴加后綴枪蘑。
-
有前綴:返回前綴加
get1
。 -
有后綴:返回
get1
加后綴。 -
沒(méi)有前后綴:直接返回
get2
觅捆。
注意:以上情況都會(huì)傳進(jìn)(哪怕是
undefined
)五行參數(shù)栅炒。
所以 generateOne
函數(shù)長(zhǎng)這樣:
Hua.prototype.generateOne = function() {
if(this.options.prefix && this.options.suffix) {
return this.options.prefix + this.options.suffix;
}
if(this.options.prefix) {
debug(this.options["five-elements"]);
return this.options.prefix + randomName.names.get1(this.options["five-elements"]);
}
if(this.options.suffix) {
debug(this.options["five-elements"]);
return randomName.names.get1(this.options["five-elements"]) + this.options.suffix;
}
return randomName.names.get2(this.options["five-elements"]);
};
生成 Count 個(gè)花名
還記得 CLI 的 count
參數(shù)么术羔?因?yàn)闉榱朔奖阋依欤覀兛梢耘可苫跃托枰?Count 個(gè)花名的函數(shù)了寥殖。
實(shí)際上就是一個(gè)循環(huán)調(diào)用 generateOne
的函數(shù)而已涩蜘。
Hua.prototype.generate = function(count) {
if(!count) count = this.options.count || 10;
var result = [];
for(var i = 0; i < count; i++) {
result.push(this.generateOne());
}
return result;
};
CLI 文件
剛剛那個(gè) nomnom
解析就在這個(gè)文件里面,然后接下去就是實(shí)例化一個(gè) Hua
對(duì)象粤策,然后生成 count
個(gè)花名误窖。
var hua = new Hua(opts);
var result = hua.generate();
最后把花名輸出來(lái)就好了。
for(var i = 0; i < result.length; i++) {
console.log(" * " + result[i]);
}
橋豆麻袋柔吼!
說(shuō)好的五行顏色呢吭服?!
好像是的哦艇棕,我們要在輸出之前給 result
上個(gè)色兒沼琉。
遍歷 result
里面的花名每個(gè)字,獲取它的五行屬性打瘪,然后涮上色兒。
chinese-random-name
暴露了字典中每個(gè)字的五行屬性彩扔,只需要賦值一下就好了僻爽。
var dict = require("chinese-random-name").names.dict;
然后逐一對(duì)比。最后對(duì)應(yīng)金木水火土的顏色值分別為:
var definedColors = [
220, 83, 26, 197, 59
];
220 為黃色敦捧,代表金;83 為綠色习瑰,代表木秽荤;26 藍(lán)色代表水;197 紅色代表火王滤;59 灰色代表土。
如果那個(gè)字無(wú)法找到屬性第喳,則不上色踱稍,保持默認(rèn)。
result = result.map(function(name) {
var withColor = "";
for(var i = 0; i < 2; i++) {
for(var j = 0; j < wuxing.length; j++) {
var wx = wuxing[j];
if(wx === " ") {
withColor += name[i];
break;
}
if(dict[wx].indexOf(name[i]) !== -1) {
var color = new Color(name[i]);
color.fgcolor = definedColors[j];
withColor += color.toString();
break;
}
}
}
return withColor;
});
至此我們的 CLI 就寫好了扩淀,最后別忘了在 hua 這個(gè) CLI 文件頂部加上一句話啤挎。
#!/usr/bin/env node
這代表到時(shí)候如果要 ./hua
的時(shí)候這個(gè)腳本是用 Node.js 來(lái)跑的。
收拾
本來(lái)想好好寫篇起花名的牢騷胜臊,結(jié)果不知不覺(jué)寫成了給初心者看的初級(jí)教程了伙判,淚目 ( ??? ? ??? )
不嫌棄的就這么看看吧。
最后這里給出我寫好的這個(gè) hua
程序勒魔。
$ [sudo] npm install -g huaming
然后就能在命令行下面跑了菇曲,跑法上面幾章有介紹過(guò)。它的 Repo 在這里弟胀。
最后希望這個(gè)包在你們起花名的時(shí)候還真有那么一丟丟的用處。