Browse code
Initial working commit
fiddlerwoaroof authored on 24/03/2016 04:11:23
Showing 5 changed files
Showing 5 changed files
1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,33 @@ |
1 |
+Simple command line utility to query the Index Thomisticus hosted on Corpus Thomisticum |
|
2 |
+and display the results. |
|
3 |
+ |
|
4 |
+# Installation: |
|
5 |
+ |
|
6 |
+To install from source: |
|
7 |
+ |
|
8 |
+- Get sbcl: [http://www.sbcl.org](http://www.sbcl.org) |
|
9 |
+- Get quicklisp: [https://www.quicklisp.org/beta/](https://www.quicklisp.org/beta/) |
|
10 |
+- Get buildapp: `sbcl --eval '(ql:quickload :buildapp)' --eval '(buildapp:build-buildapp)' --exit` |
|
11 |
+- Build this project: `./buildapp --load ~/quicklisp/setup.lisp --eval '(push (truename #p".") |
|
12 |
+ asdf:*central-registry*)' --load-system `basename $PWD` --entry indexthomisticus-client::main --output |
|
13 |
+ it-lookup --compress-core` |
|
14 |
+ |
|
15 |
+# Usage: |
|
16 |
+ |
|
17 |
+``` |
|
18 |
+./it-lookup '=ordo' '=dicit' |
|
19 |
+``` |
|
20 |
+ |
|
21 |
+This form displays the results for the query '=ordo =dicit' and prompts for further commands or queries. |
|
22 |
+Note that, if you use any of the search operators supported by corpus thomisticum, you probably should |
|
23 |
+quote the query: i.e. not `./it-lookup =ordo =dicit` but either `./it-lookup '=ordo' '=dicit'` or |
|
24 |
+`./it-lookup '=ordo =dicit'` |
|
25 |
+ |
|
26 |
+``` |
|
27 |
+./it-lookup |
|
28 |
+``` |
|
29 |
+ |
|
30 |
+This just prompts for commands or queries. |
|
31 |
+ |
|
32 |
+When at the `Query?` prompt, `next` will bring up the next page of results. `prev` brings up the previous |
|
33 |
+page of results. `quit` exits. and anything else is submitted as a query to Corpus Thomisticum. |
0 | 34 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,15 @@ |
1 |
+;;;; indexthomisticus-client.asd |
|
2 |
+ |
|
3 |
+(asdf:defsystem #:indexthomisticus-client |
|
4 |
+ :description "Describe indexthomisticus-client here" |
|
5 |
+ :author "Your Name <your.name@example.com>" |
|
6 |
+ :license "Specify license here" |
|
7 |
+ :depends-on (:alexandria |
|
8 |
+ :serapeum |
|
9 |
+ :fwoar.lisputils |
|
10 |
+ :drakma |
|
11 |
+ :lquery) |
|
12 |
+ :serial t |
|
13 |
+ :components ((:file "package") |
|
14 |
+ (:file "indexthomisticus-client"))) |
|
15 |
+ |
0 | 16 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,102 @@ |
1 |
+;;;; indexthomisticus-client.lisp |
|
2 |
+ |
|
3 |
+(in-package #:indexthomisticus-client) |
|
4 |
+ |
|
5 |
+;;; "indexthomisticus-client" goes here. Hacks and glory await! |
|
6 |
+ |
|
7 |
+(defparameter *post-url* "http://www.corpusthomisticum.org/it/index.age") |
|
8 |
+ |
|
9 |
+(defparameter *cookie-jar* (make-instance 'drakma:cookie-jar)) |
|
10 |
+ |
|
11 |
+(defun run-query (query &optional (page 1)) |
|
12 |
+ (drakma:http-request *post-url* |
|
13 |
+ :method :POST |
|
14 |
+ :parameters `(("text" . ,query) |
|
15 |
+ ("Form.option.concordances" . "concordances") |
|
16 |
+ ("results.currentPage" . ,(prin1-to-string page))) |
|
17 |
+ :cookie-jar *cookie-jar*)) |
|
18 |
+ |
|
19 |
+(defclass it-case () |
|
20 |
+ ((reference :initarg :reference :accessor case-reference) |
|
21 |
+ (text :initarg :text :accessor case-text))) |
|
22 |
+ |
|
23 |
+(defmethod initialize-instance :after ((object it-case) &key) |
|
24 |
+ (with-slots (reference text) object |
|
25 |
+ (when (arrayp reference) |
|
26 |
+ (setf reference (elt reference 0))) |
|
27 |
+ (when (plump:element-p reference) |
|
28 |
+ (setf reference (plump-dom:text reference))) |
|
29 |
+ (setf text (subseq text (+ (search reference text) (length reference)))) |
|
30 |
+ (setf reference (string-right-trim '(#\space) reference)) |
|
31 |
+ )) |
|
32 |
+ |
|
33 |
+(defmacro make-constructor (class &rest initargs) |
|
34 |
+ (let ((initarg-syms (mapcar #'(lambda (x) x (gensym)) initargs))) |
|
35 |
+ `(defun ,(intern (concatenate 'string (string 'make-) (string class))) ,initarg-syms |
|
36 |
+ (make-instance ',class ,@(loop for initarg in initargs |
|
37 |
+ for sym in initarg-syms |
|
38 |
+ nconc (list initarg sym)))))) |
|
39 |
+ |
|
40 |
+(make-constructor it-case :reference :text) |
|
41 |
+ |
|
42 |
+(defun parse-results (query-result) |
|
43 |
+ (lquery:$ (initialize query-result) "p[title]" (:combine ".ref" (text)) (map-apply #'make-it-case))) |
|
44 |
+ |
|
45 |
+(defun format-result (parsed-result &optional (stream t)) |
|
46 |
+ (with-slots (reference text) parsed-result |
|
47 |
+ (pprint-logical-block (stream nil) |
|
48 |
+ (princ reference stream) |
|
49 |
+ (pprint-indent :block 4 stream) |
|
50 |
+ (pprint-newline :mandatory stream) |
|
51 |
+ (pprint-logical-block (stream (split-sequence #\space text)) |
|
52 |
+ (loop |
|
53 |
+ (princ (pprint-pop) stream) |
|
54 |
+ (pprint-exit-if-list-exhausted) |
|
55 |
+ (princ #\space stream) |
|
56 |
+ (pprint-newline :fill stream)))))) |
|
57 |
+ |
|
58 |
+(defun format-results (parsed-results &optional (stream t)) |
|
59 |
+ (fresh-line stream) |
|
60 |
+ (loop :for parsed-results :across parsed-results |
|
61 |
+ :do (format-result parsed-results stream) |
|
62 |
+ :do (terpri stream))) |
|
63 |
+ |
|
64 |
+(defmacro compose-funcs ((&rest funcs) &rest args) |
|
65 |
+ `(funcall (compose ,@funcs) ,@args)) |
|
66 |
+ |
|
67 |
+(defun main (args) |
|
68 |
+ (handler-case |
|
69 |
+ (let ((current-page 1) |
|
70 |
+ current-query) |
|
71 |
+ (flet ((next-page () (incf current-page)) |
|
72 |
+ (prev-page () |
|
73 |
+ (when (> current-page 0) |
|
74 |
+ (decf current-page))) |
|
75 |
+ (get-results (current-query current-page) |
|
76 |
+ (compose-funcs (#'format-results #'parse-results #'run-query) |
|
77 |
+ current-query current-page))) |
|
78 |
+ |
|
79 |
+ (format *terminal-io* "~&Index Thomisticus Query Utility v0.1~%") |
|
80 |
+ |
|
81 |
+ (when (cadr args) |
|
82 |
+ (setf current-query (string-join (cdr args) #\space)) |
|
83 |
+ (format *terminal-io* "~&Query: ~a~%" current-query) |
|
84 |
+ (get-results current-query current-page)) |
|
85 |
+ (loop |
|
86 |
+ (format *terminal-io* "~&Query? ") |
|
87 |
+ (finish-output *terminal-io*) |
|
88 |
+ (let ((action (read-line *terminal-io*))) |
|
89 |
+ (string-case action |
|
90 |
+ ("quit" (return-from main)) |
|
91 |
+ ("prev" |
|
92 |
+ (prev-page) |
|
93 |
+ (format *terminal-io* "~&Query: ~a, Page: ~3d~%" current-query current-page) |
|
94 |
+ (get-results current-query current-page)) |
|
95 |
+ ("next" |
|
96 |
+ (next-page) |
|
97 |
+ (format *terminal-io* "~&Query: ~a, Page: ~3d~%" current-query current-page) |
|
98 |
+ (get-results current-query current-page)) |
|
99 |
+ (t (setf current-query action) |
|
100 |
+ (get-results current-query current-page))))))) |
|
101 |
+ (end-of-file (c) (declare (ignore c))) |
|
102 |
+ (sb-sys:interactive-interrupt (c) (declare (ignore c))))) |