javascript - 为什么我不能使用这个解析 javascript 代码的 Common Lisp 宏?

标签 javascript browser macros common-lisp bookmarklet

我正在使用 Nyxt web browser这是一个有趣的 Common Lisp 应用程序。 Nyxt 被设计成一个可无限扩展的浏览器。因此,用户可以在程序运行时更改代码和/或创建扩展。这是设计的实时黑客能力。

其中一个可能的扩展是为网络浏览器创建一个新命令。创建新命令的方法不止一种。其中之一是使用小书签命令。必须突出显示负责定义此命令的宏函数:

(defmacro nyxt::define-bookmarklet-command (name documentation source)
  "Define a bookmarklet command, the source can either be a JavaScript string to
evaluate, or a file:// URL with a file path to a JavaScript source file."
  `(define-command-global ,name (&optional (buffer (current-buffer)))
     ,documentation
     (let* ((source ,source)
            (source (if (nyxt::file-url-p source)
                        (nyxt::read-file-string source)
                        source)))
       (ffi-buffer-evaluate-javascript-async buffer source))))
(sera:export-always 'nyxt::define-bookmarklet-command :nyxt)

这个定义放在here在源代码上。我之前设法为 Nyxt 创建了一个小书签命令。基本上,来自这个 Javascript 片段的翻译:

(function() { const rate = prompt('Set the
 new playback rate', 2.5); if (rate != null) { const video =
 document.getElementsByTagName('video')[0]; video.playbackRate =
 parseFloat(rate); } })();

转换为以下使用 Nyxt 定义的 common-lisp 片段:

(define-bookmarklet-command live-hack-youtube-speed "Change youtube
 videos speed" "(function() { const rate = prompt('Set the
 new playback rate', 2.5); if (rate != null) { const video =
 document.getElementsByTagName('video')[0]; video.playbackRate =
 parseFloat(rate); } })();")

现在,我正在尝试为 Nyxt 定制一个新的小书签。基本上,找到“下一页”并单击它。这适用于 the GNU manuals 这样的页面.在 Javascript 中,这是:

(document.querySelectorAll('[rel="next"]'))[0].click()

因此,我使用 Nyxt 的宏尝试了以下操作:

  (define-bookmarklet-command goNext "Follow the link labeled next" 
     "(function() {(document.querySelectorAll('[rel="next"]'))[0].click()})();")

很尴尬,我收到了这个错误信息:

Error while parsing arguments to DEFMACRO DEFINE-BOOKMARKLET-COMMAND: too many elements in (GONEXT "Follow the link labeled next" "(function() {(document.querySelectorAll('[rel=" NEXT "]'))[0].click()})();") to satisfy lambda list (NAME DOCUMENTATION NYXT/WEB-MODE::SOURCE): exactly 3 expected, but got 5 [Condition of type SB-KERNEL::ARG-COUNT-ERROR]

我不确定为什么会这样。我正在传递宏 3 参数。但是报错提示是5。

我在 CL 宏方面存在知识空白。为什么会这样?

最佳答案

原来问题不是我对 Common Lisp 宏的理解。实际上,这很简单。我需要使用 \"next\" 来转义 "next" 周围的引号:

(define-bookmarklet-command go-next "no documentation yet" "(function() {(document.querySelectorAll('[rel=\"next\"]'))[0].click()})();")

现在,问题已解决,自定义在 Nyxt 上按预期工作:) REPL 在收到定义后返回 T,并在 Nyxt 的 GUI 上运行。

NYXT>(define-bookmarklet-command go-next "no documentation yet" "(function() {(document.querySelectorAll('[rel=\"next\"]'))[0].click()})();")
T

enter image description here

关于javascript - 为什么我不能使用这个解析 javascript 代码的 Common Lisp 宏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68050617/

相关文章:

c - 用宏包装函数(不重命名)C

unit-testing - 宏约定和最佳实践的 Lisp 单元测试

macros - SPSS 宏在多个数据文件中运行聚合命令

Javascript 函数只调用一次

javascript - Ace 编辑器 (javascript) : Triggering a tab press event for Ace Editors event handlers (not just inserting '/t' or spaces)

javascript - 如何在 chrome 中禁用或隐藏弹出退出全屏(F11)?

security - 客户端 OLAP(例如客户端 MDX 构造加上 xmla4js)是否不利于安全?

javascript - 难以在 Node-Inspector 中设置断点

javascript - 过滤不适用于 AngularJS 中的对象数组

javascript - 为什么这个倒计时 javascript 不能在 chrome 以外的任何浏览器上运行