feat: 控制台输出样式调整、新增instance指令.
This commit is contained in:
@@ -16,6 +16,7 @@ import com.serliunx.ddns.support.command.target.HelpCommand;
|
|||||||
import com.serliunx.ddns.support.command.target.ReloadCommand;
|
import com.serliunx.ddns.support.command.target.ReloadCommand;
|
||||||
import com.serliunx.ddns.support.command.target.StopCommand;
|
import com.serliunx.ddns.support.command.target.StopCommand;
|
||||||
import com.serliunx.ddns.support.command.target.config.ConfigCommand;
|
import com.serliunx.ddns.support.command.target.config.ConfigCommand;
|
||||||
|
import com.serliunx.ddns.support.command.target.instance.InstanceCommand;
|
||||||
import com.serliunx.ddns.support.log.JLineAdaptAppender;
|
import com.serliunx.ddns.support.log.JLineAdaptAppender;
|
||||||
import org.jline.reader.LineReader;
|
import org.jline.reader.LineReader;
|
||||||
import org.jline.reader.LineReaderBuilder;
|
import org.jline.reader.LineReaderBuilder;
|
||||||
@@ -143,6 +144,8 @@ public final class ManagerLite {
|
|||||||
commandDispatcher.register(new ConfigCommand(configuration));
|
commandDispatcher.register(new ConfigCommand(configuration));
|
||||||
// stop
|
// stop
|
||||||
commandDispatcher.register(new StopCommand());
|
commandDispatcher.register(new StopCommand());
|
||||||
|
// instance
|
||||||
|
commandDispatcher.register(new InstanceCommand(systemInitializer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ public abstract class AbstractInstanceContext implements InstanceContext, Multip
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Instance> getInstances() {
|
public Set<Instance> getInstances() {
|
||||||
return instanceMap == null ? Collections.emptySet() : new HashSet<>(instanceMap.values());
|
return instanceMap == null ? Collections.emptySet() : new LinkedHashSet<>(instanceMap.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.serliunx.ddns.support;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 控制台样式助手
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||||
|
* @version 1.0.4
|
||||||
|
* @since 2025/2/4
|
||||||
|
*/
|
||||||
|
public final class ConsoleStyleHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ANSI 控制台经典样式编码映射表
|
||||||
|
*/
|
||||||
|
private static final Map<String, String> CLASSIC_STYLE_MAP = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
// 格式
|
||||||
|
CLASSIC_STYLE_MAP.put("&r", "\033[0m"); // 重置
|
||||||
|
CLASSIC_STYLE_MAP.put("&l", "\033[1m"); // 加粗或高亮
|
||||||
|
|
||||||
|
// 颜色
|
||||||
|
CLASSIC_STYLE_MAP.put("&0", "\033[30m"); // 黑色
|
||||||
|
CLASSIC_STYLE_MAP.put("&1", "\033[31m"); // 红色
|
||||||
|
CLASSIC_STYLE_MAP.put("&2", "\033[32m"); // 绿色
|
||||||
|
CLASSIC_STYLE_MAP.put("&3", "\033[33m"); // 黄色
|
||||||
|
CLASSIC_STYLE_MAP.put("&4", "\033[34m"); // 蓝色
|
||||||
|
CLASSIC_STYLE_MAP.put("&5", "\033[35m"); // 品红
|
||||||
|
CLASSIC_STYLE_MAP.put("&6", "\033[36m"); // 青色
|
||||||
|
CLASSIC_STYLE_MAP.put("&7", "\033[37m"); // 白色
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化输出, 支持颜色代码
|
||||||
|
*
|
||||||
|
* @param format 格式
|
||||||
|
* @param args 参数
|
||||||
|
*/
|
||||||
|
public static void coloredPrintf(String format, final Object... args) {
|
||||||
|
if (!format.endsWith("%n")) {
|
||||||
|
format = format + "%n";
|
||||||
|
}
|
||||||
|
if (!format.endsWith("&r")) {
|
||||||
|
format = format + "&r";
|
||||||
|
}
|
||||||
|
System.out.printf(replaceStyleCode(format), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 替换样式代码
|
||||||
|
*
|
||||||
|
* @param original 原始文本
|
||||||
|
* @return 替换后的文本
|
||||||
|
*/
|
||||||
|
private static String replaceStyleCode(String original) {
|
||||||
|
Set<Map.Entry<String, String>> entries = CLASSIC_STYLE_MAP.entrySet();
|
||||||
|
for (Map.Entry<String, String> entry : entries) {
|
||||||
|
original = original.replace(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.serliunx.ddns.support.ConsoleStyleHelper.coloredPrintf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指令的抽象实现
|
* 指令的抽象实现
|
||||||
* <li> 实现公共逻辑及定义具体逻辑
|
* <li> 实现公共逻辑及定义具体逻辑
|
||||||
@@ -68,8 +70,10 @@ public abstract class AbstractCommand implements Command {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onCommand(String[] args) {
|
public boolean onCommand(String[] args) {
|
||||||
if (!hasArgs(args) ||
|
if (!hasArgs(args) ||
|
||||||
args.length < 2) {
|
args.length < 1) {
|
||||||
log.warn("用法 => {}", getUsage());
|
System.out.println();
|
||||||
|
coloredPrintf("&2用法 =>&r &6%s", getUsage());
|
||||||
|
System.out.println();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import java.util.Arrays;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.serliunx.ddns.support.ConsoleStyleHelper.coloredPrintf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指令调度器
|
* 指令调度器
|
||||||
*
|
*
|
||||||
@@ -70,11 +72,13 @@ public final class CommandDispatcher {
|
|||||||
|
|
||||||
Command command = commands.get(cmd);
|
Command command = commands.get(cmd);
|
||||||
if (command == null) {
|
if (command == null) {
|
||||||
logger.warn("未知指令: {}, 请输入 help 查看帮助!", cmd);
|
System.out.println();
|
||||||
|
coloredPrintf("&1未知指令&r: &2%s&r, &1请输入 &3help&r &1查看帮助!", cmd);
|
||||||
|
System.out.println();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!command.onCommand(splitArgs(args))) {
|
if (!command.onCommand(splitArgs(args))) {
|
||||||
logger.error("指令执行出现了错误: {}", Arrays.toString(args));
|
coloredPrintf("&1指令执行出现了错误:&r &5%s", Arrays.toString(args));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static com.serliunx.ddns.support.ConsoleStyleHelper.coloredPrintf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指令: help
|
* 指令: help
|
||||||
*
|
*
|
||||||
@@ -31,29 +33,32 @@ public class HelpCommand extends AbstractCommand {
|
|||||||
if (hasArgs(args)) {
|
if (hasArgs(args)) {
|
||||||
final String cmd = args[0];
|
final String cmd = args[0];
|
||||||
final Command command = commands.get(cmd);
|
final Command command = commands.get(cmd);
|
||||||
|
System.out.println();
|
||||||
if (command == null) {
|
if (command == null) {
|
||||||
System.out.printf("无法找到指令 %s 的相关信息, 请使用 help 查看可用的指令及帮助!%n", cmd);
|
coloredPrintf("&1无法找到指令 %s 的相关信息, 请使用 help 查看可用的指令及帮助!%n", cmd);
|
||||||
} else {
|
} else {
|
||||||
List<Command> subCommands = command.getSubCommands();
|
List<Command> subCommands = command.getSubCommands();
|
||||||
if (subCommands == null ||
|
if (subCommands == null ||
|
||||||
subCommands.isEmpty()) {
|
subCommands.isEmpty()) {
|
||||||
System.out.printf("指令:%s - %s - %s%n", cmd, command.getDescription(), command.getUsage());
|
coloredPrintf("&2%s&r - &6%s&r - &5%s%n", cmd, command.getDescription(), command.getUsage());
|
||||||
} else {
|
} else {
|
||||||
subCommands.forEach(c -> {
|
subCommands.forEach(c -> {
|
||||||
System.out.printf("%s - %s - %s%n", c.getName(), c.getDescription(), c.getUsage());
|
coloredPrintf("&2%s&r - &6%s&r - &5%s%n", c.getName(), c.getDescription(), c.getUsage());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
System.out.println();
|
||||||
} else {
|
} else {
|
||||||
|
System.out.println();
|
||||||
commands.forEach((k, v) -> {
|
commands.forEach((k, v) -> {
|
||||||
// 忽略 help 自身
|
// 忽略 help 自身
|
||||||
if (k.equals(getName())) {
|
if (k.equals(getName())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
System.out.printf("%s - %s - %s%n", k, v.getDescription(), v.getUsage());
|
coloredPrintf("&2%s&r\t - &6%s&r - &5%s%n", k, v.getDescription(), v.getUsage());
|
||||||
});
|
});
|
||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.println("使用 help <指令> 来查看更详细的帮助信息.");
|
coloredPrintf("&6&l使用 help <指令> 来查看更详细的帮助信息.");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import org.jline.reader.ParsedLine;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.serliunx.ddns.support.ConsoleStyleHelper.coloredPrintf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指令: config get
|
* 指令: config get
|
||||||
*
|
*
|
||||||
@@ -31,7 +33,9 @@ public final class ConfigGetCommand extends AbstractCommand {
|
|||||||
public boolean onCommand(String[] args) {
|
public boolean onCommand(String[] args) {
|
||||||
if (!hasArgs(args) ||
|
if (!hasArgs(args) ||
|
||||||
args.length < 1) {
|
args.length < 1) {
|
||||||
log.warn("用法 => {}", getUsage());
|
System.out.println();
|
||||||
|
coloredPrintf("&2用法 =>&r &6%s", getUsage());
|
||||||
|
System.out.println();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
System.out.println(configuration.getString(args[0]));
|
System.out.println(configuration.getString(args[0]));
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import org.jline.reader.ParsedLine;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.serliunx.ddns.support.ConsoleStyleHelper.coloredPrintf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指令: config set
|
* 指令: config set
|
||||||
*
|
*
|
||||||
@@ -31,7 +33,9 @@ public final class ConfigSetCommand extends AbstractCommand {
|
|||||||
public boolean onCommand(String[] args) {
|
public boolean onCommand(String[] args) {
|
||||||
if (!hasArgs(args) ||
|
if (!hasArgs(args) ||
|
||||||
args.length < 2) {
|
args.length < 2) {
|
||||||
log.warn("用法 => {}", getUsage());
|
System.out.println();
|
||||||
|
coloredPrintf("&2用法 =>&r &6%s", getUsage());
|
||||||
|
System.out.println();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
final String target = args[0];
|
final String target = args[0];
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.serliunx.ddns.support.command.target.instance;
|
||||||
|
|
||||||
|
import com.serliunx.ddns.support.SystemInitializer;
|
||||||
|
import com.serliunx.ddns.support.command.AbstractCommand;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令: instance
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||||
|
* @version 1.0.4
|
||||||
|
* @since 2025/2/4
|
||||||
|
*/
|
||||||
|
public final class InstanceCommand extends AbstractCommand {
|
||||||
|
|
||||||
|
public InstanceCommand(SystemInitializer systemInitializer) {
|
||||||
|
super("instance", new ArrayList<>(), "实例相关指令", "instance list/add/...");
|
||||||
|
// 子命令: list
|
||||||
|
addSubCommand(new InstanceListCommand(systemInitializer));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.serliunx.ddns.support.command.target.instance;
|
||||||
|
|
||||||
|
import com.serliunx.ddns.core.instance.Instance;
|
||||||
|
import com.serliunx.ddns.support.Assert;
|
||||||
|
import com.serliunx.ddns.support.ConsoleStyleHelper;
|
||||||
|
import com.serliunx.ddns.support.SystemInitializer;
|
||||||
|
import com.serliunx.ddns.support.command.AbstractCommand;
|
||||||
|
import org.jline.reader.Candidate;
|
||||||
|
import org.jline.reader.LineReader;
|
||||||
|
import org.jline.reader.ParsedLine;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令: instance list
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||||
|
* @version 1.0.4
|
||||||
|
* @since 2025/2/4
|
||||||
|
*/
|
||||||
|
public final class InstanceListCommand extends AbstractCommand {
|
||||||
|
|
||||||
|
private final SystemInitializer systemInitializer;
|
||||||
|
|
||||||
|
public InstanceListCommand(SystemInitializer systemInitializer) {
|
||||||
|
super("list", new ArrayList<>(), "列出所有实例", "instance list");
|
||||||
|
Assert.notNull(systemInitializer);
|
||||||
|
this.systemInitializer = systemInitializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(String[] args) {
|
||||||
|
Set<Instance> instances = systemInitializer.getInstances();
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
instances.forEach(i -> {
|
||||||
|
ConsoleStyleHelper.coloredPrintf("&2%s&r(&3%s&r)", i.getName(), i.getType());
|
||||||
|
});
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getArgs() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete(LineReader reader, ParsedLine line, int index, List<Candidate> candidates) {
|
||||||
|
//do nothing for list
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user