为什么写?
由于工作需要,正在学Antlr,自然作者写的那本经典《The Definitive ANTLR 4 Reference》是必读的。边读边写代码是程序员的常规看书姿势,我也不例外。不过习惯IDE了(Antlr每次都生成一堆堆代码,IDE下看还是不错的),来回命令行和IDE切换很是费事,所以打起了命令行下交互式菜单的主意。可惜google了一圈,没现成的。好吧,那就撸起袖子做一个吧。
项目在github上,有兴趣的可以看下,或者直接一起撸
准备实现的功能
基本信息的显示
参数名称(别名)
参数描述
回调(关键,不然谈啥交互)
输入校验
退出前整体有效性校验
流程管理 (看下面的流程图)
按需刷新菜单
注解(@annotation)的方式配置(简化使用是王道)(TODO)
命名规范(Naming Convention):这个比注解更是无侵入(只要是Bean规范的即可)(TODO)
2018/08/10 Update: field+setter的简单实现(暂不支持继承、非String参数)
格式化(太丑的估计没人用吧)(TODO)
Debug模式(对开发必须友好)(TODO)
流程
Sample
Bean based builder
2018-08-10更新
运行BeanBuilderSample.java,按照下面的输入,可以得到相应的输出:
Wrong arguments: -null: [Invalid_value] Only 'Csv' is acceptable! 1) -,--grammar [] 2) -,--startRule [token] -- R): refresh menu; X): exitYour input [# value]: 1 CsvYour input [# value]: R 1) -,--grammar [Csv] 2) -,--startRule [token] -- R): refresh menu; X): exitYour input [# value]: xBack 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; } }
全手工配置
运行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; } }
链式调用
2018-08-11 更新
运行ChainedBuilderExample.java,可得到同BasicBuilderExample.java相同的输出。具体调用代码如下:
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( // 链式调用补上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."); } }
作者:朱和
链接:https://www.jianshu.com/p/8920df1f5123
共同学习,写下你的评论
评论加载中...
作者其他优质文章