-
Notifications
You must be signed in to change notification settings - Fork 12
/
irepl.lisp
161 lines (128 loc) · 4.45 KB
/
irepl.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
;;;; irepl.lisp
(in-package #:quicklisp-controller)
;;; A repl for working through github issues.
(defvar *irepl-command-table* (make-hash-table))
(defvar *irepl-current-command* nil)
(defvar *irepl-state* nil)
(defun irepl-unknown-command ()
(warn "Unknown command ~A" *irepl-current-command*))
(defmacro define-irepl-command (command &body body)
(let ((fun-name (copy-symbol command)))
`(setf (gethash ',command *irepl-command-table*)
(labels ((,fun-name () ,@body))
#',fun-name))))
(defun invoke-irepl-command (command)
(let ((*irepl-current-command* command))
(funcall (gethash command *irepl-command-table* 'irepl-unknown-command))))
(defgeneric all-issues (state))
(defgeneric current-issue (state))
(defgeneric next-issue (state))
(defgeneric previous-issue (state))
(defgeneric reset (state))
(defgeneric issue-index (state))
(defgeneric (setf issue-index) (new-value state))
(defgeneric issue-count (state))
(defmethod current-issue (state)
(elt (all-issues state) (issue-index state)))
(defmethod next-issue (state)
(setf (issue-index state) (mod (1+ (issue-index state))
(issue-count state)))
(current-issue state))
(defmethod previous-issue (state)
(setf (issue-index state) (mod (1- (issue-index state))
(issue-count state)))
(current-issue state))
(defmethod reset (state)
(let ((issues (githappy:json
(githappy:repo-issues :owner "quicklisp"
:repo "quicklisp-projects"))))
(setf (slot-value state 'issues) issues)
(setf (issue-index state) 0)))
(defmethod issue-count (state)
(length (all-issues state)))
(defclass irepl-state ()
((issues
:reader all-issues)
(issue-index
:initform 0
:accessor issue-index)))
(defmethod shared-initialize :after ((state irepl-state) slot-names
&rest args &key &allow-other-keys)
(declare (ignore args))
(reset state))
(defun stripm (string)
(delete #\Return string))
(defun =jref (key)
(lambda (json)
(githappy:jref json key)))
(defun irref (&rest key)
(let ((value (githappy:jref (current-issue *irepl-state*) key)))
(if (stringp value)
(stripm value)
value)))
(defun irepl ()
(catch 'irepl-exit
(setf *irepl-state* (make-instance 'irepl-state))
(invoke-irepl-command 'show)
(tagbody
next
(with-simple-restart (abort "Return to irepl")
(fresh-line)
(princ "> ")
(let ((command (read)))
(cond ((and (symbolp command)
(not (boundp command)))
(shiftf *** ** * (invoke-irepl-command command)))
(t
(let ((results (multiple-value-list (eval command))))
(format t "~{~S~^ ;~%~}" results)
(shiftf *** ** * (first results)))))))
(go next))))
(defparameter *irepl-guess-patterns*
'(("(github\\.com/[\\w-_/]*)" "https" )))
(define-irepl-command quit
(throw 'irepl-exit :done))
(define-irepl-command reset
(reset *irepl-state*))
(define-irepl-command show
(format t "#~D: ~A~%---~{ [~A]~}~%~A~%"
(irref "number")
(irref "title")
(irref "labels" :* "name")
(irref "body")))
(define-irepl-command next
(next-issue *irepl-state*)
(invoke-irepl-command 'show))
(define-irepl-command previous
(previous-issue *irepl-state*)
(invoke-irepl-command 'show))
(define-irepl-command skip
(let ((index (position-if-not (=jref '("labels" :* "name"))
(all-issues *irepl-state*))))
(if index
(progn
(setf (issue-index *irepl-state*) index)
(invoke-irepl-command 'show))
(format t "; No issue without labels~%"))))
(define-irepl-command failtail
(failtail))
(defvar *irepl-guess-patterns*
"https://github.com/")
(define-irepl-command canbuild
(when *last-source*
(mark-canbuild *last-source*)
:canbuild))
(define-irepl-command cantbuild
(cond (*last-source*
(mark-cantbuild *last-source*)
(let ((log-url (publish-source-failure *last-source*)))
(comment-on-issue *last-source*
(format nil "Failure log here: ~A"
log-url)))
:cantbuild)
(t
(warn "No last-source defined"))))
(define-irepl-command commit
(when *last-source*
(commit-source *last-source*)
:committed))