org-mode 中能否创建指向某文件某个 region 的链接?

org-mode 有行号链接, 可以跳转到某一行, 有字符串链接, 可以跳转到某个字符串出现的位置, 我想问有 region 链接么, 比如 ::100-120, 这样跳转以后就自动 narrow-region 到 100-120 行?

可以写一个 hyperlink type 吧

info "(org) Adding Hyperlink Types"

可以在org 链接里嵌入elisp代码,这样点击跳转之后想做什么操作都可以

用 org-protocol 做到了, 下面这个代码有 2 个函数, 分别是 link handler 和 link generator. 生成链接的方法很简单, 选中一段区域然后执行 copy-open-file-pattern-link, 就会把 org-protocol 链接保存到剪切板. 这个链接就能打开了. 我并没有选择用行号来表示 region, 因为我觉得行号可能会变, 我修改了文本.

如图所示, handler 其实就是查找这两个字符串再 narrow 即可.

(defun org-protocol-open-file (pars)
  "Act as org-protocol-protocol-alist function with PARS as args.
Handle links like: org-protocol://open-file?file=/foo/ss/subdir/foo.js&line=132"
  (let ((file (substring (plist-get pars :file) 1)) (line (and (plist-get pars :line) (1- (string-to-number (or (plist-get pars :line) "1"))))) (pattern (plist-get pars :pattern)) (region-id (plist-get pars :region)) region-begin-position region-end-position)
    ;; (setq org-protocol-open-file-at-line pars)
    (find-file (and (file-exists-p file)
     file))
    (goto-char (point-min))
    (and line (forward-line line))
    (and pattern (search-forward pattern))
(when region-id
  (search-forward (concat "begin " region-id))
  (setq region-begin-position (line-beginning-position))
  (search-forward (concat "end " region-id))
  (setq region-end-position (line-end-position))
  (narrow-to-region region-begin-position region-end-position)
)))

(eval-after-load 'org-protocol
  (lambda ()
    (add-to-list 'org-protocol-protocol-alist
         '("open-file"
           :protocol "open-file"
           :function org-protocol-open-file))))

(defun copy-open-file-pattern-link (start end)
  (interactive "r")
(let (is-region-link region-id)
  (save-excursion
  (if (use-region-p)
; with region
(progn
  (setq is-region-link (and (equal start (line-beginning-position-of-pos start)) (equal end (line-beginning-position-of-pos end))))
  ;; pattern case, start 不是一行的开始或者 end 不是一行的结束
  (if is-region-link
(progn
  (setq region-id (random-string 5))
(goto-char start)
(goto-char (line-end-position))
(insert (concat " " comment-start "(begin " region-id ")") )
(goto-char end)
(goto-char (line-end-position))
(insert (concat " " comment-start "(end " region-id ")") )
(kill-new (concat "org-protocol://open-file?file=" (buffer-file-name) "&region=" region-id))
  )

;; pattern case, start 不是一行的开始或者 end 不是一行的结束
(progn
(let ((selected-text (buffer-substring start end)))
  (kill-new (concat "org-protocol://open-file?file=" (buffer-file-name) "&pattern=" selected-text))
  )
      )
      )
; no region
          )
(kill-new (concat "org-protocol://open-file?file=" (buffer-file-name))) 

  )
)
)
)
1 个赞