Improve the xkcd custom org link, add completion

This commit is contained in:
tecosaur 2020-05-16 02:02:49 +08:00
parent cc68c303ac
commit 358051b0ee
1 changed files with 102 additions and 17 deletions

View File

@ -1914,39 +1914,124 @@ The radar chart is a lot more involved, and I've added the following keys
This sets the number of ticks. Only works for \(n>2\), or \(n=0\) in which
case no ticks are shown.
**** Extra links
Let's start off with an xkcd link, why not.
Nice youtube embed as well, for fun.
***** xkcd
Because xkcd is cool, let's make it as easy and fun as possible to insert them.
Saving seconds adds up after all! (but only so much)
[[xkcd:1205]]
#+BEGIN_SRC emacs-lisp
(after! org
(org-link-set-parameters "xkcd"
:image-data-fun #'+org-xkcd-image-fn
:follow #'+org-xkcd-open-fn
:export #'+org-xkcd-export)
:export #'+org-xkcd-export
:complete #'+org-xkcd-complete)
(defun +org-xkcd-open-fn (link)
(+org-xkcd-image-fn nil link nil))
(defun +org-xkcd-fetch-info (num)
"Fetch the parsed json info for comic NUM"
(require 'xkcd)
(let* ((url (format "http://xkcd.com/%d/info.0.json" num))
(out (xkcd-get-json url num))
(json-assoc (json-read-from-string out)))
(json-assoc
(if (assoc num +org-xkcd-stored-info)
(assoc num +org-xkcd-stored-info)
(json-read-from-string (xkcd-get-json url num)))))
json-assoc))
(defun +org-xkcd-image-fn (_protocol link _description)
(defvar +org-xkcd-latest-num 0
"Latest xkcd number")
(defun +org-xkcd-complete (&optional arg)
"Complete xkcd using `+org-xkcd-stored-info'"
(+org-xkcd-update-stored-info)
(concat "xkcd:" (let ((num
(ivy-read (format "xkcd (%s): " +org-xkcd-latest-num)
(mapcar (lambda (info-assoc)
(format "%-4s %-30s %s"
(propertize (number-to-string (car info-assoc))
'face 'counsel-key-binding)
(cdr (assoc 'title info-assoc))
(propertize (cdr (assoc 'alt info-assoc))
'face '(variable-pitch font-lock-comment-face))))
+org-xkcd-stored-info))))
(if (equal "" num) (number-to-string +org-xkcd-latest-num)
(replace-regexp-in-string "\\([0-9]+\\).*" "\\1" num)))))
;; initialise `+org-xkcd-latest-num' and `+org-xkcd-stored-info' with latest xkcd
(add-transient-hook! '+org-xkcd-complete
(let* ((out (xkcd-get-json "http://xkcd.com/info.0.json" 0))
(json-assoc (json-read-from-string out)))
(setq +org-xkcd-latest-num (cdr (assoc 'num json-assoc)))
(setq +org-xkcd-stored-info `((,+org-xkcd-latest-num . ,json-assoc)))))
(defvar +org-xkcd-stored-info nil
"Basic info on downloaded xkcds, in the form ((num . title) ...)")
(defun +org-xkcd-update-stored-info ()
"Compare the json files in `xkcd-cache-dir' to the info in `+org-xkcd-stored-info'
and ensure that `+org-xkcd-stored-info' has info for every file"
(let* ((file-nums (mapcar (lambda (f) (string-to-number (replace-regexp-in-string "\\.json" "" f)))
(directory-files xkcd-cache-dir nil "\\.json")))
(stored-nums (mapcar #'car +org-xkcd-stored-info))
(new-nums (set-difference file-nums stored-nums)))
(dolist (num new-nums)
(let ((xkcd-info (+org-xkcd-fetch-info num)))
(push `(,num . ,xkcd-info) +org-xkcd-stored-info)))))
(defadvice! xkcd-get-json--and-cache (url &optional num)
"Fetch the Json coming from URL.
If the file NUM.json exists, use it instead.
If NUM is 0, always download from URL.
The return value is a string."
:override #'xkcd-get-json
(let* ((file (format "%s%d.json" xkcd-cache-dir num))
(cached (and (file-exists-p file) (not (eq num 0))))
(out (with-current-buffer (if cached
(find-file file)
(url-retrieve-synchronously url))
(goto-char (point-min))
(unless cached (re-search-forward "^$"))
(prog1
(buffer-substring-no-properties (point) (point-max))
(kill-buffer (current-buffer))))))
(unless (or cached (eq num 0))
(xkcd-cache-json num out))
out))
(defun +org-xkcd-image-fn (protocol link description)
"Get image data for xkcd num LINK"
(let* ((json-assoc (+org-xkcd-fetch-info (string-to-number link)))
(img (cdr (assoc 'img json-assoc)))
(alt (cdr (assoc 'alt json-assoc))))
(message alt)
(+org-http-image-data-fn "https" (substring img 6) nil)))
(defun +org-xkcd-export (path desc backend _com)
(let* ((json-assoc (+org-xkcd-fetch-info (string-to-number path)))
(img (cdr (assoc 'img json-assoc)))
(alt (cdr (assoc 'alt json-assoc)))
(title (cdr (assoc 'title json-assoc))))
(cond ((org-export-derived-backend-p backend 'html)
(format "<img src='%s' title='%s' alt='%s'>" img alt title))
((org-export-derived-backend-p backend 'latex)
(format "\\href{https://xkcd.com/%s}{%s}" path (or desc (concat "xkcd: " title))))
(t (format "https://xkcd.com/%s" path)))))
(+org-image-file-data-fn protocol (xkcd-download img (string-to-number link)) description)))
(defun +org-xkcd-export (path desc backend _com)
"Convert xkcd to html/LaTeX form"
(let* ((json-assoc (+org-xkcd-fetch-info (string-to-number path)))
(img (cdr (assoc 'img json-assoc)))
(alt (cdr (assoc 'alt json-assoc)))
(title (cdr (assoc 'title json-assoc)))
(file (xkcd-download img (string-to-number path))))
(cond ((org-export-derived-backend-p backend 'html)
(format "<img src='%s' title=\"%s\" alt='%s'>" img (subst-char-in-string ?\" ?“ alt) title))
((org-export-derived-backend-p backend 'latex)
(format "\\begin{figure}[!htb]
\\centering
\\includegraphics[scale=0.4]{%s}
\\caption*{\\label{xkcd:%s} %s}
\\end{figure}" file path (or desc
(format "\\textbf{%s} %s" title alt))))
(t (format "https://xkcd.com/%s" path))))))
#+END_SRC
***** YouTube
The ~[[yt:...]]~ links preview nicely, but don't export nicely. Thankfully, we can
fix that.
#+BEGIN_SRC emacs-lisp
(after! org
(org-link-set-parameters "yt" :export #'+org-export-yt)
(defun +org-export-yt (path desc backend _com)
(cond ((org-export-derived-backend-p backend 'html)