├── README.md ├── main.lisp ├── package.lisp └── with-user-abort.asd /README.md: -------------------------------------------------------------------------------- 1 | # with-user-abort 2 | ### _ava fox_ 3 | 4 | provides a portable way to capture control-c in your lisp programs 5 | 6 | ## Exports 7 | 8 | *Macro* `with-user-abort` &body body 9 | 10 | executes BODY and captures a user-interrupt (control-c) and signals user-abort condition 11 | 12 | *Condition* `user-abort` 13 | 14 | a simple condition that inherits from your implementation's user-interrupt. 15 | 16 | ## Example 17 | 18 | ```lisp 19 | (handler-case 20 | (with-user-abort (long-running-call)) 21 | (user-abort () 22 | (print "Quitting gracefully") 23 | (uiop:quit 1))) 24 | ``` 25 | 26 | 27 | --- 28 | 29 | ## License 30 | 31 | BSD 3-Clause 32 | -------------------------------------------------------------------------------- /main.lisp: -------------------------------------------------------------------------------- 1 | (in-package :with-user-abort) 2 | 3 | (eval-when (compile load eval) 4 | 5 | (defun get-implementation-condition () 6 | (quote 7 | #+sbcl sb-sys:interactive-interrupt 8 | #+ccl ccl:interrupt-signal-condition 9 | #+clisp system::simple-interrupt-condition 10 | #+ecl ext:interactive-interrupt 11 | #+allegro excl:interrupt-signal 12 | #+lispworks conditions:keyboard-break))) 13 | 14 | (define-condition user-abort (#.(get-implementation-condition)) 15 | () 16 | (:documentation "condition that inherits from implementation specific interrupt condition")) 17 | 18 | (defun user-abort (&optional condition) 19 | (declare (ignore condition)) 20 | (signal 'user-abort)) 21 | 22 | #+ccl 23 | (progn 24 | (defun ccl-break-hook (cond hook) 25 | "SIGINT handler on CCL." 26 | (declare (ignore hook)) 27 | (signal cond)) 28 | 29 | (setf ccl:*break-hook* #'ccl-break-hook)) 30 | 31 | (defmacro with-user-abort (&body body) 32 | "execute BODY, signalling user-abort if the interrupt signal is received" 33 | `(handler-bind ((#.(get-implementation-condition) 34 | 35 | #'user-abort)) 36 | ,@body)) 37 | -------------------------------------------------------------------------------- /package.lisp: -------------------------------------------------------------------------------- 1 | (in-package :cl-user) 2 | (defpackage with-user-abort 3 | (:use :cl) 4 | (:export :user-abort 5 | :with-user-abort)) 6 | -------------------------------------------------------------------------------- /with-user-abort.asd: -------------------------------------------------------------------------------- 1 | (asdf:defsystem #:with-user-abort 2 | :description "provides an easy way to catch ctrl+c. useful for making binaries." 3 | :author "ava fox" 4 | :license "BSD 3-Clause" 5 | :version "0.1" 6 | :serial t 7 | :components ((:file "package") 8 | (:file "main"))) 9 | --------------------------------------------------------------------------------