为什么我不能使用这个解析 javascript 代码的 Common Lisp 宏?
Why I am not being able to use this Common Lisp macro that parses javascript code?
我正在使用 Nyxt web browser,这是一个有趣的 Common Lisp 应用程序。 Nyxt 被设计成一个可无限扩展的浏览器。因此,用户可以在程序 运行 时更改代码 and/or 创建扩展。这是设计的实时黑客能力。
可能的扩展之一是为网络浏览器创建一个新命令。创建新命令的方法不止一种。其中之一是使用小书签命令。必须突出显示负责定义此命令的宏函数:
(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 定制一个新的小书签。基本上,找到 'next' 页面并单击它。这适用于 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 returns T,它可以在 Nyxt 的 GUI 上运行。
NYXT>(define-bookmarklet-command go-next "no documentation yet" "(function() {(document.querySelectorAll('[rel=\"next\"]'))[0].click()})();")
T
我正在使用 Nyxt web browser,这是一个有趣的 Common Lisp 应用程序。 Nyxt 被设计成一个可无限扩展的浏览器。因此,用户可以在程序 运行 时更改代码 and/or 创建扩展。这是设计的实时黑客能力。
可能的扩展之一是为网络浏览器创建一个新命令。创建新命令的方法不止一种。其中之一是使用小书签命令。必须突出显示负责定义此命令的宏函数:
(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 定制一个新的小书签。基本上,找到 'next' 页面并单击它。这适用于 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 returns T,它可以在 Nyxt 的 GUI 上运行。
NYXT>(define-bookmarklet-command go-next "no documentation yet" "(function() {(document.querySelectorAll('[rel=\"next\"]'))[0].click()})();")
T