用 GitHub Copilot 驱动 Joyride:在 VS Code 用户空间中用 REPL 驱动的 ClojureScript 自动化
2026/9/24 19:36:17 网站建设 项目流程

用 GitHub Copilot 驱动 Joyride:在 VS Code 用户空间中用 REPL 驱动的 ClojureScript 自动化

【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot

导读

本文讲解如何利用本仓库提供的 Copilot 自定义指令(instructions/joyride-user-project.instructions.md),让 GitHub Copilot 化身为一名精通 Joyride 的 Clojure 交互式编程专家。Joyride 是一款运行在 VS Code Extension Host 中的 SCI ClojureScript 环境,可完整访问 VS Code API;读完本文,你将掌握以 REPL 求值为核心的"交互式编程"工作流,能够使用 Joyride Core API、promesa 异步模式、扩展 API 与 Joyride Flares(WebView)在用户空间中逐步构建、验证并落地 VS Code 自动化脚本。

Joyride 与用户空间自动化:背景与定位

Joyride 是 VS Code 的自动化扩展,其核心模型是"在用户空间运行 ClojureScript":

  • SCI 解释执行:Joyride 基于 SCI(Small Clojure Interpreter)在 VS Code 的 Extension Host 进程中运行 ClojureScript,无需编译步骤即可执行;
  • 完整 VS Code API 访问:通过"vscode"模块的互操作语法直接调用windowcommandsworkspaceextensions等命名空间下的方法与成员;
  • 用户项目 vs 工作区自动化:本仓库同时提供两份互补的指令——joyride-user-project.instructions.md(applyTo: '**',面向任意项目中的 Joyride User Script 工程)与 joyride-workspace-automation.instructions.md(applyTo: "**/.joyride/**",面向.joyride/目录下的工作区专属自动化)。前者即本文主题,关注脚本与src目录下的用户工程代码。

在本仓库中的使用方式

本仓库是一个社区贡献的 Copilot 指令、Agent、Skill 与配置集合(见 README.md)。按 docs/README.instructions.md 的说明,你可以点击指令表中的安装按钮,或下载*.instructions.md文件放入工作区的.github/instructions/目录(如.github/instructions/joyride-user-project.instructions.md),指令会自动应用于 Copilot 行为。此外,仓库中的 skills/first-ask/SKILL.md 与 skills/boost-prompt/SKILL.md 都以joyride_request_human_input工具为动力,展示了 Joyride 在 Skill 场景下的真实集成形态。

核心哲学:交互式编程(REPL-Driven Development)

指令给 Copilot 定义的第一原则是:REPL 是超级武器。Copilot 的主工具是Joyride evaluation——直接在 VS Code 运行时环境中求值代码并验证,而不是给出纯理论建议。具体工作方式:

  • 逐步迭代:拿到问题陈述后,与用户一起一步一步推进;
  • 每次求值一个小表达式(不一定是完整函数),验证其行为符合预期;
  • 使用以(in-ns ...)开头的代码块,展示在 Joyride REPL 中实际求值的内容;
  • 只在用户要求时才更新文件,优先用 REPL 把功能"求值出来"。

指令还强调一套数据导向的 Clojure 风格约束:

  • 优先编写接收参数、返回结果的纯函数,副作用仅作为服务更大目标的最后手段;
  • 函数参数优先使用解构(destructuring)与 map;
  • 优先使用命名空间化关键字,可用:foo/something这类"合成命名空间"对数据分组;
  • 建模数据时扁平优于嵌套
  • 强烈不鼓励使用println(以及js/console.log)——应通过求值子表达式来测试,而不是打印输出。

最后一条经验法则:任何 API 用法在写入文件前,都先到 REPL 中验证。

入门:检查项目与信息源

在动手前,Copilot 被指示先查看项目的README.md以及scriptssrc目录中的代码。对于更全面的 Joyride 信息,指令建议(在具备fetch_webpage工具时)查阅官方提供的两份 LLM 上下文指南:agent 技术指南与用户协助指南——后者涵盖项目结构、常用模式、示例与故障排查。始终与用户、REPL 和文档三方确认,再迭代推进

核心 API 与互操作语法

加载命名空间:用joyride.core/load-file而非load-file

Clojure 内置的load-file在 Joyride 中并未实现,应使用 Joyride 的异步版本:

(joyride/load-file) ; 异步,接受绝对路径或相对工作区的路径,返回 promise

命名空间定位至关重要:使用 Joyride evaluation 工具时,务必指定正确的命名空间参数。若函数定义未定位到目标命名空间,可能落入错误的命名空间(如user),导致在预期位置不可用。

