gugu
1
我用chatgpt写了一段代码,用zotero打开相应的pdf文件。
原理是提取pdf最后两级路径,之后调用终端异步执行 open zotero://open-pdf/library/items/…(item-name/pdf-name)
因为zotero基本上是最好用的pdf软件,做笔记,与emacs联动都很方便。
目前缺点是,用zotero打开的同时,emacs中会用pdf-viewer-mode再打开一次pdf,这个缺点我目前无法解决,如果有兴趣,请帮忙解决,我相信这会很有用!
如果能把它做成一个minor mode,就更好了!
代码如下:
(defun open-pdf-in-zotero ()
"Open the current PDF file in Zotero."
(interactive)
(let* ((pdf-path buffer-file-name)
(pdf-name (file-name-nondirectory pdf-path))
(pdf-dir (file-name-directory pdf-path))
(parent-dir (file-name-nondirectory (directory-file-name pdf-dir)))
(grandparent-dir (file-name-nondirectory (directory-file-name (file-name-directory pdf-dir))))
(zotero-path (concat "zotero://open-pdf/library/items/" grandparent-dir "/" parent-dir "/" pdf-name)))
(async-start-process "open-zotero" "open" nil zotero-path)))
(add-hook 'pdf-view-mode-hook 'open-pdf-in-zotero)
谢谢!
1 个赞
gugu
2
另外,这个函数可以用zotero打开orb-note-actions和helm-bibtex中的链接。
其实只要zotero里面有这个条目,都可以用这个函数通过zotero打开,因为这个函数是和pdf-viewer-mode挂钩的。希望能实现以下功能:
当zotero库中有这个条目时,只用zotero打开,不用pdf-iewer-mode打开。
当zotero库中没有这个条目时,用openwith-mode打开。(openwith在windows上可以设置成sumatra,在linux上可以设置成evince)
并且把这个mode设置成zotero-mode,如上所述,它是先于openwith-mode的。
进阶:制作一个在org中的页数标签,可以与orb的链接一起插入文本中。点击这个链接,就自动跳转到zotero的那一个文档的那一页。
关于为什么不用org-noter:因为太老旧了,pdf滚动太慢。不能直接和orb联动。并且不能直接创建一个文献笔记页面。
关于为什么不用eaf-pdf-viewer:尝试了几天用linux安装,安装之后不能运行。这应该是我的技术问题,不过这也反映出,安装对新手来说是复杂的,各平台安装方法也不一样,有些难度,各平台和各桌面环境支持程度也不一。另外,zotero功能可能要多点。
这个zotero函数像是低配版的org-noter加上eaf-pdf-viewer。希望能够体谅emacs新手的不足!
1 个赞
eaf安装不能运行, 请看中文README底部, 写的有解决方案, 一般都是Python没有安装好。
你可能应该直接改orb-note-actions和helm-bibtex打开链接的方式,而不是打开 PDF 之后再 hook
1 个赞
(defun private/open-in-zotero (citekey)
"Open a reference item in Zotero."
(interactive (list (citar-select-ref)))
(citar-file-open-external
(concat "zotero://select/items/@" citekey)))
可以通过 citekey 来打开文件,这里的 citar-file-open-external 不重要,只要有 citekey 了,拼出链接,后面总能打开文件。
2 个赞
gugu
6
谢谢你!不过我现在还不用citar,我目前在用org-ref,另外我想直接在pdf链接上操作,用zotero(优先)或者evince(次之)方式打开。
gugu
8
谢谢建议,我刚刚用chatgpt生成了段代码避免了这个问题,我等下附上。
gugu
9
下面这段代码解决了以上问题。
功能是:判断这个文件在不在zotero库里。如果在,则用zotero打开。如果不在,则用evince打开。emacs里面不会再用pdf-viewer-mode打开了。
直接粘在init文件里应该就可以用。这将替换emacs里所有pdf打开的方式。
evince也可以按需要替换成其他的软件。
(defun expand-tilde (path)
"Expand tilde in PATH to user's home directory."
(if (string-prefix-p "~" path)
(concat (getenv "HOME") (substring path 1))
path))
(defun open-pdf-in-zotero-or-evince (pdf-path)
"Open the PDF file at PDF-PATH in Zotero if it is in a Zotero storage directory, otherwise use Evince."
(setq pdf-path (expand-tilde pdf-path))
(if (string-match "/storage/" pdf-path)
(let* ((pdf-name (file-name-nondirectory pdf-path))
(pdf-dir (file-name-directory pdf-path))
(parent-dir (file-name-nondirectory (directory-file-name pdf-dir)))
(grandparent-dir (file-name-nondirectory (directory-file-name (file-name-directory pdf-dir))))
(zotero-path (concat "zotero://open-pdf/library/items/" grandparent-dir "/" parent-dir "/" pdf-name)))
(async-start-process "open-zotero" "open" nil zotero-path))
(async-start-process "open-evince" "evince" nil pdf-path)))
(defun my-find-file-advice (orig-fun &rest args)
"Advice function around ORIG-FUN to open PDFs in Zotero or Evince."
(let ((file (car args)))
(if (string-equal (file-name-extension file) "pdf")
(open-pdf-in-zotero-or-evince file)
(apply orig-fun args))))
(advice-add 'find-file :around #'my-find-file-advice)
1 个赞
gugu
10
以下是windows系统里的代码:
(defun expand-tilde (path)
"Expand tilde in PATH to user's home directory."
(if (string-prefix-p "~" path)
(concat (getenv "HOME") (substring path 1))
path))
(defun open-pdf-in-zotero-or-reader (pdf-path)
"Open the PDF file at PDF-PATH in Zotero if it is in a Zotero storage directory, otherwise use the default PDF reader."
(setq pdf-path (expand-tilde pdf-path))
(let ((zotero-path "D:/zotero_7/zotero.exe")
(zotero-uri nil))
(if (string-match "/storage/" pdf-path)
(let* ((pdf-name (file-name-nondirectory pdf-path))
(pdf-dir (file-name-directory pdf-path))
(parent-dir (file-name-nondirectory (directory-file-name pdf-dir)))
(grandparent-dir (file-name-nondirectory (directory-file-name (file-name-directory pdf-dir)))))
(setq zotero-uri (format "zotero://open-pdf/library/items/%s/%s/%s" grandparent-dir parent-dir pdf-name)))
(setq zotero-uri (format "zotero://open-pdf/library/items/%s" (file-name-sans-extension (file-name-nondirectory pdf-path)))))
(if (and (file-exists-p zotero-path) zotero-uri)
(progn
(start-process "zotero" nil zotero-path "-url" zotero-uri)
(message "Attempting to open PDF in Zotero..."))
(start-process "open-pdf" nil "explorer" pdf-path))))
(defun my-find-file-advice (orig-fun &rest args)
"Advice function around ORIG-FUN to open PDFs in Zotero or default PDF reader."
(let ((file (car args)))
(if (string-equal (file-name-extension file) "pdf")
(open-pdf-in-zotero-or-reader file)
(apply orig-fun args))))
(advice-add 'find-file :around #'my-find-file-advice)
1 个赞