transform command: help

This commit is contained in:
gongdewei
2020-05-27 11:43:40 +08:00
parent 33175d2f3e
commit a318bbdabe
7 changed files with 380 additions and 33 deletions
@@ -1,5 +1,6 @@
package com.taobao.arthas.core.command.basic1000;
import com.taobao.arthas.core.command.model.*;
import com.taobao.arthas.core.shell.cli.Completion;
import com.taobao.arthas.core.shell.cli.CompletionUtils;
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
@@ -9,24 +10,15 @@ import com.taobao.arthas.core.shell.command.CommandResolver;
import com.taobao.arthas.core.shell.session.Session;
import com.taobao.arthas.core.util.usage.StyledUsageFormatter;
import com.taobao.middleware.cli.CLI;
import com.taobao.middleware.cli.Option;
import com.taobao.middleware.cli.annotations.Argument;
import com.taobao.middleware.cli.annotations.Description;
import com.taobao.middleware.cli.annotations.Name;
import com.taobao.middleware.cli.annotations.Summary;
import com.taobao.text.Color;
import com.taobao.text.Decoration;
import com.taobao.text.Style;
import com.taobao.text.ui.Element;
import com.taobao.text.ui.LabelElement;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
import java.util.ArrayList;
import java.util.List;
import static com.taobao.text.ui.Element.label;
import static com.taobao.text.ui.Element.row;
/**
* @author vlinux on 14/10/26.
*/
@@ -47,16 +39,91 @@ public class HelpCommand extends AnnotatedCommand {
public void process(CommandProcess process) {
List<Command> commands = allCommands(process.session());
Command targetCmd = findCommand(commands);
String message;
if (targetCmd == null) {
message = RenderUtil.render(mainHelp(commands), process.width());
process.appendResult(createHelpModel(commands));
} else {
message = commandHelp(targetCmd, process.width());
process.appendResult(createHelpDetailModel(targetCmd));
}
process.write(message);
process.end();
}
public HelpModel createHelpDetailModel(Command targetCmd) {
return new HelpModel(createCommandVO(targetCmd, true));
}
private HelpModel createHelpModel(List<Command> commands) {
HelpModel helpModel = new HelpModel();
for (Command command : commands) {
if(command.cli() == null || command.cli().isHidden()){
continue;
}
helpModel.addCommandVO(createCommandVO(command, false));
}
return helpModel;
}
private CommandVO createCommandVO(Command command, boolean withDetail) {
CLI cli = command.cli();
CommandVO commandVO = new CommandVO();
commandVO.setName(command.name());
if (cli!=null){
commandVO.setSummary(cli.getSummary());
if (withDetail){
commandVO.setCli(cli);
StyledUsageFormatter usageFormatter = new StyledUsageFormatter(null);
String usageLine = usageFormatter.computeUsageLine(null, cli);
commandVO.setUsage(usageLine);
commandVO.setDescription(cli.getDescription());
//以线程安全的方式遍历options
List<Option> options = cli.getOptions();
for (int i = 0; i < options.size(); i++) {
Option option = options.get(i);
if (option.isHidden()){
continue;
}
commandVO.addOption(createOptionVO(option));
}
//arguments
List<com.taobao.middleware.cli.Argument> arguments = cli.getArguments();
for (int i = 0; i < arguments.size(); i++) {
com.taobao.middleware.cli.Argument argument = arguments.get(i);
if (argument.isHidden()){
continue;
}
commandVO.addArgument(createArgumentVO(argument));
}
}
}
return commandVO;
}
private ArgumentVO createArgumentVO(com.taobao.middleware.cli.Argument argument) {
ArgumentVO argumentVO = new ArgumentVO();
argumentVO.setArgName(argument.getArgName());
argumentVO.setMultiValued(argument.isMultiValued());
argumentVO.setRequired(argument.isRequired());
return argumentVO;
}
private CommandOptionVO createOptionVO(Option option) {
CommandOptionVO optionVO = new CommandOptionVO();
if (!isEmptyName(option.getLongName())) {
optionVO.setLongName(option.getLongName());
}
if (!isEmptyName(option.getShortName())) {
optionVO.setShortName(option.getShortName());
}
optionVO.setDescription(option.getDescription());
optionVO.setAcceptValue(option.acceptValue());
return optionVO;
}
private boolean isEmptyName(String name) {
return name == null || name.equals(Option.NO_NAME);
}
@Override
public void complete(Completion completion) {
List<Command> commands = allCommands(completion.session());
@@ -72,24 +139,6 @@ public class HelpCommand extends AnnotatedCommand {
CompletionUtils.complete(completion, names);
}
private static String commandHelp(Command command, int width) {
return StyledUsageFormatter.styledUsage(command.cli(), width);
}
private static Element mainHelp(List<Command> commands) {
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
table.row(new LabelElement("NAME").style(Style.style(Decoration.bold)), new LabelElement("DESCRIPTION"));
for (Command command : commands) {
CLI cli = command.cli();
// com.taobao.arthas.core.shell.impl.BuiltinCommandResolver doesn't have CLI instance
if (cli == null || cli.isHidden()) {
continue;
}
table.add(row().add(label(cli.getName()).style(Style.style(Color.green))).add(label(cli.getSummary())));
}
return table;
}
private List<Command> allCommands(Session session) {
List<CommandResolver> commandResolvers = session.getCommandResolvers();
List<Command> commands = new ArrayList<Command>();
@@ -0,0 +1,43 @@
package com.taobao.arthas.core.command.model;
/**
* @author gongdewei 2020/4/3
*/
public class ArgumentVO {
private String argName;
private boolean required;
private boolean multiValued;
public ArgumentVO() {
}
public ArgumentVO(String argName, boolean required, boolean multiValued) {
this.argName = argName;
this.required = required;
this.multiValued = multiValued;
}
public String getArgName() {
return argName;
}
public void setArgName(String argName) {
this.argName = argName;
}
public boolean isRequired() {
return required;
}
public void setRequired(boolean required) {
this.required = required;
}
public boolean isMultiValued() {
return multiValued;
}
public void setMultiValued(boolean multiValued) {
this.multiValued = multiValued;
}
}
@@ -0,0 +1,62 @@
package com.taobao.arthas.core.command.model;
/**
* @author gongdewei 2020/4/3
*/
public class CommandOptionVO {
/**
* the option long name.
*/
private String longName;
/**
* the option short name.
*/
private String shortName;
/**
* The option description.
*/
private String description;
/**
* whether or not the option receives a single value or multiple values.
*/
private boolean acceptValue;
public CommandOptionVO() {
}
public String getLongName() {
return longName;
}
public void setLongName(String longName) {
this.longName = longName;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isAcceptValue() {
return acceptValue;
}
public void setAcceptValue(boolean acceptValue) {
this.acceptValue = acceptValue;
}
}
@@ -0,0 +1,94 @@
package com.taobao.arthas.core.command.model;
import com.taobao.middleware.cli.CLI;
import java.util.ArrayList;
import java.util.List;
/**
* @author gongdewei 2020/4/3
*/
public class CommandVO {
//TODO remove cli
private transient CLI cli;
private String name;
private String description;
private String usage;
private String summary;
private List<CommandOptionVO> options = new ArrayList<CommandOptionVO>();
private List<ArgumentVO> arguments = new ArrayList<ArgumentVO>();
public CommandVO() {
}
public CommandVO(String name, String description) {
this.name = name;
this.description = description;
}
public CommandVO addOption(CommandOptionVO optionVO){
this.options.add(optionVO);
return this;
}
public CommandVO addArgument(ArgumentVO argumentVO){
this.arguments.add(argumentVO);
return this;
}
public CLI cli() {
return cli;
}
public void setCli(CLI cli) {
this.cli = cli;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUsage() {
return usage;
}
public void setUsage(String usage) {
this.usage = usage;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public List<CommandOptionVO> getOptions() {
return options;
}
public void setOptions(List<CommandOptionVO> options) {
this.options = options;
}
public List<ArgumentVO> getArguments() {
return arguments;
}
public void setArguments(List<ArgumentVO> arguments) {
this.arguments = arguments;
}
}
@@ -0,0 +1,51 @@
package com.taobao.arthas.core.command.model;
import java.util.ArrayList;
import java.util.List;
/**
* @author gongdewei 2020/4/3
*/
public class HelpModel extends ResultModel {
//list
private List<CommandVO> commands;
//details
private CommandVO detailCommand;
public HelpModel() {
}
public HelpModel(List<CommandVO> commands) {
this.commands = commands;
}
public HelpModel(CommandVO command) {
this.detailCommand = command;
}
public void addCommandVO(CommandVO commandVO){
if (commands == null) {
commands = new ArrayList<CommandVO>();
}
this.commands.add(commandVO);
}
public List<CommandVO> getCommands() {
return commands;
}
public void setCommands(List<CommandVO> commands) {
this.commands = commands;
}
public CommandVO getDetailCommand() {
return detailCommand;
}
@Override
public String getType() {
return "help";
}
}
@@ -0,0 +1,48 @@
package com.taobao.arthas.core.command.view;
import com.taobao.arthas.core.command.model.CommandVO;
import com.taobao.arthas.core.command.model.HelpModel;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.usage.StyledUsageFormatter;
import com.taobao.middleware.cli.CLI;
import com.taobao.text.Color;
import com.taobao.text.Decoration;
import com.taobao.text.Style;
import com.taobao.text.ui.Element;
import com.taobao.text.ui.LabelElement;
import com.taobao.text.ui.TableElement;
import com.taobao.text.util.RenderUtil;
import java.util.List;
import static com.taobao.text.ui.Element.label;
import static com.taobao.text.ui.Element.row;
/**
* @author gongdewei 2020/4/3
*/
public class HelpView extends ResultView<HelpModel> {
@Override
public void draw(CommandProcess process, HelpModel result) {
if (result.getCommands() != null) {
String message = RenderUtil.render(mainHelp(result.getCommands()), process.width());
process.write(message);
} else if (result.getDetailCommand() != null) {
process.write(commandHelp(result.getDetailCommand().cli(), process.width()));
}
}
private static Element mainHelp(List<CommandVO> commands) {
TableElement table = new TableElement().leftCellPadding(1).rightCellPadding(1);
table.row(new LabelElement("NAME").style(Style.style(Decoration.bold)), new LabelElement("DESCRIPTION"));
for (CommandVO commandVO : commands) {
table.add(row().add(label(commandVO.getName()).style(Style.style(Color.green))).add(label(commandVO.getSummary())));
}
return table;
}
private static String commandHelp(CLI command, int width) {
return StyledUsageFormatter.styledUsage(command, width);
}
}
@@ -103,7 +103,7 @@ public class StyledUsageFormatter extends UsageMessageFormatter {
return Style.style(Decoration.bold, fontColor);
}
private String computeUsageLine(String prefix, CLI cli) {
public String computeUsageLine(String prefix, CLI cli) {
// initialise the string buffer
StringBuilder buff;
if (prefix == null) {