為什么寫贮尉?
由于工作需要,正在學(xué)Antlr魁蒜,自然作者寫的那本經(jīng)典《The Definitive ANTLR 4 Reference》是必讀的摔刁。邊讀邊寫代碼是程序員的常規(guī)看書姿勢(shì),我也不例外痢甘。不過(guò)習(xí)慣IDE了(Antlr每次都生成一堆堆代碼喇嘱,IDE下看還是不錯(cuò)的),來(lái)回命令行和IDE切換很是費(fèi)事塞栅,所以打起了命令行下交互式菜單的主意者铜∏簧ィ可惜google了一圈,沒(méi)現(xiàn)成的作烟。好吧愉粤,那就擼起袖子做一個(gè)吧。
項(xiàng)目在github上拿撩,有興趣的可以看下衣厘,或者直接一起擼??
準(zhǔn)備實(shí)現(xiàn)的功能
- 基本信息的顯示
- 參數(shù)名稱(別名)
- 參數(shù)描述
- 回調(diào)(關(guān)鍵,不然談啥交互)
- 輸入校驗(yàn)
- 退出前整體有效性校驗(yàn)
- 流程管理 (看下面的流程圖)
- 按需刷新菜單
- 注解(@annotation)的方式配置(簡(jiǎn)化使用是王道)(TODO)
- 命名規(guī)范(Naming Convention):這個(gè)比注解更是無(wú)侵入(只要是Bean規(guī)范的即可)(TODO)
- 2018/08/10 Update: field+setter的簡(jiǎn)單實(shí)現(xiàn)(暫不支持繼承压恒、非String參數(shù))
- 格式化(太丑的估計(jì)沒(méi)人用吧)(TODO)
- Debug模式(對(duì)開發(fā)必須友好)(TODO)
流程
Sample
Bean based builder
2018-08-10更新
運(yùn)行BeanBuilderSample.java影暴,按照下面的輸入,可以得到相應(yīng)的輸出:
Wrong arguments:
-null: [Invalid_value]
Only 'Csv' is acceptable!
1) -,--grammar []
2) -,--startRule [token]
--
R): refresh menu; X): exit
Your input [# value]: 1 Csv
Your input [# value]: R
1) -,--grammar [Csv]
2) -,--startRule [token]
--
R): refresh menu; X): exit
Your input [# value]: x
Back to main, let's continue.
BeanBuilderSample.java的源代碼:
public class BeanBuilderSample {
private String grammar;
private String startRule;
public static void main(final String... args) {
final BeanBuilderSample sample = new BeanBuilderSample();
// mock arguments
final String[] mockedArgs = {"--grammar", "Invalid_value", "--startRule", "token"};
new BeanMenuBuilder().bean(sample).build(mockedArgs).render();
System.out.println("\nBack to main, let's continue.");
}
public void setGrammar(final String value) {
if (!"Csv".equals(value))
throw new IllegalArgumentException("Only 'Csv' is acceptable!");
grammar = value;
}
public void setStartRule(final String value) {
startRule = value;
}
}
全手工配置
運(yùn)行BasicBuilderExample.java探赫,按照下面的輸入型宙,可以得到輸出:
Wrong arguments:
-g: [Invalid_value]
Only 'Csv' is acceptable!
1) -g,--grammar []: Grammar name
2) -,--startRule [token]: Start rule of this parser
--
其他同上
BasicBuilderExample.java的源代碼:
class BasicBuilderSample {
private String grammar;
private String startRule;
public static void main(final String... args) {
final BasicBuilderSample sample = new BasicBuilderSample();
// mock arguments
final String[] mockedArgs = {"-g", "Invalid_value", "--startRule", "token"};
final BasicMenuBuilder builder = new BasicMenuBuilder();
builder
.item(new MenuItemBuilder()
.argName("g")
.longArgName("grammar")
.value(() -> sample.grammar)
.description("It should be same with file name of your .g4")
.inputChecker(sample::setGrammar)
.build()
)
.item(new MenuItemBuilder()
.argName("r").longArgName("startRule")
.value(() -> sample.startRule)
.inputChecker(sample::setStartRule)
.build()
)
.build(mockedArgs)
.render();
System.out.println("\nBack to main, let's continue.");
}
void setGrammar(final String value) {
if (!"Csv".equals(value))
throw new IllegalArgumentException("Only 'Csv' is acceptable!");
grammar = value;
}
void setStartRule(final String value) {
startRule = value;
}
}
鏈?zhǔn)秸{(diào)用
2018-08-11 更新
運(yùn)行ChainedBuilderExample.java,可得到同BasicBuilderExample.java相同的輸出伦吠。具體調(diào)用代碼如下:
public class ChainedBuilderSample {
private String grammar;
private String startRule;
public void setGrammar(final String value) {
if (!"Csv".equals(value))
throw new IllegalArgumentException("Only 'Csv' is acceptable!");
grammar = value;
}
public void setStartRule(final String value) {
startRule = value;
}
public static void main(final String... args) {
final ChainedBuilderSample sample = new ChainedBuilderSample();
// mock arguments
final String[] mockedArgs = {"--grammar", "Invalid_value", "--startRule", "token"};
new BeanMenuBuilder()
.bean(sample) // 從Bean中提取配置
.with( // 鏈?zhǔn)秸{(diào)用補(bǔ)上Bean中缺失的信息妆兑,譬如描述信息
new BasicMenuBuilder()
.item("g", "grammar", "Grammar name")
.item(null, "startRule", "Start rule of this parser")
)
.build(mockedArgs)
.render();
System.out.println("\nBack to main, let's continue.");
}
}
項(xiàng)目在github上,有興趣的可以看下毛仪,或者直接一起擼??