-
Notifications
You must be signed in to change notification settings - Fork 2
/
external.rkt
124 lines (110 loc) · 4.68 KB
/
external.rkt
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
118
119
120
121
122
123
124
#lang racket
(require net/base64 net/http-client net/url)
(require json)
(require sxml/sxpath)
(require (only-in rnrs/io/ports-6 call-with-port))
(require (only-in srfi/13 string-contains))
(define (read-all)
(let loop ((xs '()))
(let ((x (read)))
(if (eof-object? x) (reverse xs) (loop (cons x xs))))))
(define (write-sexp-file filename forms)
(call-with-atomic-output-file
filename
(lambda (port _)
(parameterize ((current-output-port port))
(for-each writeln forms)))))
(define (command->string command . args)
(let-values (((sub stdout stdin stderr)
(apply subprocess #f
(current-input-port)
(current-error-port)
(find-executable-path command)
args)))
(let ((output (port->string stdout)))
(subprocess-wait sub)
(if (eqv? 0 (subprocess-status sub))
output
(error "Command failed:" (cons command args))))))
(define (call-with-url-port url proc)
(call-with-port (get-pure-port (string->url url)) proc))
(define (query-github query)
(read-json (get-pure-port (string->url (string-append "https://api.github.com" query)))))
(define (base64-decode-string str)
(bytes->string/utf-8 (base64-decode (string->bytes/utf-8 str))))
(define (not-space? str)
(not (string=? str " ")))
(displayln "Scraping listings for")
(displayln "Snow Fort...")
;; Snow Fort repo is in SXML format. We can directly query it with SXPath.
(let ((repo (read (get-pure-port (string->url "https://snow-fort.org/pkg/repo"))))
(query (sxpath '(package library name srfi))))
(with-output-to-file "data/snow-fort.pose" #:exists 'replace
(thunk (for-each displayln (sort (remove-duplicates (map cadr (query repo))) <)))))
(displayln "chez-srfi...")
;; GitHub API returns data in JSON format, which we can `read' into `hasheq's of lists.
(let ((repo (query-github "/repos/arcfide/chez-srfi/contents")))
(define results
(sort
(for/list ((file (map (curryr hash-ref 'name) repo))
#:when (string-prefix? file "%3a")
#:unless (string-suffix? file ".sls"))
(string->number (substring file 3)))
<))
(with-output-to-file "data/chez-external.pose" #:exists 'replace
(thunk (for-each displayln results)))
(with-output-to-file "data/iron-external.pose" #:exists 'replace
(thunk (for-each displayln results)))
(with-output-to-file "data/loko-external.pose" #:exists 'replace
(thunk (for-each displayln results)
(displayln 160))))
(define (parse-org-mode-table table chicken-port egg-port)
;; Ad hoc, quick-and-dirty org-mode table parser
(define (get-srfi-number cells)
(cadr (regexp-match #rx"\\[\\[.+\\]\\[(.+)\\]\\]" (string-trim (list-ref cells 6)))))
(let loop ((lines (map string-normalize-spaces (cdddr table)))) ; Skip the header row
(unless (< (length lines) 2)
(let ((cells (string-split (cadr lines) "|"))) ; Divide meaningful lines into cells
(when (not-space? (car cells)) ; First row = core
(displayln (get-srfi-number cells) chicken-port))
(when (not-space? (cadr cells)) ; Second row = egg
(displayln (get-srfi-number cells) egg-port)))
;; Every other line is a horizontal rule, so we always skip one.
(loop (cddr lines)))))
(define (get-chicken-built-in-srfis)
(let* ((whole-page (call-with-url-port
"https://wiki.call-cc.org/supported-standards"
port->string))
(c3-c4-start (string-contains
whole-page "<h4 id=\"chicken-3-and-4\">"))
(c5-part (substring whole-page 0 c3-c4-start)))
(map (lambda (srfi-nnn)
(string->number (substring srfi-nnn (string-length "srfi-"))))
(regexp-match* #rx"SRFI-[0-9]+" c5-part))))
(define (get-chicken-external-srfis)
(sort
(append-map
(lambda (egg)
(let ((name (symbol->string (car egg))))
(cond ((string=? name "box") '(111))
((string=? name "srfi-69") '(69 90))
((string=? name "vector-lib") '(43))
((and (string-prefix? name "srfi-")
(string->number (substring name (string-length "srfi-"))))
=> list)
(else '()))))
(with-input-from-string
(command->string
"curl"
"--location"
"--fail"
"--silent"
"--show-error"
"--user" "anonymous:"
"https://code.call-cc.org/svn/chicken-eggs/release/5/egg-locations")
read-all))
<))
(displayln "CHICKEN...")
(write-sexp-file "data/chicken.pose" (get-chicken-built-in-srfis))
(write-sexp-file "data/chicken-external.pose" (get-chicken-external-srfis))
(displayln "Scraped.")