時間:2023-07-26 07:12:02 | 來源:網(wǎng)站運營
時間:2023-07-26 07:12:02 來源:網(wǎng)站運營
20.使用org-mode管理瀏覽器書簽:#東方Project あたいってばさいきょ?ね?。?! - なにょち的插畫 - pixiv^G
正則得到的結(jié)果。 query-replace
有點像,也許可以考慮使用相似方法在 emacs 中實現(xiàn)。 pip install buku
后得到了這樣的結(jié)果… M-x info
再找 Org,為了寫這一部分我花了兩天時間把整個文檔讀了一遍)。當然我更建議讀 Org Mode Compact Guide,這個更加簡單。 NAMEDESCRIPTION
或是 URL
等固定名字了。這里有篇文章可作參考:bookmarking with org-modeC-c C-x C-w
(org-cut-special)來刪除一整個標題的內(nèi)容。 * Search Engine:PROPERTY::Is-Folder: t:END:** Baidu:PROPERTIES::Is-Folder : nil:END:www.baidu.com** google:PROPERTIES::Is-Folder : nil:END:www.google.com......
不過我不打算使用這種分層分類的方式,如上文所見,我不是太喜歡它,分類層級太多的話查找起來并不方便。我準備直接使用類似表格的格式,也就是只使用同一級標題表示書簽,這樣實現(xiàn)起來也更加方便。 :ARCHIVE:
的 tag 即可。使用 org-agenda 還可以對歸檔文件進行方便地搜索。 C-c C-o
即可在默認瀏覽器中打開鏈接,但這還是比不上從瀏覽器中直接點方便。要是能夠同步 org 文件和書簽欄的話效果應該挺不錯的,這就需要我去學習怎么寫插件了。使用數(shù)據(jù)庫來與瀏覽器交互應該會更好,所以等 29 吧(笑)。 [ ]
如果使用 sqlite 就可對數(shù)據(jù)進行加密(免費版好像不行…,需要使用 SEE 加密工具),這樣應該會更加安全一點,也許可以做一個寫入和讀出數(shù)據(jù)庫的功能,實現(xiàn) org 文本和數(shù)據(jù)庫的無縫轉(zhuǎn)換[ ]
如果功能足夠豐富的話,可以考慮寫個 minor-mode[X]
添加下載網(wǎng)頁的功能,把值得收藏的網(wǎng)頁下載并存儲下來url
和 description
可使用 org 的默認格式表示: [[link][description]]
。當在標題上按下 C-c C-o
或單擊鼠標時就可在瀏覽器打開該網(wǎng)頁tag
tag 直接放在標題后面,使用 :
分隔,舉例來說是這樣: :a:b:c:
PROPERTIES
里面存放鏈接添加時間等日常無需了解的數(shù)據(jù)text
放在標題的正文部分,對書簽的內(nèi)容做進一步說明* [[https://baidu.com][百度一下,你就知道]] :search:ATTACH::PROPERTIES::ID: 114514-191981:YYOB-CREATE-TIME: [2022-07-27 Wed 19:36]:YYOB-ID: 1:YYOB-MD5: c4ca4238a0b923820dcc509a6f75849b:END:百度,一個搜索引擎......
在上面的例子中, :search:
就是 tag, :PROPERTIES:
中的 :ID:
就是 attach 的 ID 值,用來索引保存的文件位置。 :YYOB-CREATE-TIME:
就是創(chuàng)建時間, :END:
后面的文本就是詳細描述部分,這部分的內(nèi)容就隨意了。 org-map-entries
遍歷文件中的所有標題org-heading-components
獲取標題的一些狀態(tài),具體內(nèi)容可 C-h f
org-entry-get
org-entry-put
獲取和設置屬性值org-map-tree
遍歷所有嵌套的標題yyorg-bookmark
,鏈接放在本節(jié)的最后。首先從設計思路上來說吧。 t-
而不是 yyorg-bookmark-
,emacs 在讀取時會自動轉(zhuǎn)換。yyorg-bookmark
里。 #+NAME: startup#+BEGIN_SRC emacs-lisp(your-code-here)#+END_SRC...# Local Variables:# org-confirm-babel-evaluate: nil# eval: (progn (org-babel-goto-named-src-block "startup") (org-babel-execute-src-block) (outline-hide-sublevels 1))# End:
通過將變量使用 setq-local
設置就可設置 buffer 局部變量,這樣就不容易引起 buffer 間沖突。同時代碼塊里也可以包含一些專用于 buffer 的管理函數(shù),它們可以是 yyorg-bookmark
的函數(shù)的包裝,或是自己定義的管理函數(shù)。 yyorg-bookmark-enchant
的命令,使用該命令即可將模板文件附加到當前 buffer 末尾,這樣完成了一個 yyorg
書簽數(shù)據(jù)庫的建立,完成了對 buffer 的“附魔”(笑)。 symbol-value
來獲取。那要如何獲取書簽文件的 buffer 呢?好在 org-mode 提供了一個模板名與文件對應的關聯(lián)表 org-capture-templates
,在進行內(nèi)容捕獲時,org-mode 根據(jù)它來選擇對應的模板,并寫入對應的文件。 (yyorg-bookmark--template-filename key)
,根據(jù) org-capture-templates
和模板名獲取捕獲的目標文件(defun t-get-local-value (key symbol) "get buffer-local value in target file" (let* ((filename (t--template-filename key)) (buf (get-file-buffer filename))) (save-current-buffer (set-buffer buf) (symbol-value symbol))))(defun t-set-local-value (key symbol value) "set buffer-local value in target file" (let* ((filename (t--template-filename key)) (buf (get-file-buffer filename))) (save-current-buffer (set-buffer buf) (set symbol value))))
當然這也帶來一個問題,代碼變長了不少(畢竟是打洞做法……) org-capture-templates
添加/刪除的處理。它是我這個包里最重要的全局資源,用來關聯(lián)模板和書簽文件。為了避免出現(xiàn)一些低級錯誤,比如類型錯誤,模板錯誤等,需要對添加過程做一些檢查。同時考慮到它的全局性,在添加同名模板時也要檢查是否沖突,由用戶來決定是否覆蓋已存在的同名模板。 yyorg-bookmark-add-template
函數(shù)來添加模板,一個簡單的例子如下,這是附魔文件里的例子模板: (yyorg-bookmark-add-template :key "l" :desc "Add browser bookmark" :type 'entry :target `(file+headline ,(buffer-file-name) "Bookmarks") :temp "* %c %^g/n:PROPERTIES:/n:YYOB-CREATE-TIME: %T/n:YYOB-ID: %(yyorg-bookmark-control-key-counter /"l/")/n:END:" :props '(:prepend t)))
除了添加外也要考慮刪除,我還編寫了 yyorg-bookmark-remove-template
用于從 minibuffer 中選擇并刪除模板。 (defun t-remove-template (key) "remove a template from `org-capture-templates'use minibuffer to select a key" (interactive (list (completing-read "key: " (t--template-keys) nil t))) (setq org-capture-templates (cl-delete-if (lambda (x) (string= key (car x))) org-capture-templates)))
再然后就是對屬性值的操作,org-mode 提供了一些函數(shù): org-entry-get
,獲取某一點所在 HEADLINE 的屬性值org-entry-put
,設置某一點所在 HEADLINE 的屬性值org-find-entry
,尋找第一個匹配的屬性值,返回位置org-find-entry
查找屬性位置: (defun t--get-property (pname &optional on-headline) "return string if found, or nil if not" (let ((place (if on-headline (point) (org-find-property pname)))) (if place (org-entry-get place pname) nil)))(defun t--set-property (pname strval &optional on-headline) "set property `pname' if found and return t, or nil if notif on-headline is set and point is on headlinethis function will always success" (let ((place (if on-headline (point) (org-find-property pname)))) (if place (prog1 t (org-entry-put place pname strval)) nil)))
另外,由于 org-mode 中屬性值都是以字符串保存的,如果要進行數(shù)學運算并不方便。我添加了一些計數(shù)器操作,可以較方便的對某個屬性值進行自增和自減,最終的可用函數(shù)如下: (defun t-control-counter (pname op &optional on-headline) "control counter's value'+ is add1, '- is sub1, 'r is reset to 0, 'z is unchangereturn the origin value" (cl-case op ((+) (t-increase-counter pname on-headline)) ((-) (t-decrease-counter pname on-headline)) ((r) (t-reset-counter pname on-headline)) ((z) (t--get-property pname on-headline)) (t (error "unrecognized op %s" op))))
最后是對標題屬性值的枚舉,可以獲取所有 HEADLINE 的屬性值,這個函數(shù)可配合 emacs 的 narrow
功能實現(xiàn)區(qū)域枚舉。 (defun t-get-all-entries-properties (pnames) "get all entries specific propertyreturn form is ( ((p1 . v1) (p2 . v2) ...) ... )in other words, return value is a nested alistyou can use it with narrow" (let ((pro-list)) (org-map-tree (lambda () (let ((a (org-entry-properties)) (b)) (mapc (lambda (x) (let ((c (assoc x a))) (when c (push c b)))) pnames) (when b (push b pro-list))))) (reverse pro-list)))
上面這些函數(shù)基本上就是 yyorg-bookmark.el
文件中實現(xiàn)的功能了,接下來我們來到附魔模板的代碼編寫,來實現(xiàn)一些更加貼近用戶的操作。 yyorg-bookmark
,這里不使用 yyorg-bookmark-add-template
函數(shù): (add-to-list 'org-capture-templates `("l" "Add browser bookmark" entry (file+headline ,(buffer-file-name) "Bookmarks") "* %c/n:PROPERTIES:/n:TIME: %T/n:END:" :prepend t))
上面這段代碼的作用是將模板 "l"
添加到 org-capture-templates
中。這里目標選擇當前 buffer 對應文件,HEADLINE 選擇 Bookmark,屬性選擇 :prepent t
,這表示將新的項添加到最前。完整版的例子在代碼倉庫的附魔模板文件中。 M-x org-capture
,然后選中 l
,你可以看到剪切板中的內(nèi)容被放到了添加項的標題中, TIME
屬性值成為了當前時間。接著按下 C-c C-c
完成捕獲。動圖如下所示: org-capture
后,"Hello world" 出現(xiàn)在了標題位置,這是 %c
的作用,其他的特殊符號可參考官方文檔。 org-capture
,更要命的是我從來不用蘋果的筆記本電腦。 org-protocol
。 emacsclient file
命令在已啟動的 emacs 中打開文件,這樣就不會有多個 emacs 實例了,再也不用擔心 emacs 啟動太慢了(笑)。 (require 'server)(unless (eq (server-running-p) t) (server-start))
org-protocol 默認支持三種協(xié)議,我們要使用的那一種是 capture
,傳遞給 emacsclient 的字符串是這樣的一個格式: emacsclient "org-protocol://capture?template=X&url=URL&title=TITLE&body=BODY"
調(diào)用 emacsclient 后, org-capture
會使用模板 X
來處理捕獲內(nèi)容,并完成捕獲??梢钥吹缴厦娴膬?nèi)容包括三個部分,分別是 url,標題和內(nèi)容,使用文檔中的對應的特殊符號即可在 org-capture
模板中獲取這些字符串。通過設置一些選項, org-capture
可以不需要 C-c C-c
確認而直接完成捕獲過程,這樣就可以一鍵捕獲了。 REGEDIT4; see https://orgmode.org/worg/org-contrib/org-protocol.html; and https://github.com/sprig/org-capture-extension[HKEY_CLASSES_ROOT/org-protocol]@="URL:Org Protocol""URL Protocol"=""[HKEY_CLASSES_ROOT/org-protocol/shell][HKEY_CLASSES_ROOT/org-protocol/shell/open][HKEY_CLASSES_ROOT/org-protocol/shell/open/command]; use you own path to emacsclientw.exe@="/"path//to//your//emacs//bin//emacsclientw.exe" /"%1/""
具體原理可以參考 “有個網(wǎng)站想打開此應用”原理是什么?,這里直接摘過來了: 作者:Hawaii在添加相應的注冊表項后,當你在瀏覽器地址欄中輸入類似
鏈接:https://www.zhihu.com/question/410173377/answer/1366638756
來源:本站
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
1.瀏覽器解析URL,得到協(xié)議部分thunder://
2.瀏覽器嘗試在已知的協(xié)議列表中匹配thunder協(xié)議
3.thunder不是已知協(xié)議,瀏覽器轉(zhuǎn)而在注冊表中查找thunder協(xié)議的注冊信息,也即HKEY_CLASSES_ROOT/thunder這個鍵
4.瀏覽器使用這個鍵下的Shell/Open/command子鍵的值作為運行此協(xié)議的程序路徑,并將URL的路徑部分作為程序的參數(shù)
5.瀏覽器彈出提示框“有個網(wǎng)站想打開此應用”,詢問用戶是否要執(zhí)行此協(xié)議關聯(lián)的程序。
org-protocol://capture?template=l&url=baidu.com&title=百度一下你就知道&body=hello
的 url 時,瀏覽器就會提示你是否運行 emacsclient,點擊運行即可執(zhí)行捕獲動作。 location.href = 'org-protocol://capture?template=' + key + '&url=' + encodeURIComponent(location.href) + '&title=' + encodeURIComponent(document.title) + '&body=' + encodeURIComponent(window.getSelection());// use this for bookmarkjavascript:location.href='org-protocol://capture?template='+'yyobp'+'&url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title)+'&body='+encodeURIComponent(window.getSelection());
在一些瀏覽器中你可以將那一長條代碼放到書簽地址中,然后點擊書簽即可實現(xiàn)捕獲。我在 firefox 和 edge 上進行了嘗試,firefox 可行但 edge 不可行。edge 不允許從書簽處執(zhí)行 JS 代碼。使用書簽不能適用于所有瀏覽器。下圖是 firefox 的編輯書簽對話框: org-capture
的插件,這里是源代碼及文檔。按照它的說明配置好 emacs 后,點擊瀏覽器插件的那個馬頭(還是獨角獸?)就可以一鍵保存了。很可惜這個插件在 edge 上并沒有。 // ==UserScript==// @name yyob-add-bookmark// @namespace http://tampermonkey.net/// @version 0.1// @description use org-protocol and tm-script to add bookmark// @author include-yy// @match *://*/*// @grant unsafeWindow// @grant GM_registerMenuCommand// ==/UserScript==(function() { 'use strict'; // Your code here... // all templates // [key, description, accesskey] // comment or uncomment to add/remove item let all = [ ['yyobp', 'Add Bookmark', 'a'], ['L', 'add bk 2', 'p'] ]; let i = 0; // https://stackoverflow.com/questions/25750183/how-to-create-a-toolbar-button-for-a-chrome-tampermonkey-user-script // how to add MenuCommand for (i = 0; i < all.length; i++) { let name = all[i][0]; let desc = all[i][1]; let hotkey = all[i][2]; GM_registerMenuCommand(desc, function() { main(name); }, hotkey); } // https://github.com/toure00/org-capture-tag-bookmark // how to capture link and description function main (key) { location.href = 'org-protocol://capture?template=' + key + '&url=' + encodeURIComponent(location.href) + '&title=' + encodeURIComponent(document.title) + '&body=' + encodeURIComponent(window.getSelection()); } // my original thought was to use radio/checkbox dialog to add or remove template to use // but I found it easier to just add/remove a list in a list variable :p // if you want to do like this, you can refer to // https://stackoverflow.com/questions/11668111/how-do-i-pop-up-a-custom-form-dialog-in-a-greasemonkey-script // and https://github.com/toure00/org-capture-tag-bookmark // if you want to use jQuery, just paste blow line to the ==userscript== block // @require https://code.jquery.com/jquery-2.1.4.min.js})();
https://www.zhihu.com/video/1537991207703166976下面是上面演示中使用的捕獲模板, template
部分看著非常別扭,下面會解釋原因: (yyorg-bookmark-add-template :key "yyobp" :desc "Add browser bookmark" :type 'entry :target `(file+headline ,(buffer-file-name) "Bookmarks") :temp "* [[%:link][%:description]] %(yyorg-bookmark-add-repeat-tag (md5 /"%:link/") (yyorg-bookmark-get-local-value /"yyobp/" 'yyob-hashtable) 'gethash)/n:PROPERTIES:/n:YYOB-ID: %(if (string= (yyorg-bookmark-add-repeat-tag (md5 /"%:link/") (yyorg-bookmark-get-local-value /"yyobp/" 'yyob-hashtable) 'gethash) /"/") (progn (puthash (md5 /"%:link/") (yyorg-bookmark-control-key-counter /"yyobp/" 'z) (yyorg-bookmark-get-local-value /"yyobp/" 'yyob-hashtable)) (yyorg-bookmark-control-key-counter /"yyobp/")) (gethash (md5 /"%:link/") (yyorg-bookmark-get-local-value /"yyobp/" 'yyob-hashtable)))/n:YYOB-CREATE-TIME: %T/n:YYOB-MD5: %(md5 /"%:link/")/n:END:%(if (string= /"/" /"%i/") /"/" /"/n%i/")" :props '(:prepend t :immediate-finish t :jump-to-captured t)))
這一部分我參考的資料有很多: org-cut-subtree
( C-c C-x C-w
)來刪除整一個書簽的內(nèi)容。 C-c k
來刪除書簽,使用 C-c i
來添加書簽(信息)。與普通的文本操作不同,這兩個操作會修改一些管理信息。 :repeat:
tag。 C-c k
上。與之相反, C-c i
的作用是將項的 信息 添加到哈希表中,若信息已存在則不進行操作。 C-c k
刪除了某書簽,但是我們又想讓它恢復到?jīng)]有刪除之前的狀態(tài),那可以 C-/
(undo)然后使用 C-c i
將書簽信息重新添加到哈希表中。 C-c r
快捷鍵,它根據(jù)當前的書簽項來刷新哈希表,你可以多次刪除多個書簽后直接使用它,而不需要使用多次 C-c k
。 %^g
),添加 tag 可將光標移至 headline 處并按下 C-c C-c
,然后 emacs 會提提供一些已存在的 tag 供你選擇。這些沒什么好說的,下面參考官方文檔簡單提一下嵌套 tag 的寫法。 # 注意空格,所有的空格都是必要的#+TAGS: [ GTD : Control Persp ]#+TAGS: [ Control : Context Task ]#+TAGS: [ Persp : Vision Goal AOF Project ]
C-c C-a a
添加文件后 org-mode 會給標題分配一個唯一的 ID,以及和 ID 關聯(lián)的文件夾,附加的文件默認會復制到該文件夾內(nèi)。使用 C-c C-a o
可打開文件夾內(nèi)某一文件,使用 C-c C-a f
可在 emacs 中打開該文件目錄。 (defun t-get-url-from-link (str) "get link from [[link][description]]" (cl-assert (string= (substring str 0 2) "[[")) (let ((i 0)) (while (and (not (= (aref str i) ?/])) (< i (length str))) (cl-incf i)) (if (= i (length str)) (error "link not found") (substring str 2 i))));; https://stackoverflow.com/questions/13505113/how-to-open-the-native-cmd-exe-window-in-emacs;; https://www.tecmint.com/wget-download-file-to-specific-directory/;; https://www.anycodings.com/1questions/2463613/is-it-possible-for-wget-to-flatten-the-result-directories(defun t-attach-use-wget (link) "-E -H -k -K -p -nd -e robots=off -P target-directory used only on windows just to modify cmd to bash and something else to adapt to linux or use advice" (let* ((dir-path (org-attach-dir-get-create)) (wget-exe (or t-wget-path "wget"))) (let ((proc (start-process "yyob-wget" nil "cmd.exe" "/C" "start" "cmd.exe" "/K" wget-exe "-E" "-k" "-K" "-p" "-nd" "-e" "robots=off" link "-P" dir-path))) (set-process-query-on-exit-flag proc nil))))
在 windows 上使用需要配置 yyorg-wget-path
為 wget
的絕對路徑,不過由于我現(xiàn)在懶得弄 linux,我也沒有寫使用 bash 的 linux 版本,我將下載鍵綁定在了 C-c u
上。org-attach 提供的默認下載功能太弱,不建議使用。 C-c [
把 buffer 加入到它的搜索列表中,如果想要移除某 buffer 就在該 buffer 中按下 C-c ]
。使用 M-x org-agenda
即可進入搜索選擇界面,它提供了非常多的選擇,org-mode 建議將該命令綁定到 C-c a
上: (global-set-key (bkd "C-c a") 'org-agenda)
我在書簽文件中添加了局部快捷鍵 C-c m
,它可以直接清空 org-agenda 使用的文件表,這樣就不用一個一個 C-c ]
了。 t
列出所有的 TODO
項, T
列出帶有特殊 TODO
標志的項m
搜索 tag/prop/todo, M
只對 TODO
項進行搜索s
關鍵詞搜索, S
只對 TODO
項進行搜索/
使用多 buffer occur
進行搜索?
找到帶有 :FLAGGED:
tag 的項#
列出所有阻塞的項目yyorg-bookmark
的全部功能,感興趣的話可以自己動手,在附魔模板的基礎上添加自己想要的功能。 關鍵詞:書簽,瀏覽,管理,使用
微信公眾號
版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。