diff --git a/pom.xml b/pom.xml
index 8e594bb01a36601873e8b046d8e495de70730963..8650c148321ddf2315a9dd7b424852e38b9b83e2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,44 +1,68 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.example
cli-menu-app
1.0-SNAPSHOT
+ CLI Menu App
17
17
UTF-8
+ 4.7.5
-
+
info.picocli
picocli
- 4.7.6
+ ${picocli.version}
-
+
- org.apache.maven.plugins
- maven-jar-plugin
- 3.3.0
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.0.0
-
-
- com.example.climenu.Main
-
-
+ com.example.climenu.Main
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.5.1
+
+
+ package
+
+ shade
+
+
+
+
+
+ com.example.climenu.Main
+
+
+
+
+
+ cli-menu-app-exec
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/example/climenu/Main.java b/src/main/java/com/example/climenu/Main.java
index 7724999ed2f05c5a8ca575dcd43fa8f557089257..063de50d90be3f387196f204583a6a69980140da 100644
--- a/src/main/java/com/example/climenu/Main.java
+++ b/src/main/java/com/example/climenu/Main.java
@@ -1,70 +1,64 @@
package com.example.climenu;
-import picocli.CommandLine;
-
import java.util.Scanner;
+/**
+ * 主类:统一处理命令行参数和交互式菜单
+ */
public class Main {
+
public static void main(String[] args) {
- // 如果没有命令行参数,则启动交互式菜单
- if (args.length == 0) {
- runInteractiveMenu();
- } else {
- // 如果有参数,则按标准 picocli 方式处理
- int exitCode = new CommandLine(new MenuCommand()).execute(args);
+ // 步骤1:如果有命令行参数,直接用 picocli 解析执行
+ if (args != null && args.length > 0) {
+ int exitCode = MenuCommand.execute(args);
System.exit(exitCode);
}
+
+ // 步骤2:无参数时,启动交互式菜单(复用 picocli 逻辑)
+ runInteractiveMenu();
}
+ /**
+ * 交互式菜单(构造参数数组,复用 MenuCommand 的核心逻辑)
+ */
private static void runInteractiveMenu() {
Scanner scanner = new Scanner(System.in);
- MenuCommand menuCmd = new MenuCommand(); // 实例化用于调用方法
+ boolean exit = false;
- while (true) { // 循环直到用户选择退出
- // 显示菜单(调用 MenuCommand 中的方法)
- menuCmd.showMenu();
+ while (!exit) {
+ // 显示菜单
+ System.out.println("\n===== 交互式菜单 =====");
+ System.out.println("1. 显示当前时间");
+ System.out.println("2. 计算斐波那契数列");
+ System.out.println("3. 退出");
+ System.out.print("请选择选项(1-3):");
- System.out.print("请选择操作 (输入 1-3 或 'exit' 退出): ");
+ // 读取用户输入
String input = scanner.nextLine().trim();
-
switch (input) {
case "1":
- // 模拟执行 -t 命令
- System.out.println("🕒 " + CommandLine.Help.Ansi.AUTO.string("@|bold,green " + java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "|@"));
+ // 复用命令行逻辑:构造 [-t] 参数
+ MenuCommand.execute(new String[]{"-t"});
break;
case "2":
- System.out.print("请输入要计算的斐波那契数列项数 N: ");
+ // 读取斐波那契参数,构造 [-f N] 参数
+ System.out.print("请输入斐波那契数列项数(正整数):");
+ String fibInput = scanner.nextLine().trim();
try {
- String fibInput = scanner.nextLine().trim();
int n = Integer.parseInt(fibInput);
- if (n <= 0) {
- System.err.println(CommandLine.Help.Ansi.AUTO.string("@|red 请输入一个正整数。|@"));
- break;
- }
- System.out.println(CommandLine.Help.Ansi.AUTO.string("@|yellow 斐波那契数列(前" + n + "项):|@"));
- for (int i = 0; i < n; i++) {
- System.out.println(" " + CommandLine.Help.Ansi.AUTO.string("@|cyan " + fibonacci(i) + "|@"));
- }
+ MenuCommand.execute(new String[]{"-f", String.valueOf(n)});
} catch (NumberFormatException e) {
- System.err.println(CommandLine.Help.Ansi.AUTO.string("@|red 输入无效,请输入一个数字。|@"));
+ System.err.println("错误:请输入有效的整数!");
}
break;
case "3":
- case "exit":
- case "quit":
- System.out.println("👋 再见!");
- scanner.close();
- return; // 退出循环和程序
+ exit = true;
+ System.out.println("退出程序...");
+ break;
default:
- System.out.println(CommandLine.Help.Ansi.AUTO.string("@|red 无效输入,请输入 1, 2, 3, 或 'exit'。|@"));
+ System.err.println("错误:无效选项,请重新选择!");
}
- System.out.println(); // 空行分隔
}
- }
-
- // 为了在 Main 中复用,将 fibonacci 方法也移到这里,或在 MenuCommand 中设为 public static
- private static long fibonacci(int n) {
- if (n <= 1) return n;
- return fibonacci(n - 1) + fibonacci(n - 2);
+ scanner.close();
}
}
\ No newline at end of file
diff --git a/src/main/java/com/example/climenu/MenuCommand.java b/src/main/java/com/example/climenu/MenuCommand.java
index 22b3841d26999e9dd73587ef5d9d876e4dfc9be4..b317e4de7c859eebaace3dc6d384e7452bce0972 100644
--- a/src/main/java/com/example/climenu/MenuCommand.java
+++ b/src/main/java/com/example/climenu/MenuCommand.java
@@ -3,63 +3,72 @@ package com.example.climenu;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
-import picocli.CommandLine.Help.Ansi;
import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
import java.util.concurrent.Callable;
+/**
+ * 统一的命令处理类(同时支持命令行参数和交互式菜单)
+ */
@Command(
name = "cli-menu",
mixinStandardHelpOptions = true,
- version = "1.0",
- description = "🌈 一个带美化界面的命令行菜单程序"
+ description = "CLI交互式菜单示例,支持时间显示和斐波那契计算"
)
public class MenuCommand implements Callable {
+ // 选项:显示时间
@Option(names = {"-t", "--time"}, description = "显示当前时间")
private boolean showTime;
- @Option(names = {"-f", "--fib"}, description = "计算斐波那契数列前N项", paramLabel = "COUNT")
- private Integer fibonacciCount;
+ // 选项:计算斐波那契
+ @Option(names = {"-f", "--fib"}, description = "计算斐波那契数列第N项")
+ private Integer fibNumber;
+ // 核心业务逻辑:显示当前时间
+ public void showCurrentTime() {
+ System.out.println("当前时间:" + LocalDateTime.now());
+ }
+
+ // 核心业务逻辑:计算斐波那契数列(迭代实现,避免递归栈溢出)
+ public long calculateFibonacci(int n) {
+ if (n < 0) {
+ throw new IllegalArgumentException("斐波那契数不能为负数!");
+ }
+ if (n == 0) return 0;
+ if (n == 1) return 1;
+ long prev = 0, curr = 1;
+ for (int i = 2; i <= n; i++) {
+ long next = prev + curr;
+ prev = curr;
+ curr = next;
+ }
+ return curr;
+ }
+
+ // picocli 核心执行方法(统一入口)
@Override
- public Integer call() {
+ public Integer call() throws Exception {
+ // 优先级:先处理时间,再处理斐波那契
if (showTime) {
- String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
- System.out.println("🕒 " + Ansi.AUTO.string("@|bold,green " + now + "|@"));
+ showCurrentTime();
return 0;
}
-
- if (fibonacciCount != null) {
- if (fibonacciCount <= 0) {
- System.err.println(Ansi.AUTO.string("@|red 请输入一个正整数作为斐波那契数列的项数。|@"));
+ if (fibNumber != null) {
+ try {
+ long result = calculateFibonacci(fibNumber);
+ System.out.printf("斐波那契数列第%d项:%d%n", fibNumber, result);
+ return 0;
+ } catch (IllegalArgumentException e) {
+ System.err.println("错误:" + e.getMessage());
return 1;
}
- System.out.println(Ansi.AUTO.string("@|yellow 斐波那契数列(前" + fibonacciCount + "项):|@"));
- for (int i = 0; i < fibonacciCount; i++) {
- System.out.println(" " + Ansi.AUTO.string("@|cyan " + fibonacci(i) + "|@"));
- }
- return 0;
}
-
- // 当使用 picocli 方式运行且没有任何功能选项时,也显示菜单
- showMenu();
- return 0;
- }
-
- // 移除 private,改为 public,以便 Main 类可以调用
- public void showMenu() {
- System.out.println(Ansi.AUTO.string("@|bold,blue \n======== 欢迎使用 CLI 菜单助手 ========|@"));
- System.out.println("1. " + Ansi.AUTO.string("@|yellow 显示当前时间|@"));
- System.out.println("2. " + Ansi.AUTO.string("@|yellow 计算斐波那契数列|@"));
- System.out.println("3. " + Ansi.AUTO.string("@|yellow 退出程序|@"));
- System.out.println(Ansi.AUTO.string("@|bold,blue ========================================|@") + "\n");
- System.out.println(Ansi.AUTO.string("@|italic 提示: 运行 --help 查看详细帮助信息。|@"));
+ return 0; // 无参数时返回0,触发交互式菜单
}
- private long fibonacci(int n) {
- if (n <= 1) return n;
- return fibonacci(n - 1) + fibonacci(n - 2);
+ // 静态方法:供外部调用(统一执行逻辑)
+ public static int execute(String[] args) {
+ return new CommandLine(new MenuCommand()).execute(args);
}
}
\ No newline at end of file