@casouri 大佬有个包expreg 非常不错,我看到有人提了一个Accept numeric prefix arg for commands? · Issue #4 · casouri/expreg · GitHub 的请求,真是个好主意。于是让AI帮忙做了个小改造,效果还不错,有 flash.nvim 那味了,还不错,于是分享一下。
效果是这样的:
代码如下:
;;; expreg-numeric-selection.el
(defface expreg-number-face
'((t :foreground "#ffff00" :weight bold))
"Face for expreg numeric overlays.")
(defvar-local expreg--region-overlays nil
"List of overlays showing region numbers.")
;; ---------------------------------------------------------------------------
;; 主要交互命令
;; ---------------------------------------------------------------------------
(defun expreg-expand-with-numbers ()
"Show numbered expansion options and allow direct selection."
(interactive)
(let ((regions (expreg--collect-expansion-sequence)))
(if (null regions)
(message "No expansion regions found")
(unwind-protect
(progn
(expreg--show-region-numbers regions)
(let ((choice (expreg--read-region-choice (length regions))))
(when choice
(expreg--apply-region-selection choice regions))))
(expreg--cleanup-region-overlays)))))
;; ---------------------------------------------------------------------------
;; 收集连续扩张区域
;; ---------------------------------------------------------------------------
(defun expreg--collect-expansion-sequence ()
"Collect expansion regions by repeatedly calling expreg-expand."
(let ((regions '())
(original-point (point))
(original-mark (when (region-active-p) (mark)))
(max-expansions 9))
(save-excursion
(save-restriction
(goto-char original-point)
(deactivate-mark)
(dotimes (i max-expansions)
(condition-case nil
(let ((before-beg (if (region-active-p) (region-beginning) (point)))
(before-end (if (region-active-p) (region-end) (point))))
(if (fboundp 'expreg-expand)
(call-interactively 'expreg-expand)
(error "expreg-expand function not found"))
(when (region-active-p)
(let ((new-beg (region-beginning))
(new-end (region-end)))
(unless (and (= new-beg before-beg) (= new-end before-end))
(let ((new-region (cons new-beg new-end)))
(unless (member new-region regions)
(push new-region regions)))))))
(error (cl-return))))))
(goto-char original-point)
(if original-mark
(progn (set-mark original-mark) (activate-mark))
(deactivate-mark))
(reverse regions)))
;; ---------------------------------------------------------------------------
;; 显示数字标签
;; ---------------------------------------------------------------------------
(defun expreg--show-region-numbers (regions)
"Display number labels for each expansion region."
(setq expreg--region-overlays nil)
(cl-loop for region in regions
for i from 1 to (min (length regions) 9)
do (setq expreg--region-overlays
(append (expreg--create-number-overlay (car region) (cdr region) i)
expreg--region-overlays))))
;; ---------------------------------------------------------------------------
;; 创建纯数字标签(无括号,无背景)
;; ---------------------------------------------------------------------------
(defun expreg--create-number-overlay (beg end number)
"Left: N Right: N Bright yellow."
(let ((ov-left (make-overlay beg beg))
(ov-right (make-overlay end end))
(str (number-to-string number)))
(overlay-put ov-left 'before-string
(propertize str 'face 'expreg-number-face 'display '(raise 0.2)))
(overlay-put ov-right 'after-string
(propertize str 'face 'expreg-number-face 'display '(raise 0.2)))
(list ov-left ov-right)))
;; ---------------------------------------------------------------------------
;; 读取选择
;; ---------------------------------------------------------------------------
(defun expreg--read-region-choice (max-regions)
(let ((prompt (format "Choose region (1–%d, or q to quit): " (min max-regions 9))))
(let ((char (read-char prompt)))
(cond
((and (>= char ?1) (<= char ?9))
(let ((choice (- char ?0)))
(if (<= choice max-regions) choice
(progn (message "Invalid choice: %d" choice) nil))))
((or (= char ?q) (= char ?\C-g)) (message "Selection cancelled") nil)
(t (message "Invalid input: %c" char) nil)))))
;; ---------------------------------------------------------------------------
;; 应用选择
;; ---------------------------------------------------------------------------
(defun expreg--apply-region-selection (choice regions)
(let ((selected-region (nth (1- choice) regions)))
(when selected-region
(goto-char (car selected-region))
(set-mark (cdr selected-region))
(activate-mark)
(message "Selected region %d: %d–%d"
choice (car selected-region) (cdr selected-region)))))
;; ---------------------------------------------------------------------------
;; 清理
;; ---------------------------------------------------------------------------
(defun expreg--cleanup-region-overlays ()
(when expreg--region-overlays
(mapc #'delete-overlay expreg--region-overlays)
(setq expreg--region-overlays nil)))
;; ---------------------------------------------------------------------------
;; 前缀命令
;; ---------------------------------------------------------------------------
(defun expreg-expand-region-interactive (&optional arg)
(interactive "P")
(cond
((and (numberp arg) (> arg 0))
(dotimes (_ arg)
(condition-case nil
(call-interactively 'expreg-expand)
(error (message "Cannot expand further") (cl-return)))))
((equal arg '(4)) (expreg-expand-with-numbers))
(t (if (fboundp 'expreg-expand)
(call-interactively 'expreg-expand)
(message "expreg-expand function not available")))))
;; ---------------------------------------------------------------------------
;; 键绑定
;; ---------------------------------------------------------------------------
(defun expreg-setup-numeric-bindings ()
(global-set-key (kbd "M-=") 'expreg-expand-region-interactive)
(global-set-key (kbd "C-M-=") 'expreg-expand-with-numbers))
;; ---------------------------------------------------------------------------
;; 一次性初始化
;; ---------------------------------------------------------------------------
(defun expreg-numeric-selection-init ()
(expreg-setup-numeric-bindings)
(message "Expreg numeric selection initialized"))
(provide 'expreg-numeric-selection)
;;; expreg-numeric-selection.el ends here