feat: 实现从资源文件中加载 Snow 编程语言版本信息
This commit is contained in:
parent
34fd7c6d8b
commit
dd2d14743e
10
pom.xml
10
pom.xml
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
<groupId>org.jcnc.snow</groupId>
|
<groupId>org.jcnc.snow</groupId>
|
||||||
<artifactId>Snow</artifactId>
|
<artifactId>Snow</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>0.4.0</version>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>24</maven.compiler.source>
|
<maven.compiler.source>24</maven.compiler.source>
|
||||||
@ -17,6 +17,13 @@
|
|||||||
|
|
||||||
<!-- 通用编译 & 打包插件 -->
|
<!-- 通用编译 & 打包插件 -->
|
||||||
<build>
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<!-- Java 编译插件 -->
|
<!-- Java 编译插件 -->
|
||||||
<plugin>
|
<plugin>
|
||||||
@ -37,6 +44,7 @@
|
|||||||
<manifest>
|
<manifest>
|
||||||
<mainClass>org.jcnc.snow.compiler.cli.SnowCLI</mainClass>
|
<mainClass>org.jcnc.snow.compiler.cli.SnowCLI</mainClass>
|
||||||
<addClasspath>true</addClasspath>
|
<addClasspath>true</addClasspath>
|
||||||
|
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||||
</manifest>
|
</manifest>
|
||||||
</archive>
|
</archive>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@ -3,40 +3,31 @@ package org.jcnc.snow.compiler.cli;
|
|||||||
import org.jcnc.snow.compiler.cli.commands.CompileCommand;
|
import org.jcnc.snow.compiler.cli.commands.CompileCommand;
|
||||||
import org.jcnc.snow.compiler.cli.commands.RunCommand;
|
import org.jcnc.snow.compiler.cli.commands.RunCommand;
|
||||||
import org.jcnc.snow.compiler.cli.commands.VersionCommand;
|
import org.jcnc.snow.compiler.cli.commands.VersionCommand;
|
||||||
|
import org.jcnc.snow.compiler.cli.utils.CLIUtils;
|
||||||
|
import org.jcnc.snow.compiler.cli.utils.VersionUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SnowCLI 是项目的命令行入口类,负责解析用户输入、
|
* Snow 编程语言的命令行接口入口类。
|
||||||
* 分发子命令,并统一处理帮助、版本和错误输出。
|
* <p>
|
||||||
|
* 该类解析用户输入的命令行参数,调度相应的子命令(compile、run、version),
|
||||||
|
* 并处理全局帮助和版本信息输出。
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class SnowCLI {
|
public class SnowCLI {
|
||||||
/** Snow 编程语言的版本号。 */
|
|
||||||
public static final String SNOW_VERSION = "1.0.0";
|
|
||||||
|
|
||||||
/** 全局帮助标志,当输入匹配时显示帮助信息。 */
|
|
||||||
private static final Set<String> GLOBAL_HELP_FLAGS = Set.of("help", "-h", "--help");
|
|
||||||
|
|
||||||
/** 全局版本标志,当输入匹配时显示版本信息。 */
|
|
||||||
private static final Set<String> GLOBAL_VERSION_FLAGS = Set.of("-v", "--version");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 全局选项定义列表。
|
* Snow 编程语言的当前版本号,从资源文件中加载。
|
||||||
* 每个 Option 包含可用标志列表及对应的描述信息。
|
|
||||||
*/
|
*/
|
||||||
private static final List<Option> GLOBAL_OPTIONS = List.of(
|
public static final String SNOW_VERSION = VersionUtils.loadVersion();
|
||||||
new Option(List.of("-h", "--help"), "Show this help message and exit"),
|
|
||||||
new Option(List.of("-v", "--version"), "Print snow programming language version and exit")
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 所有可用子命令的映射:
|
* 可用子命令名称与对应命令处理器的映射表。
|
||||||
* 键为命令名称,值为对应命令实例的提供者。
|
* 键为子命令名称("compile", "run", "version"),
|
||||||
* 通过 Map.of 初始化,添加新命令时只需在此注册。
|
* 值为返回相应 {@link CLICommand} 实例的 Supplier。
|
||||||
*/
|
*/
|
||||||
private static final Map<String, Supplier<CLICommand>> COMMANDS = Map.of(
|
private static final Map<String, Supplier<CLICommand>> COMMANDS = Map.of(
|
||||||
"compile", CompileCommand::new,
|
"compile", CompileCommand::new,
|
||||||
@ -45,92 +36,57 @@ public class SnowCLI {
|
|||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 程序主入口。
|
* 程序入口方法,解析并调度子命令。
|
||||||
* <p>
|
* <p>
|
||||||
* 负责处理以下逻辑:
|
|
||||||
* <ul>
|
|
||||||
* <li>全局帮助标志:无参数或 help 标志时显示通用帮助并退出。</li>
|
|
||||||
* <li>全局版本标志:-v/--version 时打印版本并退出。</li>
|
|
||||||
* <li>子命令调度:根据第一个参数匹配子命令并分发执行。</li>
|
|
||||||
* <li>子命令帮助:子命令后带 --help 时显示该命令帮助。</li>
|
|
||||||
* <li>错误处理:捕获执行异常并打印错误信息。</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
*
|
||||||
* @param args 用户在命令行中输入的参数数组
|
* @param args 命令行参数数组
|
||||||
|
* 无参数或首参数为帮助标志时,打印全局用法说明并退出
|
||||||
|
* 首参数为版本标志时,打印版本信息并退出
|
||||||
|
* 首参数为子命令名时,进一步解析该子命令的参数并执行
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// —— 全局帮助 —— //
|
// 处理全局帮助
|
||||||
if (args.length == 0 || GLOBAL_HELP_FLAGS.contains(args[0])) {
|
if (args.length == 0 || CLIUtils.GLOBAL_HELP_FLAGS.contains(args[0])) {
|
||||||
printGeneralUsage();
|
CLIUtils.printGeneralUsage(COMMANDS);
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// —— 全局版本 —— //
|
// 处理全局版本请求
|
||||||
if (GLOBAL_VERSION_FLAGS.contains(args[0])) {
|
if (CLIUtils.GLOBAL_VERSION_FLAGS.contains(args[0])) {
|
||||||
new VersionCommand().execute(new String[0]);
|
new VersionCommand().execute(new String[0]);
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// —— 子命令调度 —— //
|
// 子命令名称
|
||||||
String cmdName = args[0];
|
String cmdName = args[0];
|
||||||
Supplier<CLICommand> cmdSupplier = COMMANDS.get(cmdName);
|
Supplier<CLICommand> cmdSupplier = COMMANDS.get(cmdName);
|
||||||
|
|
||||||
|
// 未知子命令处理
|
||||||
if (cmdSupplier == null) {
|
if (cmdSupplier == null) {
|
||||||
System.err.println("Unknown command: " + cmdName);
|
System.err.println("Unknown command: " + cmdName);
|
||||||
printGeneralUsage();
|
CLIUtils.printGeneralUsage(COMMANDS);
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 创建对应子命令实例
|
||||||
CLICommand cmd = cmdSupplier.get();
|
CLICommand cmd = cmdSupplier.get();
|
||||||
|
// 提取子命令参数
|
||||||
String[] subArgs = Arrays.copyOfRange(args, 1, args.length);
|
String[] subArgs = Arrays.copyOfRange(args, 1, args.length);
|
||||||
|
|
||||||
// —— 子命令帮助 —— //
|
// 如果子命令请求帮助,则打印该命令的用法说明并退出
|
||||||
if (subArgs.length > 0 && GLOBAL_HELP_FLAGS.contains(subArgs[0])) {
|
if (subArgs.length > 0 && CLIUtils.GLOBAL_HELP_FLAGS.contains(subArgs[0])) {
|
||||||
cmd.printUsage();
|
cmd.printUsage();
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// —— 执行子命令 —— //
|
// 执行子命令并根据返回的退出码退出
|
||||||
try {
|
try {
|
||||||
int exitCode = cmd.execute(subArgs);
|
int exitCode = cmd.execute(subArgs);
|
||||||
System.exit(exitCode);
|
System.exit(exitCode);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
// 捕获命令执行过程中的异常并打印错误消息
|
||||||
System.err.println("Error: " + e.getMessage());
|
System.err.println("Error: " + e.getMessage());
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 打印动态生成的通用帮助信息。
|
|
||||||
* <p>
|
|
||||||
* 列出全局选项和所有注册子命令的名称与描述。
|
|
||||||
*/
|
|
||||||
private static void printGeneralUsage() {
|
|
||||||
System.out.println("Usage:");
|
|
||||||
System.out.println(" snow [OPTIONS] <command>");
|
|
||||||
System.out.println();
|
|
||||||
System.out.println("Options:");
|
|
||||||
// 动态遍历全局选项
|
|
||||||
for (Option opt : GLOBAL_OPTIONS) {
|
|
||||||
String flags = String.join(", ", opt.flags());
|
|
||||||
System.out.printf(" %-15s %s%n", flags, opt.description());
|
|
||||||
}
|
|
||||||
System.out.println();
|
|
||||||
System.out.println("Commands:");
|
|
||||||
// 遍历注册的子命令,动态输出
|
|
||||||
COMMANDS.forEach((name, supplier) -> {
|
|
||||||
CLICommand c = supplier.get();
|
|
||||||
System.out.printf(" %-10s %s%n", name, c.description());
|
|
||||||
});
|
|
||||||
System.out.println();
|
|
||||||
System.out.println("Use \"snow <command> --help\" for command-specific options.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 全局选项的数据结构,包含标志列表和描述信息。
|
|
||||||
*
|
|
||||||
* @param flags 选项的所有标志,例如 -h, --help
|
|
||||||
* @param description 选项的功能说明
|
|
||||||
*/
|
|
||||||
private record Option(List<String> flags, String description) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,7 +49,8 @@ public final class VersionCommand implements CLICommand {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int execute(String[] args) {
|
public int execute(String[] args) {
|
||||||
System.out.println("snow version " + SnowCLI.SNOW_VERSION);
|
System.out.println("snow version " + "\"" + SnowCLI.SNOW_VERSION + "\"");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
70
src/main/java/org/jcnc/snow/compiler/cli/utils/CLIUtils.java
Normal file
70
src/main/java/org/jcnc/snow/compiler/cli/utils/CLIUtils.java
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package org.jcnc.snow.compiler.cli.utils;
|
||||||
|
|
||||||
|
import org.jcnc.snow.compiler.cli.CLICommand;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令行界面通用工具类,提供全局帮助和版本标志、全局选项定义,以及打印通用用法的方法。
|
||||||
|
*/
|
||||||
|
public class CLIUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局帮助标志集合,支持 "help"、"-h"、"--help"。
|
||||||
|
*/
|
||||||
|
public static final Set<String> GLOBAL_HELP_FLAGS = Set.of(
|
||||||
|
"help", "-h", "--help"
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局版本标志集合,支持 "-v"、"--version"。
|
||||||
|
*/
|
||||||
|
public static final Set<String> GLOBAL_VERSION_FLAGS = Set.of(
|
||||||
|
"-v", "--version"
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局选项列表,包括帮助和版本选项的描述。
|
||||||
|
*/
|
||||||
|
public static final List<Option> GLOBAL_OPTIONS = List.of(
|
||||||
|
new Option(List.of("-h", "--help"), "Show this help message and exit"),
|
||||||
|
new Option(List.of("-v", "--version"), "Print snow programming language version and exit")
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打印命令行工具的通用用法说明。
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @param commands 可用子命令名称到命令处理器的映射,用于列出所有子命令及其描述
|
||||||
|
*/
|
||||||
|
public static void printGeneralUsage(Map<String, Supplier<CLICommand>> commands) {
|
||||||
|
System.out.println("Usage:");
|
||||||
|
System.out.println(" snow [OPTIONS] <command>");
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Options:");
|
||||||
|
for (Option opt : GLOBAL_OPTIONS) {
|
||||||
|
String flags = String.join(", ", opt.flags());
|
||||||
|
System.out.printf(" %-15s %s%n", flags, opt.description());
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Commands:");
|
||||||
|
commands.forEach((name, supplier) -> {
|
||||||
|
CLICommand c = supplier.get();
|
||||||
|
System.out.printf(" %-10s %s%n", name, c.description());
|
||||||
|
});
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("Use \"snow <command> --help\" for command-specific options.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局选项的数据结构,包含选项标志和描述。
|
||||||
|
*
|
||||||
|
* @param flags 选项标志列表,例如 ["-h", "--help"]
|
||||||
|
* @param description 选项功能描述
|
||||||
|
*/
|
||||||
|
public record Option(List<String> flags, String description) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package org.jcnc.snow.compiler.cli.utils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 版本工具类,用于加载资源文件中的 Snow 编程语言版本信息。
|
||||||
|
* <p>
|
||||||
|
* 从 classpath 路径下的 version.properties 文件中读取属性 "snow.version",
|
||||||
|
* 并返回对应的版本号字符串。
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class VersionUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 资源文件路径常量,指向 classpath 根目录下的 version.properties 文件。
|
||||||
|
*/
|
||||||
|
private static final String PROPERTIES_PATH = "/version.properties";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载并返回 Snow 编程语言的版本号。
|
||||||
|
* <p>
|
||||||
|
* 通过 Class.getResourceAsStream 方法读取 version.properties 文件,
|
||||||
|
* 使用 {@link Properties} 类解析并获取 key 为 "snow.version" 的值。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return 从 version.properties 中读取的版本号(如 "1.0.0")
|
||||||
|
* @throws UncheckedIOException 如果读取或解析配置文件时发生 I/O 错误
|
||||||
|
*/
|
||||||
|
public static String loadVersion() {
|
||||||
|
try (InputStream in = VersionUtils.class.getResourceAsStream(PROPERTIES_PATH)) {
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.load(in);
|
||||||
|
return properties.getProperty("snow.version");
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException("Failed to load version from " + PROPERTIES_PATH, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/main/resources/version.properties
Normal file
1
src/main/resources/version.properties
Normal file
@ -0,0 +1 @@
|
|||||||
|
snow.version=${project.version}
|
||||||
Loading…
x
Reference in New Issue
Block a user