/
init-scholar-annotations.lisp
117 lines (105 loc) · 5.04 KB
/
init-scholar-annotations.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
(in-package :nyxt-user)
(defvar *scholar-annotation-style* "font-size: large; color: red; font-weight: bold"
"CSS style to be assigned to scholar annotations.")
(define-parenscript collect-scholar-references-on-page ()
(ps:let ((paper-ids (ps:*array))
(papers (ps:chain document
(query-selector-all ".gs_scl.gs_or.gs_r"))))
(ps:for ((i 0)) ((< i (length papers))) ((incf i))
(ps:let*
((paper (ps:getprop papers i))
;; (url (ps:@ (ps:chain paper
;; (query-selector ".gs_ri > .gs_fl"))
;; children 2
;; href))
;; (id (ps:chain (-reg-exp ".*scholar\\?cites=([0-9]+)&.*")
;; (exec url)))
(data-did (ps:getprop (ps:chain paper dataset) "did")))
;; (ps:if (not id) ps:continue)
;; (ps:setq id (ps:getprop id 1))
(ps:chain paper-ids (push data-did))))
paper-ids))
(define-parenscript annotate-scholar-entries-by-id (id text)
(ps:let* ((paper (ps:chain document
(query-selector
(ps:lisp (concatenate 'string "[data-did=\"" id "\"]")))))
(annotation (ps:if paper
(ps:chain document (create-element "h4")))))
(ps:when paper
(ps:setf (ps:chain annotation style) (ps:lisp *scholar-annotation-style*))
(ps:setf (ps:inner-html annotation) (ps:lisp text))
(ps:chain paper (append-child annotation))
)))
(define-parenscript find-scholar-paper-title-by-id (id)
(ps:let ((paper (ps:chain document
(query-selector
(ps:lisp (concatenate 'string "[data-did=\"" id "\"]"))))))
(ps:chain paper (query-selector "h3 > a") text)))
(define-class scholar-annotation (nyxt:annotation)
((gsc-id ""
:documentation "Google Scholar ID for reference.")
(paper-title ""
:documentation "Paper title of reference."))
(:export-class-name-p t)
(:export-accessor-names-p t)
(:accessor-name-transformer (class*:make-name-transformer name)))
(defmethod nyxt::render ((annotation scholar-annotation))
(spinneret:with-html-string
(:p (:b "Title: ") (paper-title annotation))
(:p (:b "Annotation: ") (data annotation))
(:p (:b "GSCID: ") (gsc-id annotation))
(:p (:b "Tags: ") (format nil "~{~a ~}" (tags annotation)))))
(defmacro with-user-provided-scholar-entry (id-sym &body body)
"Prompt user for a google scholar entry and then pass the selected
id to THEN."
(let ((lam-var-sym (gensym)))
`(nyxt/web-mode:query-hints
"Paper to annotate"
(lambda (,lam-var-sym) (when (and ,lam-var-sym (car ,lam-var-sym))
(let ((,id-sym (plump:get-attribute (car ,lam-var-sym) "id")))
,@body)))
:selector ".gs_scl.gs_or > .gs_ri > h3 a")))
(define-command-global add-scholar-annotation (&optional (buffer (current-buffer)))
"Create a annotation for a Google Scholar entry in BUFFER."
(with-current-buffer buffer
(with-user-provided-scholar-entry id
(let* ((data (prompt1
:prompt "Annotation"
:sources (list (make-instance 'prompter:raw-source
:name "Note"))))
(tags (prompt
:prompt "Tag(s)"
:sources (list (make-instance 'prompter:word-source
:name "New tags"
:multi-selection-p t))))
(annotation (make-instance
'scholar-annotation
:gsc-id id
:paper-title (find-scholar-paper-title-by-id id)
:data data
:tags tags)))
(annotate-scholar-entries-by-id id data)
(nyxt::annotation-add annotation)))))
(define-command show-scholar-annotations-for-page ()
"Update current buffer with any google-scholar annotations."
(let ((citations-on-page (collect-scholar-references-on-page))
(annotations (nyxt::annotations)))
(loop for annotation in annotations do
(when (and (scholar-annotation-p annotation)
(member (gsc-id annotation)
citations-on-page
:test #'equal))
(annotate-scholar-entries-by-id (gsc-id annotation) (data annotation))
))))
(defun update-scholar-entries-with-annotations-handler (buffer)
(let ((buffer-url (url buffer)))
(when (and
(or (quri.uri.http:uri-https-p buffer-url)
(quri.uri.http:uri-http-p buffer-url))
(equal (quri:uri-authority buffer-url) "scholar.google.com"))
(with-current-buffer buffer
(show-scholar-annotations-for-page)))))
(define-configuration web-buffer
((nyxt:buffer-loaded-hook
(hooks:add-hook %slot-default% #'update-scholar-entries-with-annotations-handler)
)))