Comments 7
UFO just landed and posted this here
да, для Node.JS тоже есть интересная библиотека, — tjholowaychuk.com/post/9103188408/commander-js-nodejs-command-line-interfaces-made-easy
0
«Деревяный API» — это как?
0
Это API не подходящее под желаемый контекст применения.
В случае с Commons-cli потребовалось бы создание большого количества обвязок для получения того, что дает JCommander из-коробки.
Commons-CLI:
JCommander+Guice:
Второй вариант, на мой взгляд, выглядит более дружелюбно, поскольку работа ведется не в стиле процедурного программирования, а объектно — на выходе получаем инициализированный экземпляр Команды которая инкапсулирует свое состояние и поведение.
Конечно в этом примере не указан пример разбора строки через JCommander, основная идея в том, что паттерн Команда не поддерживается в Commons-CLI и такую поддержку нужно делать самостоятельно.
В случае с Commons-cli потребовалось бы создание большого количества обвязок для получения того, что дает JCommander из-коробки.
Commons-CLI:
Options options = new Options();
options.addOption( "a", "all", false, "do not hide entries starting with ." );
options.addOption( "A", "almost-all", false, "do not list implied . and .." );
options.addOption( "b", "escape", false, "print octal escapes for nongraphic "
+ "characters" );
options.addOption( OptionBuilder.withLongOpt( "block-size" )
.withDescription( "use SIZE-byte blocks" )
.hasArg()
.withArgName("SIZE")
.create() );
options.addOption( "B", "ignore-backups", false, "do not list implied entried "
+ "ending with ~");
options.addOption( "c", false, "with -lt: sort by, and show, ctime (time of last "
+ "modification of file status information) with "
+ "-l:show ctime and sort by name otherwise: sort "
+ "by ctime" );
options.addOption( "C", false, "list entries by columns" );
String[] args = new String[]{ "--block-size=10" };
try {
CommandLine line = parser.parse( options, args );
if( line.hasOption( "block-size" ) ) {
// print the value of block-size
System.out.println( line.getOptionValue( "block-size" ) );
}
}
catch( ParseException exp ) {
System.out.println( "Unexpected exception:" + exp.getMessage() );
}
* This source code was highlighted with Source Code Highlighter.
JCommander+Guice:
@Parameters(commandDescription = "Command sample")
@Named("command-sample")
public class CommandSample extends Command {
@Parameter(names = {"-a", "-all"}, description = "do not hide entries starting with ")
protected boolean all;
@Parameter(names = {"-A", "-almost-all"}, description = "do not list implied . and ..")
protected boolean almostAll;
@Parameter(names = {"-b", "-escape"}, description = "print octal escapes for nongraphic characters")
protected boolean escape;
@Parameter(names = {"-B", "-ignore-backups"}, description = "do not list implied entried ending with ~")
protected boolean ignoreBackups;
@Parameter(names = {"-c"}, description = "with -lt: sort by, and show, ctime (time of last \" \n" +
" + \"modification of file status information) with \"\n" +
" + \"-l:show ctime and sort by name otherwise: sort \"\n" +
" + \"by ctime")
protected boolean c;
@Parameter(names = {"-C"}, description = "list entries by columns")
protected boolean C;
@Parameter(names = {"--block-size"}, description = "block size")
protected int blockSize;
@Override
public void execute() throws ExecutionException {
if (blockSize > 0) {
System.out.println(String.valueOf(blockSize));
}
}
}
* This source code was highlighted with Source Code Highlighter.
Второй вариант, на мой взгляд, выглядит более дружелюбно, поскольку работа ведется не в стиле процедурного программирования, а объектно — на выходе получаем инициализированный экземпляр Команды которая инкапсулирует свое состояние и поведение.
Конечно в этом примере не указан пример разбора строки через JCommander, основная идея в том, что паттерн Команда не поддерживается в Commons-CLI и такую поддержку нужно делать самостоятельно.
+1
Второй подход одозначно приятнее.
Но я не вижу там особой поддержки паттерна «команда» — вы вручную написали класс CommandSample с методом execute(). Что мешает обернуть в это же самое первый пример? И будет та самая поддержка, разве нет?
Но я не вижу там особой поддержки паттерна «команда» — вы вручную написали класс CommandSample с методом execute(). Что мешает обернуть в это же самое первый пример? И будет та самая поддержка, разве нет?
0
Чтобы понять где-же там кроется паттерн нужно показать то, как конфигурирется JCommander (это происходит в JCommanderProvider):
Метод addCommand это уже API JCommander-а — мы передаем ему имя команды, созданный экземпляр нашей команды и ее алиасы.
Класс команды должен расширять Object, главное — чтобы в классе поля-параметры были помечены аннотациями @Parameter и имели модификаторы доступа protected/public.
После этого мы выполняем разбор консольного ввода (CLISupport):
commander.addCommand(command.getCommandName(), command, command.getAliases());
Метод addCommand это уже API JCommander-а — мы передаем ему имя команды, созданный экземпляр нашей команды и ее алиасы.
Класс команды должен расширять Object, главное — чтобы в классе поля-параметры были помечены аннотациями @Parameter и имели модификаторы доступа protected/public.
После этого мы выполняем разбор консольного ввода (CLISupport):
//args - ввод с консоли (массив строк полученны путем разбивки строки ввода по пробелам)
JCommander jCommander = injector.getInstance(JCommander.class);
jCommander.parse(args);
List
Почему автор фреймворка не ввел какой нибудь маркерный интерфейс, типа того же Executable или Command я сказать не могу - не знаю, но и с Object-ом все получается достаточно изящно. Самая неизящная часть всего действа находится как раз в CLISupport.
И конечно же, при желании, можно и Commons-CLI довести до подобного уровня.
0
Корректный код разбора ввода с консоли:
//args - ввод с консоли (массив строк полученны путем разбивки строки ввода по пробелам)
JCommander jCommander = injector.getInstance(JCommander.class);
jCommander.parse(args);
List<Object> commands = jCommander.getCommands().get(parsedCommand).getObjects();
for (final Object command : commands) {
if (command instanceof Command) {
// тут у нас полный инициализированный экземпляр Command - осталось только вызвать .execute()
}
}
* This source code was highlighted with Source Code Highlighter.
0
Sign up to leave a comment.
CLI на стероидах: Google Guice и JCommander