change: 调整指令样式; 调整config指令.
This commit is contained in:
@@ -12,10 +12,10 @@ import com.serliunx.ddns.support.InstanceContextHolder;
|
|||||||
import com.serliunx.ddns.support.SystemInitializer;
|
import com.serliunx.ddns.support.SystemInitializer;
|
||||||
import com.serliunx.ddns.support.command.CommandCompleter;
|
import com.serliunx.ddns.support.command.CommandCompleter;
|
||||||
import com.serliunx.ddns.support.command.CommandDispatcher;
|
import com.serliunx.ddns.support.command.CommandDispatcher;
|
||||||
import com.serliunx.ddns.support.command.target.ConfigCommand;
|
|
||||||
import com.serliunx.ddns.support.command.target.HelpCommand;
|
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.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;
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
package com.serliunx.ddns.support.command;
|
package com.serliunx.ddns.support.command;
|
||||||
|
|
||||||
import com.serliunx.ddns.ManagerLite;
|
import com.serliunx.ddns.ManagerLite;
|
||||||
|
import org.jline.reader.Candidate;
|
||||||
|
import org.jline.reader.LineReader;
|
||||||
|
import org.jline.reader.ParsedLine;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指令的抽象实现
|
* 指令的抽象实现
|
||||||
@@ -39,6 +44,11 @@ public abstract class AbstractCommand implements Command {
|
|||||||
return subCommands;
|
return subCommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void addSubCommand(Command command) {
|
||||||
|
subCommands.add(command);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return description;
|
return description;
|
||||||
@@ -49,6 +59,67 @@ public abstract class AbstractCommand implements Command {
|
|||||||
return usage;
|
return usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令逻辑默认实现: 调用子命令
|
||||||
|
*
|
||||||
|
* @param args 当前指令参数
|
||||||
|
* @return 成功执行返回真, 否则返回假. (目前没影响)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(String[] args) {
|
||||||
|
if (!hasArgs(args) ||
|
||||||
|
args.length < 2) {
|
||||||
|
log.warn("用法 => {}", getUsage());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String subCommand = args[0];
|
||||||
|
List<Command> subCommands = getSubCommands();
|
||||||
|
for (Command command : subCommands) {
|
||||||
|
if (command.getName().equalsIgnoreCase(subCommand)) {
|
||||||
|
return command.onCommand(CommandDispatcher.splitArgs(args));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getArgs() {
|
||||||
|
if (subCommands == null ||
|
||||||
|
subCommands.isEmpty()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return subCommands.stream()
|
||||||
|
.map(Command::getName)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete(LineReader reader, ParsedLine line, int index, List<Candidate> candidates) {
|
||||||
|
if (index < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String currentWord = line.word();
|
||||||
|
// 补全子命令
|
||||||
|
final List<Command> subCommands = getSubCommands();
|
||||||
|
if (index == 1) {
|
||||||
|
subCommands.forEach(c -> {
|
||||||
|
if (c.getName().startsWith(currentWord)) {
|
||||||
|
candidates.add(new Candidate(c.getName()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else { // 交给子命令补全
|
||||||
|
for (Command c : subCommands) {
|
||||||
|
if (c.getName().equals(line.words().get(1))) {
|
||||||
|
c.onComplete(reader, line, index, candidates);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean hasArgs(String[] args) {
|
protected boolean hasArgs(String[] args) {
|
||||||
return args.length > 0;
|
return args.length > 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,13 @@ public interface Command {
|
|||||||
*/
|
*/
|
||||||
List<Command> getSubCommands();
|
List<Command> getSubCommands();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加子命令
|
||||||
|
*
|
||||||
|
* @param command 子命令
|
||||||
|
*/
|
||||||
|
void addSubCommand(Command command);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取该指令的描述
|
* 获取该指令的描述
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,76 +0,0 @@
|
|||||||
package com.serliunx.ddns.support.command.target;
|
|
||||||
|
|
||||||
import com.serliunx.ddns.config.Configuration;
|
|
||||||
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.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 指令: config
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
|
||||||
* @version 1.0.4
|
|
||||||
* @since 2025/1/22
|
|
||||||
*/
|
|
||||||
public class ConfigCommand extends AbstractCommand {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 配置信息
|
|
||||||
*/
|
|
||||||
private final Configuration configuration;
|
|
||||||
|
|
||||||
public ConfigCommand(Configuration configuration) {
|
|
||||||
super("config", null, "调整配置信息", "config <配置项> 新的值");
|
|
||||||
this.configuration = configuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCommand(String[] args) {
|
|
||||||
if (!hasArgs(args) ||
|
|
||||||
args.length < 2) {
|
|
||||||
log.warn("用法 => {}", getUsage());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
final String target = args[0];
|
|
||||||
final String value = args[1];
|
|
||||||
return configuration.modify(target, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getArgs() {
|
|
||||||
final Map<String, String> allKeyAndValue;
|
|
||||||
if (configuration == null ||
|
|
||||||
(allKeyAndValue = configuration.getAllKeyAndValue()) == null) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
return new ArrayList<>(allKeyAndValue.keySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onComplete(LineReader reader, ParsedLine line, int index, List<Candidate> candidates) {
|
|
||||||
if (index < 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final String currentWord = line.word();
|
|
||||||
|
|
||||||
// 补全配置键
|
|
||||||
if (index == 1) {
|
|
||||||
final Map<String, String> allKeyAndValue;
|
|
||||||
if (configuration == null ||
|
|
||||||
(allKeyAndValue = configuration.getAllKeyAndValue()) == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
allKeyAndValue.keySet().forEach(k -> {
|
|
||||||
if (k.startsWith(currentWord)) {
|
|
||||||
candidates.add(new Candidate(k));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -28,14 +28,21 @@ public class HelpCommand extends AbstractCommand {
|
|||||||
public boolean onCommand(String[] args) {
|
public boolean onCommand(String[] args) {
|
||||||
final Map<String, Command> commands = getAllCommands();
|
final Map<String, Command> commands = getAllCommands();
|
||||||
|
|
||||||
log.info("==========================================");
|
|
||||||
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);
|
||||||
if (command == null) {
|
if (command == null) {
|
||||||
log.warn("无法找到指令 {} 的相关信息, 请使用 help 查看可用的指令及帮助!", cmd);
|
System.out.printf("无法找到指令 %s 的相关信息, 请使用 help 查看可用的指令及帮助!%n", cmd);
|
||||||
} else {
|
} else {
|
||||||
log.info("指令:{} - {} - {}", cmd, command.getDescription(), command.getUsage());
|
List<Command> subCommands = command.getSubCommands();
|
||||||
|
if (subCommands == null ||
|
||||||
|
subCommands.isEmpty()) {
|
||||||
|
System.out.printf("指令:%s - %s - %s%n", cmd, command.getDescription(), command.getUsage());
|
||||||
|
} else {
|
||||||
|
subCommands.forEach(c -> {
|
||||||
|
System.out.printf("%s - %s - %s%n", c.getName(), c.getDescription(), c.getUsage());
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
commands.forEach((k, v) -> {
|
commands.forEach((k, v) -> {
|
||||||
@@ -43,12 +50,11 @@ public class HelpCommand extends AbstractCommand {
|
|||||||
if (k.equals(getName())) {
|
if (k.equals(getName())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.info("{} - {} - {}", k, v.getDescription(), v.getUsage());
|
System.out.printf("%s - %s - %s%n", k, v.getDescription(), v.getUsage());
|
||||||
});
|
});
|
||||||
log.info("");
|
System.out.println();
|
||||||
log.info("使用 help <指令> 来查看更详细的帮助信息.");
|
System.out.println("使用 help <指令> 来查看更详细的帮助信息.");
|
||||||
}
|
}
|
||||||
log.info("==========================================");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.serliunx.ddns.support.command.target.config;
|
||||||
|
|
||||||
|
import com.serliunx.ddns.config.Configuration;
|
||||||
|
import com.serliunx.ddns.support.command.AbstractCommand;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令: config
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||||
|
* @version 1.0.4
|
||||||
|
* @since 2025/1/22
|
||||||
|
*/
|
||||||
|
public class ConfigCommand extends AbstractCommand {
|
||||||
|
|
||||||
|
public ConfigCommand(Configuration configuration) {
|
||||||
|
super("config", new ArrayList<>(), "调整配置信息", "config <get/set/...>");
|
||||||
|
// 子命令: set
|
||||||
|
addSubCommand(new ConfigSetCommand(configuration));
|
||||||
|
// 子命令: get
|
||||||
|
addSubCommand(new ConfigGetCommand(configuration));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.serliunx.ddns.support.command.target.config;
|
||||||
|
|
||||||
|
import com.serliunx.ddns.config.Configuration;
|
||||||
|
import org.jline.reader.Candidate;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* config 指令相关工具方法
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||||
|
* @version 1.0.4
|
||||||
|
* @since 2025/2/4
|
||||||
|
*/
|
||||||
|
final class ConfigCommandHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有配置键, 作为参数返回
|
||||||
|
*
|
||||||
|
* @param configuration 配置信息
|
||||||
|
* @return 配置键集合
|
||||||
|
*/
|
||||||
|
static List<String> getArgs(Configuration configuration) {
|
||||||
|
final Map<String, String> allKeyAndValue;
|
||||||
|
if (configuration == null ||
|
||||||
|
(allKeyAndValue = configuration.getAllKeyAndValue()) == null) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
return new ArrayList<>(allKeyAndValue.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 补全配置键
|
||||||
|
*
|
||||||
|
* @param configuration 配置键
|
||||||
|
* @param currentWord 当前输入内容
|
||||||
|
* @param candidates 候选参数列表
|
||||||
|
*/
|
||||||
|
static void completeConfigKeys(Configuration configuration, String currentWord, List<Candidate> candidates) {
|
||||||
|
final Map<String, String> allKeyAndValue;
|
||||||
|
if (configuration == null ||
|
||||||
|
(allKeyAndValue = configuration.getAllKeyAndValue()) == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
allKeyAndValue.keySet().forEach(k -> {
|
||||||
|
if (k.startsWith(currentWord)) {
|
||||||
|
candidates.add(new Candidate(k));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.serliunx.ddns.support.command.target.config;
|
||||||
|
|
||||||
|
import com.serliunx.ddns.config.Configuration;
|
||||||
|
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.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令: config get
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||||
|
* @version 1.0.4
|
||||||
|
* @since 2025/2/4
|
||||||
|
*/
|
||||||
|
public final class ConfigGetCommand extends AbstractCommand {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置信息
|
||||||
|
*/
|
||||||
|
private final Configuration configuration;
|
||||||
|
|
||||||
|
public ConfigGetCommand(Configuration configuration) {
|
||||||
|
super("get", null, "获取指定配置项的值", "config get <配置项>");
|
||||||
|
this.configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(String[] args) {
|
||||||
|
if (!hasArgs(args) ||
|
||||||
|
args.length < 1) {
|
||||||
|
log.warn("用法 => {}", getUsage());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
System.out.println(configuration.getString(args[0]));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getArgs() {
|
||||||
|
return ConfigCommandHelper.getArgs(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete(LineReader reader, ParsedLine line, int index, List<Candidate> candidates) {
|
||||||
|
if (index == 2)
|
||||||
|
ConfigCommandHelper.completeConfigKeys(configuration, line.word(), candidates);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.serliunx.ddns.support.command.target.config;
|
||||||
|
|
||||||
|
import com.serliunx.ddns.config.Configuration;
|
||||||
|
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.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指令: config set
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:serliunx@yeah.net">SerLiunx</a>
|
||||||
|
* @version 1.0.4
|
||||||
|
* @since 2025/2/4
|
||||||
|
*/
|
||||||
|
public final class ConfigSetCommand extends AbstractCommand {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置信息
|
||||||
|
*/
|
||||||
|
private final Configuration configuration;
|
||||||
|
|
||||||
|
public ConfigSetCommand(Configuration configuration) {
|
||||||
|
super("set", null, "设置指定配置项的值", "config set <配置项> <新的值>");
|
||||||
|
this.configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(String[] args) {
|
||||||
|
if (!hasArgs(args) ||
|
||||||
|
args.length < 2) {
|
||||||
|
log.warn("用法 => {}", getUsage());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
final String target = args[0];
|
||||||
|
final String value = args[1];
|
||||||
|
return configuration.modify(target, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getArgs() {
|
||||||
|
return ConfigCommandHelper.getArgs(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onComplete(LineReader reader, ParsedLine line, int index, List<Candidate> candidates) {
|
||||||
|
if (index == 2)
|
||||||
|
ConfigCommandHelper.completeConfigKeys(configuration, line.word(), candidates);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user