From 1627684b219418f21b2001b3f3480a0143098a77 Mon Sep 17 00:00:00 2001 From: fushulinaaa <16423437+fushulinaaa@user.noreply.gitee.com> Date: Fri, 5 Dec 2025 10:26:19 +0800 Subject: [PATCH] =?UTF-8?q?fix:=201.=20=E9=85=8D=E7=BD=AEshade=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E6=89=93=E5=8C=85=E8=83=96JAR=EF=BC=9B2.=20=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E4=BB=A3=E7=A0=81=E7=BB=9F=E4=B8=80=E4=BA=A4=E4=BA=92?= =?UTF-8?q?=E4=B8=8E=E5=91=BD=E4=BB=A4=E8=A1=8C=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 50 +++++++++--- src/main/java/com/example/climenu/Main.java | 74 ++++++++--------- .../java/com/example/climenu/MenuCommand.java | 79 +++++++++++-------- 3 files changed, 115 insertions(+), 88 deletions(-) diff --git a/pom.xml b/pom.xml index 8e594bb..8650c14 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 7724999..063de50 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 22b3841..b317e4d 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 -- Gitee