VS Code API 访问

通过"vscode"模块直接互操作:

(require '["vscode" :as vscode]) ;; Common patterns users need (vscode/window.showInformationMessage "Hello!") (vscode/commands.executeCommand "workbench.action.files.save") (vscode/window.showQuickPick #js ["Option 1" "Option 2"])

互操作语法要点:函数与成员使用vscode/api.method形式;不要实例化 JS 类,而是直接使用普通 JS 对象,例如#js {:role "user" :content "..."}

Joyride Core API 速查

符号说明
joyride/*file*当前文件路径
(joyride/invoked-script)正在运行的脚本(在 REPL 中为 nil)
(joyride/extension-context)VS Code 扩展上下文
(joyride/output-channel)Joyride 的输出通道
joyride/user-joyride-dir用户 joyride 目录路径
joyride/slurp类似 Clojureslurp,但为异步;接受绝对路径或相对工作区路径,返回 promise
joyride/load-file类似 Clojureload-file,但为异步;接受绝对路径或相对工作区路径,返回 promise

异步操作处理:awaitResult 参数

evaluation 工具提供awaitResult参数来管理异步操作:

  • awaitResult: false(默认):立即返回,适用于同步操作或"即发即弃"(fire-and-forget)的异步求值;
  • awaitResult: true:等待异步操作完成后返回结果,即返回 promise 的解析值。

应使用awaitResult: true的场景

  • 需要读取用户输入结果的对话框(showInputBoxshowQuickPick);
  • 需要结果的findFilesreadFile等文件操作;
  • 返回 promise 的扩展 API 调用;
  • 带按钮的信息消息,需要知道点击了哪个按钮。

保持默认awaitResult: false的场景:同步操作、简单的信息消息等即发即弃调用、不需要返回值的副作用型异步操作。

Promise 处理:用 promesa 编排异步

Joyride 的异步模型依赖 promise,指令推荐使用promesa.core

(require '[promesa.core :as p]) ;; Users need to understand async operations (p/let [result (vscode/window.showInputBox #js {:prompt "Enter value:"})] (when result (vscode/window.showInformationMessage (str "You entered: " result)))) ;; Pattern for unwrapping async results in REPL (use awaitResult: true) (p/let [files (vscode/workspace.findFiles "**/*.cljs")] (def found-files files)) ;; Now `found-files` is defined in the namespace for later use ;; Yet another example with `joyride.core/slurp` (use awaitResult: true) (p/let [content (joyride.core/slurp "some/file/in/the/workspace.csv")] (def content content) ; if you want to use/inspect `content` later in the session ; Do something with the content )

注意其中"先求值再def固化结果"的模式:把异步结果解包后存入命名空间中的 def,便于在当前会话后续引用与检查。

安全访问其他扩展的 API

自动化常常需要读取其他扩展的能力。指令给出了"先检查、再使用"的防御性模式:

;; How to access other extensions safely (when-let [ext (vscode/extensions.getExtension "ms-python.python")] (when (.-isActive ext) (let [python-api (.-exports ext)] ;; Use Python extension API safely (-> python-api .-environments .-known count)))) ;; Always check if extension is available first (defn get-python-info [] (if-let [ext (vscode/extensions.getExtension "ms-python.python")] (if (.-isActive ext) {:available true :env-count (-> ext .-exports .-environments .-known count)} {:available false :reason "Extension not active"}) {:available false :reason "Extension not installed"}))

要点:getExtension可能返回 nil(未安装);扩展对象上要用.-isActive检查是否已激活;导出 API 通过.-exports访问——例如上述 Python 示例最终返回一个扁平、自描述的 map({:available ... :reason ...}),正是指令推崇的数据导向风格。

Joyride Flares:创建 WebView 与侧边栏视图

Flares 是 Joyride 提供的一种便捷方式,用于创建 WebView 面板与侧边栏视图,并支持通过 REPL 与之交互。

基本用法

(require '[joyride.flare :as flare]) ;; Create a flare with Hiccup (flare/flare!+ {:html [:h1 "Hello World!"] :title "My Flare" :key "example"}) ;; Create sidebar flare (slots 1-5 available) (flare/flare!+ {:html [:div [:h2 "Sidebar"] [:p "Content"]] :key :sidebar-1}) ;; Load from file (HTML or EDN with Hiccup) (flare/flare!+ {:file "assets/my-view.html" :key "my-view"}) ;; Display external URL (flare/flare!+ {:url "https://example.com" :title "External Site"})

注意:flare!+返回 promise,调用时应使用awaitResult: true

关键点

  • Hiccup 样式:style属性使用 map,如{:color :red :margin "10px"}
  • 文件路径:支持绝对路径、相对路径(要求处于工作区内)或 Uri 对象;
  • 生命周期管理(flare/close! key)(flare/ls)(flare/close-all!)
  • 双向消息:通过:message-handlerpost-message!+实现 WebView 与 REPL 之间的双向通信。

指令同时提醒:当演示创建状态栏按钮这类可驻留 UI 的一次性对象时,务必持有该对象的引用,以便后续修改与 dispose(释放)。

常用用户模式

脚本执行守卫(Script Execution Guard)

这是最基础的守护模式——保证代码只在作为脚本被调用时执行,而在 REPL 中加载时不误触发:

;; Essential pattern - only run when invoked as script, not when loaded in REPL (when (= (joyride/invoked-script) joyride/*file*) (main))

原理即前文 API 表中的invoked-script(被调用的脚本,REPL 中为 nil)与*file*(当前文件路径)二者比对。

管理 Disposables:统一注册到扩展上下文

事件订阅等返回的 disposable 必须纳入扩展上下文的 subscriptions,随扩展生命周期统一释放:

;; Always register disposables with extension context (let [disposable (vscode/workspace.onDidOpenTextDocument handler)] (.push (.-subscriptions (joyride/extension-context)) disposable))

可视化展示结果与文件编辑

指令要求 Copilot 在演示能力时以可视化方式呈现结果,例如:

  • 统计或汇总后,用信息消息(showInformationMessage)展示结果;
  • 生成 Markdown 文件并以预览模式打开;
  • 更进阶的做法:创建并打开一个 WebView(Flare),通过 Joyride REPL 与之交互。

文件编辑则遵循同样的原则:优先用 REPL 开发;确需编辑文件时,优先使用结构化编辑工具(structural editing tools)而非直接改字面文本。

从源码视角印证:Joyride 在仓库 Skill 中的实际形态

本仓库虽不包含 Joyride 扩展本体源码,但其 skills/first-ask/SKILL.md 与 skills/boost-prompt/SKILL.md 是 Joyride 工具在实际 Skill 中集成的可运行证据:

  • first-askSkill 声明"Requires the Joyride extension",其工作流完全由joyride_request_human_input工具驱动——在refining阶段反复向人类开发者询问范围、交付物、约束,确认无更多输入后再展示计划、建立 todo list 并开工;
  • boost-promptSkill 同样在需要澄清细节时调用joyride_request_human_input

从源码结构看,可以推断这类joyride_*工具正是 Joyride 向 Copilot/Agent 暴露"REPL 求值 + 请求人工输入"能力的两面:前者把 ClojureScript 表达式的求值结果交回对话流(对应本文的 evaluation/awaitResult机制),后者把对话暂停权交给用户。这也解释了为何指令反复强调命名空间定位与异步结果处理——它们是工具正确工作的前提。

使用限制与适用前提

  • 本文所有 API 均以 Joyride 在 VS Code Extension Host 中运行 SCI ClojureScript 为前提,需已安装 Joyride 扩展;joyride_request_human_input等工具仅在对应扩展就绪时可用(first-askSkill 明确标注了这一依赖);
  • load-fileslurp等均为异步实现并返回 promise,需配合 promesa 与awaitResult: true使用,不能按 Clojure 同步语义调用;
  • 命名空间参数必须显式指定,否则函数会落入错误命名空间;
  • 涉及外部扩展(如ms-python.python)的访问,必须先检查安装与激活状态,示例中展示的是防御式访问而非假设 API 一定存在。

小结

这份指令把 GitHub Copilot 塑造成"以 REPL 为超级武器"的 Joyride 专家:从命名空间加载、VS Code API 互操作、Joyride Core API,到awaitResult与 promesa 的异步编排、扩展 API 的安全访问、Flares WebView 创建,以及脚本执行守卫与 disposable 管理两大高频模式,构成了一条"逐步求值、就地验证、最后落地"的完整开发闭环。配合仓库中的 joyride-workspace-automation.instructions.md(面向.joyride/工作区自动化)与依赖 Joyride 工具的 first-ask、boost-prompt 两个 Skill,你可以把同一套 REPL 驱动方法论,从个人用户脚本扩展到团队共享的项目级自动化。

【免费下载链接】awesome-copilotCommunity-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-copilot

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询