如何为 Raku CLI 使用包装脚本

如何解决如何为 Raku CLI 使用包装脚本

我想知道在 Raku 中创建 CLI 应用程序时推荐哪些步骤(例如 shebang 行和包装脚本)。我对将与 Zef 一起安装的脚本和将单独分发的脚本的信息感兴趣。

文档提供了示例 frobnicate 程序:

# inside "frobnicate.raku" 
sub MAIN(Str $file where *.IO.f,Int  :$length = 24,Bool :$verbose) { #`(body omitted)}

我可以用 raku frobnicate.raku 运行——一个很好的脚本解决方案,但对真正的程序来说不是很好。

如果我希望它更像一个标准程序,我可以创建一个 frobnicate 文件,如下所示:

#!/usr/bin/env raku
sub MAIN(Str $file where *.IO.f,Bool :$verbose) { #`(body omitted)}

我可以使用 chmod +x 使该文件可执行并将其移动到我的 $PATH 中的目录中;然后我可以使用命令 frobnicate 进行 frobnicate。到目前为止,所有这些都非常合理,就像任何其他脚本语言一样。

然而,这些都没有利用 Raku 的编译。因此,在 MAIN 中进行更多处理的 CLI 应用程序可能会变慢(即使生成 --help 输出也是如此)。因此,下一步是允许预编译应用程序,但我不太确定该怎么做。

与泽夫

当我查看使用 Zef 安装 Raku 程序后执行的脚本时,它们几乎都具有以下形式:

#!/usr/bin/env perl6
sub MAIN(:$name,:$auth,:$ver,*@,*%) {
    CompUnit::RepositoryRegistry.run-script("frobnicate",:$name,:$ver);
}

而且,当我检查包的来源时,此 CompUnit::RepositoryRegistry.run-script 行不存在。所以我猜Zef会添加它?如果是这样,在编写我的脚本时我需要做些什么来确保 Zef 将使用这个包装器并且包装器可以工作?

This comment 有助于了解正在发生的事情,但我仍然不确定我是否 100% 明白)。

没有Zef

我想编写用户可以运行的脚本,无需通过 Zef 安装它们(尽管这是我推荐的安装方法)。有没有办法在没有 Zef 的情况下使用上面显示的 run-script 方法?或者我应该做以下类似的事情,我也看到过:

#!/usr/bin/env raku
use Frobnicate::CLI

(然后将实际功能移动到 Frobnicate/CLI.rakumod 文件中)。

如果我走这条路,我需要指导用户下载上面的 frobnicate 包装脚本和 Frobnicate/CLI.rakumod 文件,对吗? (也就是说,无法在单个文件中执行此操作,是吗?)

假设我确实需要让我的用户下载两个文件,我应该让他们在哪里安装这些文件? frobnicate 需要进入其 PATH 中的目录,但是 Frobnicate/CLI.rakumod 呢?是否需要将其复制到他们的 Raku 模块搜索路径中(如果需要,什么命令会向他们显示该路径是什么)?或者我可以以某种方式修改 frobnicate 包装器(也许通过将 raku 更改为 raku -Ilib 或类似的东西?),让他们将两者都安装到 {{ 1}}?

在把所有这些都打出来之后,我觉得我想得太多了。如果是这样,也请让我知道!无论如何,如果我能更好地理解这一点,我很乐意在文档的相关部分添加更多细节。

解决方法

所以我猜是 Zef 添加了它?

CompUnit::Repository::Installation adds it

为什么会在那里?原因之一是因为某些包装器需要管理同名的 bin 脚本,否则如果它们在同一目录中,则会发生冲突。

有没有办法在没有 Zef 的情况下使用上面显示的 run-script 方法?

run-script is for CompUnit::Repository::Installation only -- 如果你没有安装模块,那么 run-script 不会有兴趣

假设我确实需要让我的用户下载两个文件,我应该让他们在哪里安装这些文件?

推荐/惯用的方法是使用核心 raku 功能来安装东西(即使用 zef)。否则,您应该在何处放置一些代码 a) 无关紧要或 b) 将主要依赖于您的环境,您的操作系统的惯用语等。

是否需要将其复制到他们的 Raku 模块搜索路径中(如果需要,什么命令会向他们显示该路径是什么)

