Kinney
1
有如下的代码:
(while (re-search-forward gkroam-link-regexp nil t)
(replace-match
(gkroam--format-backlink
(gkroam--get-page (match-string-no-properties 2))
(match-string-no-properties 2))))
目的是搜索符合正则的字符串后,使用 replace-match
替换为 一个经过 gkroam--format-backlink
函数处理过的字符串。 gkroam--format-backlink
函数中使用了 匹配的字符串的分组作为参数。
运行结果报错:(args-out-of-range 0 1)
,这里 replace-match
的用法有问题吗?烦请大佬赐教。
Kinney
4
谢谢,刚刚解决了。原因是 gkroam--get-page
函数中也有搜索的操作,导致这里的 match-data 被污染了。现在,我将所有的 title 和 filename 缓存在了hashtable 里,不使用实时搜索就没问题了。
这个报错信息缺吧,我这里 Emacs 27.1 会给出 Buffer 信息
(args-out-of-range #<buffer foo> 5 6)
字符串越界也会给出字符串。
buffer-substring/substring。
Kinney
6
就是这样的,我是从 backtrace 复制的。我是直接在 buffer 里面 用 eval-expression
测试的代码,可能是这个原因吧。
借楼提问,我用replace-match时同样报错 Args out of range: 0, 7
,代码如下:
(while (re-search-forward org-media-note--timestamp-pattern
nil t)
(let* ((hms (buffer-substring (match-beginning 1)
(match-end 1)))
(adjusted-hms (org-media-note--seconds-to-hms (+ (org-timer-hms-to-secs hms)
offset))))
(replace-match adjusted-hms 'fixedcase)))
其中, org-media-note--timestamp-pattern
为 "\\([0-9]+:[0-9]+:[0-9]+\\)[ \t]?"
用于匹配hms, adjusted-hms
是一个字符串,在运行到 replace-match
的时候,adjusted-hms
已正确计算。
现在发现似乎是由于 (org-timer-hms-to-secs hms)
引起的,是因为该函数内部使用了 string-match
?我现在把replace-match 改成了 delete-region + insert。不知道有没有更好的方法?
简单的例子:
(while (re-search-forward "\\([0-9]+:[0-9]+:[0-9]+\\)[ \t]?" nil t)
(replace-match "xxx" nil nil ))
01:44:20
没有问题,但:
(while (re-search-forward "\\([0-9]+:[0-9]+:[0-9]+\\)[ \t]?" nil t)
(org-timer-hms-to-secs "01:44:20")
(replace-match "xxx" nil nil ))
01:44:20
Debugger entered--Lisp error: (args-out-of-range 0 8)
看来是org-timer-hms-to-secs
中的 match-string 污染问题。类似于楼主原因:
原因是 gkroam--get-page
函数中也有搜索的操作,导致这里的 match-data 被污染了。
想到一个办法是将搜索,保存分成两个函数。
第一次函数负责在搜索的过程中,写成一个列表。第二个用来替换。
有个save-match-data
,把你不希望污染match data的部分用它包起来就好了。我翻了一下自己的配置,发现它通常的用法是放在一个函数的最外层,这样这个函数在对当前buffer进行搜索时不会污染用户的match data。
我看到的 save-match-data
都是和 string-match
配合使用,并保存最后一个值。它也是可以和 re-search-forward
配合,保存所有匹配值?
看文档就知道了,两种search用的同一个系统保存match data。话说 save-match-data
有点misleading,他其实应该叫做“丢弃下面这段代码产生的match data”