package com.github.ompc.greys.core.command;
import com.github.ompc.greys.core.command.annotation.Cmd;
import com.github.ompc.greys.core.command.annotation.IndexArg;
import com.github.ompc.greys.core.command.annotation.NamedArg;
import com.github.ompc.greys.core.server.Session;
import com.github.ompc.greys.core.textui.TTable;
import com.github.ompc.greys.core.util.affect.RowAffect;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Field;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/**
* 帮助明令<br/>
* 这个类的代码丑得一B啊,我都不想看
* <p/>
* Created by oldmanpushcart@gmail.com on 14/10/26.
*/
@Cmd(name = "help", sort = 12, summary = "Display Greys Help",
eg = {
"help",
"help sc",
"help sm",
"help watch"
})
public class HelpCommand implements Command {
@IndexArg(index = 0, isRequired = false, name = "command-name", summary = "Command name")
private String cmd;
@Override
public Action getAction() {
return new RowAction() {
@Override
public RowAffect action(Session session, Instrumentation inst, Printer printer) throws Throwable {
if (isBlank(cmd)
|| !Commands.getInstance().listCommands().containsKey(cmd)) {
printer.print(mainHelp()).finish();
} else {
final Class<?> clazz = Commands.getInstance().listCommands().get(cmd);
printer.print(commandHelp(clazz)).finish();
}
return new RowAffect(1);
}
};
}
private String drawUsage(final Class<?> clazz, final Cmd cmd) {
final StringBuilder usageSB = new StringBuilder();
final StringBuilder sbOp = new StringBuilder();
final StringBuilder sbLongOp = new StringBuilder();
for (Field f : clazz.getDeclaredFields()) {
if (f.isAnnotationPresent(NamedArg.class)) {
final NamedArg namedArg = f.getAnnotation(NamedArg.class);
if (namedArg.name().length() == 1) {
sbOp.append(namedArg.name());
if (namedArg.hasValue()) {
sbOp.append(":");
}
} else {
sbLongOp.append(namedArg.name());
if (namedArg.hasValue()) {
sbLongOp.append(":");
}
}
}
}
if (sbOp.length() > 0) {
usageSB.append("-[").append(sbOp).append("]").append(" ");
}
if (sbLongOp.length() > 0) {
usageSB.append("--[").append(sbLongOp).append("]").append(" ");
}
for (Field f : clazz.getDeclaredFields()) {
if (f.isAnnotationPresent(IndexArg.class)) {
final IndexArg indexArg = f.getAnnotation(IndexArg.class);
usageSB.append(indexArg.name()).append(" ");
}
}
if (usageSB.length() > 0) {
usageSB.append("\n");
}
usageSB.append(cmd.summary());
return usageSB.toString();
}
private String drawOptions(Class<?> clazz) {
final TTable tTable = new TTable(new TTable.ColumnDefine[]{
new TTable.ColumnDefine(15, false, TTable.Align.RIGHT),
new TTable.ColumnDefine(60, false, TTable.Align.LEFT)
});
tTable.getBorder().remove(TTable.Border.BORDER_OUTER);
tTable.padding(1);
// final TKv tKv = new TKv(new TTable.ColumnDefine(20, false, TTable.Align.RIGHT), new TTable.ColumnDefine(50, false, TTable.Align.LEFT));
for (Field f : clazz.getDeclaredFields()) {
if (f.isAnnotationPresent(NamedArg.class)) {
final NamedArg namedArg = f.getAnnotation(NamedArg.class);
final String named = "[" + namedArg.name() + (namedArg.hasValue() ? ":" : "") + "]";
String description = namedArg.summary();
if (isNotBlank(namedArg.description())) {
description += "\n\n" + namedArg.description();
}
tTable.addRow(named, description);
// tKv.add(named, description);
}
}
for (Field f : clazz.getDeclaredFields()) {
if (f.isAnnotationPresent(IndexArg.class)) {
final IndexArg indexArg = f.getAnnotation(IndexArg.class);
String description = indexArg.summary();
if (isNotBlank(indexArg.description())) {
description += "\n\n" + indexArg.description();
}
tTable.addRow(indexArg.name(), description);
// tKv.add(indexArg.name(), description);
}
}
return tTable.rendering();
}
private String drawEg(Cmd cmd) {
final StringBuilder egSB = new StringBuilder();
for (String eg : cmd.eg()) {
egSB.append(eg).append("\n");
}
return egSB.toString();
}
private String commandHelp(Class<?> clazz) {
final Cmd cmd = clazz.getAnnotation(Cmd.class);
final TTable tTable = new TTable(new TTable.ColumnDefine[]{
new TTable.ColumnDefine(TTable.Align.RIGHT),
new TTable.ColumnDefine(80, false, TTable.Align.LEFT)
})
.addRow("USAGE", drawUsage(clazz, cmd));
boolean hasOptions = false;
for (Field f : clazz.getDeclaredFields()) {
if (f.isAnnotationPresent(IndexArg.class)
|| f.isAnnotationPresent(NamedArg.class)) {
hasOptions = true;
break;
}
}
if (hasOptions) {
tTable.addRow("OPTIONS", drawOptions(clazz));
}
if (null != cmd.eg()) {
tTable.addRow("EXAMPLE", drawEg(cmd));
}
return tTable.padding(1).rendering();
}
/*
* 输出主帮助菜单
*/
private String mainHelp() {
final TTable tTable = new TTable(new TTable.ColumnDefine[]{
new TTable.ColumnDefine(TTable.Align.RIGHT),
new TTable.ColumnDefine(80, false, TTable.Align.LEFT)
});
final Map<String, Class<?>> commandMap = Commands.getInstance().listCommands();
final List<Class<?>> classes = new ArrayList<Class<?>>(commandMap.values());
Collections.sort(classes, new Comparator<Class<?>>() {
@Override
public int compare(Class<?> o1, Class<?> o2) {
final Integer o1s = o1.getAnnotation(Cmd.class).sort();
final Integer o2s = o2.getAnnotation(Cmd.class).sort();
return o1s.compareTo(o2s);
}
});
for (Class<?> clazz : classes) {
if (clazz.isAnnotationPresent(Cmd.class)) {
final Cmd cmd = clazz.getAnnotation(Cmd.class);
if (!cmd.isHacking()) {
tTable.addRow(cmd.name(), cmd.summary());
}
}
}
return tTable.padding(1).rendering();
}
}