首页 > 其他分享 >交互式命令行

交互式命令行

时间:2023-06-13 17:48:07浏览次数:38  
标签:交互式 val terminal 命令行 reader systemRegistry class description

市面上有不少交互式命令行工具
picocli\jline\kotlin-REPL\jshell
有些直接可以使用,有些需要部分改造,我使用Picocli-shell-jline项目的基础上实现了一款交互式命令行的LicenseGenerator工具

引入maven依赖

<dependency>
  <groupId>info.picocli</groupId>
      <artifactId>picocli-shell-jline3</artifactId>
      <version>4.7.4</version>
  </dependency>

启动

try {
        val workDir = Supplier { Paths.get(System.getProperty("user.dir")) }
        // set up JLine built-in commands
        val builtins = Builtins(workDir, ConfigurationPath(Path.of(""), Path.of("")), null)
        builtins.rename(Builtins.Command.TTOP, "top")
        // set up picocli commands
        val commands = App()
        val factory = PicocliCommands.PicocliCommandsFactory()
        // Or, if you have your own factory, you can chain them like this:
        // MyCustomFactory customFactory = createCustomFactory(); // your application custom factory
        // PicocliCommandsFactory factory = new PicocliCommandsFactory(customFactory); // chain the factories
        val cmd = CommandLine(commands, factory)
        val picocliCommands = PicocliCommands(cmd)
        val parser: Parser = DefaultParser()
        TerminalBuilder.builder().build().use { terminal ->
            val systemRegistry: SystemRegistry = SystemRegistryImpl(parser, terminal, workDir, null)
            systemRegistry.setCommandRegistries(builtins, picocliCommands)
            systemRegistry.register("help", picocliCommands)
            val reader = LineReaderBuilder.builder()
                .terminal(terminal)
                .completer(systemRegistry.completer())
                .parser(parser)
                .variable(LineReader.LIST_MAX, 50) // max tab completion candidates
                .build()
            builtins.setLineReader(reader)
            commands.setReader(reader)
            factory.setTerminal(terminal)
            val widgets =
                TailTipWidgets(reader, systemRegistry::commandDescription, 5, TailTipWidgets.TipType.COMPLETER)
            widgets.enable()
            val keyMap: KeyMap<Binding> = reader.keyMaps["main"]!!
            keyMap.bind(Reference("tailtip-toggle"), KeyMap.alt("s"))
            val prompt = "License> "
            val rightPrompt: String? = null

            // start the shell and process input until the user quits with Ctrl-D
            var line: String?
            while (true) {
                try {
                    systemRegistry.cleanUp()
                    line = reader.readLine(prompt, rightPrompt, null as MaskingCallback?, null)
                    systemRegistry.execute(line)
                    Thread.sleep(1000)
                } catch (e: UserInterruptException) {
                    // Ignore
                } catch (e: EndOfFileException) {
                    return
                } catch (e: Exception) {
                    systemRegistry.trace(e)
                }
            }
        }
    } catch (t: Throwable) {
        t.printStackTrace()
    }

Command

@Command(name = "", version = ["v1.1.2"],
    description = [
        "Example interactive shell with completion and autosuggestions. " +
                "Hit @|magenta <TAB>|@ to see available commands.",
        "Hit @|magenta ALT-S|@ to toggle tailtips.",
        ""],
    footer = ["", "Press Ctrl-D to exit."],
    subcommands = [Generate::class, Checksum::class, Sign::class, Verify::class, PicocliCommands.ClearScreen::class, CommandLine.HelpCommand::class])
class App : Runnable {
    var out: PrintWriter? = null
    override fun run() {
        out?.println(CommandLine(this).usageMessage);
    }
    fun setReader(reader: LineReader) {
        out = reader.terminal.writer()
    }
}

生成公私钥

@CommandLine.Command(name = "generate", version = ["v1.1.2"],
    description = ["Generate Public and Private Keys"])
class Generate : Runnable {
    @Option(names = ["algorithm", "-a"], defaultValue = "RSA", description = ["Algorithm with RSA DECB PKCS5Padding"])
    var algorithm = "RSA"
    @Option(names = ["size", "-s"], defaultValue = "2048", description = ["Size default with 2048"])
    var size = 2048
    @Option(names = ["public", "-p"], defaultValue = "./pub.cert", description = ["Public Key locate"])
    lateinit var public: File
    @Option(names = ["private", "-r"], defaultValue = "./pri.cert", description = ["Private Key locate"])
    lateinit var private: File
    @OptIn(ExperimentalEncodingApi::class)
    override fun run() {
        val generator = KeyPairGenerator.getInstance(algorithm)
        generator.initialize(size)
        val pair = generator.genKeyPair()
        val albyte = algorithm.toByteArray(Charsets.UTF_8)
        val pubBytes = pair.public.encoded
        val priBytes = pair.private.encoded
        FileOutputStream(public).write(Base64.encodeToByteArray(pubBytes))
        FileOutputStream(private).write(Base64.encodeToByteArray(priBytes))
    }
}

