微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

我正在使用 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()})();")

奇怪的是,我收到此错误消息:

解析 defmacro DEFINE-BOOKMARKLET-COMMAND 参数时出错: 元素太多 (GONEXT“按照标记为下一步的链接” "(function() {(document.querySelectorAll('[rel=" NEXT "]'))[0].click()})();") 满足 lambda 列表 (NAME DOCUMENTATION NYXT/WEB-MODE::SOURCE):正好是 3 个,但是得到了 5 个 [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

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