;;;; jira-api.lisp (declaim (optimize (debug 3))) (in-package #:jira-api) (defun get-issues (auth) (api-get-call auth "search")) (defun get-issue (auth key &rest params &key expand) (declare (ignore expand)) (apply 'api-get-call auth (format nil "issue/~a" key) params)) (defun get-projects (auth) (api-get-call auth "issue/createmeta")) (defun make-issue (project-key summary &key (description nil description-p) (issue-type "Bug")) (let* ((issue (make-hash-table :test 'equal)) (project (alist-string-hash-table `(("key" . ,project-key)))) (issue-type (alist-string-hash-table `(("name" . ,issue-type))))) (setf (gethash "fields" issue) (alist-string-hash-table `(("project" . ,project) ("summary" . ,summary) ,@(when description-p (list (cons "description" description))) ("issuetype" . ,issue-type)))) issue)) (defun post-issue (auth issue) (let-each (:be *) issue (with-output-to-string (s) (yason:encode * s)) (api-post-call auth "issue" *))) (defun post-issue-from-fields (auth project-key summary &key (description nil description-p) (issue-type nil issue-type-p)) (let ((optional-arguments '())) (when issue-type-p (push issue-type optional-arguments)) (when description-p (push description optional-arguments)) (let-each (:be *) (apply #'make-issue project-key summary optional-arguments) (post-issue auth *)))) (defun read-issue (&optional (iostream *query-io*)) (let ((project-key (prompt :project-key iostream)) (summary (prompt :summary iostream)) (description (optional-prompt iostream :description "Add a description? "))) (apply #'make-issue project-key summary (list* (when description (list description)))))) (defun show-person (person title) (format t "~&~4t~a: ~a~%" title (show person))) (defun show-labels (labels) (format t "~&~4tLabels: ~{~a~}~%" (coerce labels 'list))) (defun show-description (description) (pprint-logical-block (*standard-output* (mapcar (compose 'tokens 'trim-whitespace) (lines description))) (pprint-indent :block 4 *standard-output*) (pprint-newline :mandatory *standard-output*) (loop (pprint-exit-if-list-exhausted) (let ((line (pprint-pop))) (pprint-logical-block (*standard-output* line) (loop (princ (pprint-pop) *standard-output*) (pprint-exit-if-list-exhausted) (princ #\space *standard-output*) (pprint-indent :block 3) (pprint-newline :fill *standard-output*))) (pprint-newline :mandatory *standard-output*))))) (defun show-summary (summary) (pprint-logical-block (*standard-output* (funcall (compose 'tokens 'trim-whitespace) summary)) (pprint-indent :block 8 *standard-output*) (pprint-exit-if-list-exhausted) (format *standard-output* "~4tSummary: ") (loop (princ (pprint-pop)) (pprint-exit-if-list-exhausted) (pprint-newline :fill *standard-output*) (princ #\space)))) (defun classify-issues (sheeple-issues &optional (classify-by '(status name))) (sheeple:with-properties (issues) sheeple-issues (loop with classes = (make-hash-table :test 'equalp) for issue across issues do (loop for classification in classify-by for thing = (sheeple:property-value (fields issue) classification) then (sheeple:property-value thing classification) finally (push issue (gethash thing classes))) finally (return classes)))) (defun show-issue-short (issue) (sheeple:with-properties (key self) issue (let* ((fields (fields issue)) (status (name (status fields))) (summary (summary fields))) (format t "~&~a ~a (~a)~%" self key status) (show-summary summary) (fresh-line)))) (default) (defun show-issues (sheeple-issues) (sheeple:with-properties (issues) sheeple-issues (loop for issue across issues do (ensure-parent issue =issue=) do (show-issue-short issue)))) (defun print-on-own-line (str) (format t "~&~a~&" str)) (defun show-projects (projects) (sheeple:with-properties (projects) projects (loop for project across projects do (ensure-parent project =project=) do (print-on-own-line (show project)))))