假设有以下文本:
(define-advice foo\n (:around (orig-fn arg) debug)
body)
(cl-defmethod foo :around\n (arg)
body)
(defun foo (arg)
body)
想提取为以下形式:
<filename>:define-advice, foo, (:around (orig-fn arg) debug)
<filename>:cl-defmethod, foo, (arg)
<filename>:defun, foo, (arg)
末尾的参数列表可能是嵌套的 list,用 rg 可以捕捉到:
(let ((def-pat (replace-regexp-in-string "\\\\" "" (regexp-opt-group
'("cl-defmethod"
"cl-defmacro"
"cl-defun"
"defalias"
"defcustom"
"define-advice"
"defmacro"
"defun"
"defvar"))))
(samples "(define-advice foo\n (:around (orig-fn arg) debug)
body)
(cl-defmethod foo :around\n (arg)
body)
(defun foo (arg)
body)"))
(shell-command-to-string
(concat (format "echo %S | " samples)
(format (concat "rg -U --pcre2 '^[\s\t]*"
"\\((%s)[\s\t]+" ;; Group1: declaration
"([^\s\t\n]+)[\s\t\n]+" ;; Group2: function name
"(?::[^(]+)?" ;; Option: decoration
"(\\((?:[^()]++|(?3))*+\\))'" ;; Group3: arg-list
" -r '$1, $2, $3' -o -N -H -g '*.el'")
def-pat))))
;; => "<stdin>:define-advice, foo, (:around (orig-fn arg) debug)
;; <stdin>:cl-defmethod, foo, (arg)
;; <stdin>:defun, foo, (arg)"
ag 似乎连打印 capture group 都不支持,得用 \K
间接实现,但这只是把 \K
作为打印的起点,相当于打印 group0,有用没用的(例如 (?:...)
) 都打印出来了:
;; `\K` is used to reset the match star:
;; https://github.com/ggreer/the_silver_searcher/issues/400#issuecomment-418454903
(format "ag '^[\s\t]*\\(\\K(%s)[\s\t]+(?:[^\s\t\n]+)' -o -H --nonumbers" def-pat)
;; => "define-advice foo
;; cl-defmethod foo
;; defun foo"
这种情况下应该如何捕捉/打印嵌套的参数列表、并忽略 (?:...)
组?