echo $RAKULIB 在大多数情况下应该足以显示模块搜索路径,尤其是当他们对安装路径的位置不感兴趣时​​。因此,您可以指示用户设置例如RAKULIB=$FROB_LIB_DIR 指向您的库所在的任何位置,如果您希望他们能够运行您的脚本而无需通过 raku -I../ frobnicate 手动指定它(因此他们不会将代码复制到任何特殊的地方,他们只是指向他们例如克隆你的回购)。与 $PATH 一起使用也是如此。

或者我可以以某种方式修改 frobnicate 包装器(也许通过将 raku 更改为 raku -Ilib 或类似的东西?),以便让他们将两者都安装到其 PATH 上的目录中?

我建议不要根据 $PATH 中的某个值安装东西。指示用户设置 $PATH,不要将东西安装到 $PATH

从技术上讲,您可以将 use lib '../' 添加到您的脚本中,但是在您还希望用户正常安装的脚本中使用 use lib 不太理想,因为它会在以下情况下添加未使用的、可能被劫持的模块搜索路径从这样的安装中运行。

如果您希望您的代码预编译,那么我建议将其放在一个模块中,并指示您的用户,如果他们不打算安装它,则在每次使用的基础上通过 raku -I../ ./frobnicate 调用它或者像 export RAKULIB="$FROB_LIB_DIR,$RAKULIB" 后跟 ./frobnicate 之类的东西,以获得更持久的东西。或者,如果有人最终实现了脚本的预编译,那么您可以只使用单文件方法。

,

关于这个话题的一些评论。

  1. 我认为最好使用 zef,因为 zef 也会加载依赖项。能够在不使用其他模块的情况下编写 Raku 程序已经很不寻常了,我预计随着更多 Raku 模块的开发,这种情况会变得更加不寻常。

  2. 我忘记了在我的系统上安装了哪些模块,并包含在程序中。通过在 META6.json 中指定所有内容,然后运行 ​​zef test .,可以提高确保其他人可以下载模块的机会。实际上,我发现确保这一点的最佳方法是创建一个 docker 文件并尝试在 docker 映像/容器中安装一个新模块 - 但这是另一个话题。

  3. 我发现(对于 Linux,我无法评论 Windows)如果我:

    • 在 Raku 中编写一个可执行文件(见下文),我们称之为 MyWonder
    • 将其放在 <distribution>/bin 文件夹中,
    • 给它 +x 权限,并且
    • 在分发的根 META6.json 文件中指定它
    • (发布发行版)

    然后当 zef 安装发行版时,MyWonder 将在命令行上工作(假设 zef 本身在命令行上工作,暗示 PATH 包含目录到 zef)。

  4. 调用旨在在命令行上使用或由桌面调用的程序的最佳(对我而言)方式是:

    • 将以下内容放入 MyWonder 文件(无需扩展名)
    use v6.d;
    use MyWonderLife;
    
    • 将所有功能放入 MyWonderLife.rakumod
    • 确保sub MAIN中至少有一个MyWonderLife.rakumod
    • MyWonderLife 文件中指定 META6.json(这对于将实际 MyWonderLife.rakummod 文件放在哪个目录下具有很大的灵活性;它不必是 {{1 }})
    • 为分布创建一个简单的测试 lib/,只有测试 t/basic.rakutest

    这个秘籍意味着所有功能都由 zef 预编译,因此当用户调用可执行文件时,响应速度要快得多。使用 Raku 时最慢的部分是编译程序。通过使用 zef 安装,这在安装过程中完成一次。所有语言的程序安装都很慢,因此 Raku 程序不会让用户想知道在使用它时发生了什么。

    其次,可以使用多个 use-ok 'MyWonderLife; 来处理各种调用情况,并使用现在可以处理的命令行选项范围。虽然这显然在任何脚本中都是可能的,但将它们全部放在 multi sub MAIN 文件中似乎(对我来说)更自然。

    我发现在安装模块时需要进行大量测试,因此我开始将大部分开发和维护测试转移到 .rakumod,并且仅在 {{1} 进行简单的安装测试}}。

    最后,有了这个秘籍(并假设您在 xt/ 文件中为发行版指定了名称 MyWonderLife,t/ 的安装说明,假设可以不带参数调用该程序简单地说:

    使用zef安装MyWonderLife,例如,

    META6.json

    并在命令行上使用它,如下所示:

    MyWonder

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-