总结

总体来说picocli-shell-jline3项目好像还没有开发完,也好像没人维护了,启动非常繁琐,而且有bug,得自己改动,一些逻辑本身不太清楚,而且用了反射的方式调用java基础库的一些不让调用的功能,需要设置jvm启动参数避免警告,总体来说框架本身功能还是非常快速上手,文档也非常全

--illegal-access=deny --add-opens java.base/java.lang=ALL-UNNAMED

标签:交互式,val,terminal,命令行,reader,systemRegistry,class,description
From: https://www.cnblogs.com/terrency/p/17478311.html

相关文章

  • 关于iotop-磁盘IO分析工具的非交互式的用法
    对于iotop命令,默认同top命令模式一样,是交互式模式,实时输出如果我们需要输出到日志文件中,进行分析,可能更多的情况是是需要使用非交互式模式刚好iotop命令,可以使用-b选项,进行非交互模式,然后每隔一秒输出一次所有进程-线程对磁盘IO的使用情况关于iotop命令的先项,本文以在RedHatE......
  • Java用命令行给main方法传参
    Java用命令行给main方法传参1.cd到当前程序的src路径下。2.编译文件,我的文件是在com.test包下。javaccom/test/Demo.java3.给main方法传值。javacom/test/Demo.java123Dowhatyouthinkisright做你认为正确的事......
  • linux命令行elasticsearch查询工具es2unix
    当想在linux的命令行中查看elasticsearch的状态时,可以用es2unix这个工具,插件地址: https://github.com/elasticsearch/es2unix。它是elasticsearch官方推出的,可以通过命令来查看es的各种状态,安装方法curl-sdownload.elasticsearch.org/es2unix/es>/bin/eschmod+x/bin/es这......
  • Linux命令行与shell脚本编程大全学习笔记
    理解Linux文件权限执行ls-l命令获取当前目录下所有文件、目录和设备的权限。显示的列表字段分别为:文件类型,比如目录(d)、文件(-)、字符型文件(c)或块设备(b);文件的权限;文件的硬链接总数;文件属主的用户名;文件属组的组名;文件的大小(以字节为单位);文件的上次修改时间;文件名或目录名。输出......
  • phonegap3.1.0自学笔记01_命令行界面(CLI)简单使用
    要使用phonegap的CLI必须首先安装好phonegap,phonegap的安装还请参看我的另外一篇文章:windows7搭建phonegap3Android开发环境。本篇文章介绍CLI的简单使用,由于本人水平有限,还请大侠不要拍砖。 phonegap3.1.0使用命令行去创建应用程序的框架,然后我们可以基于命令行创建的程序再去进......
  • Linux数据分析之九个给力的命令行工具
    要对数据进行分析,大家会从哪里入手?对于大多数熟悉了图形工作环境的朋友来说,电子表格工具无疑是第一选项。但命令行工具同样能够更快更高效地解决问题——且只须稍微学习即可上手。大部分此类工具冻严格局限于Linux,而多数可同样运行在Unix甚至是Windows环境之下。在今天的文章中,我......
  • Linux数据分析之九个给力的命令行工具
    要对数据进行分析,大家会从哪里入手?对于大多数熟悉了图形工作环境的朋友来说,电子表格工具无疑是第一选项。但命令行工具同样能够更快更高效地解决问题——且只须稍微学习即可上手。要对数据进行分析,大家会从哪里入手?对于大多数熟悉了图形工作环境的朋友来说,电子表格工具......
  • Python从命令行参数和配置文件获取信息
    实际开发中,很多时候需要从外部获取数据,根据用户的输入或配置信息来决定下一步应采取的行为。除了使用内置函数input()或者GUI库的控件和对话框来接收用户输入以外,还可以使用sys和argparse模块来接收命令行参数,使用configparser模块从外部配置文件中获取信息。sys模块的argv是一个包......
  • rust学习 - 构建mini 命令行工具
    rust的运行速度、安全性、单二进制文件输出和跨平台支持使其成为构建命令行程序的最佳选择。实现一个命令行搜索工具grep,可以在指定文件中搜索指定的字符串。想实现这个功能呢,可以按照以下逻辑流程处理:获取输入文件路径、需要搜索的字符串读取文件;在文件内容中查找字符串......
  • 2、客户端访问ZooKeeper--命令行客户端和图形化客户端访问
    客户端访问命令行客户端访问ZooKeeper安装zookeeper的bin里面,有命令行工具[root@ubuntu2004~]#ls/usr/local/zookeeper/bin/zkCli.sh/usr/local/zookeeper/bin/zkCli.sh里面存的脚本是由java运行起来的#可连接至zookeeper集群中的任意一台zookeeper节点进行以下操作,zkCli......