Dick around with batchcolor a bit more
author |
Steve Losh <steve@stevelosh.com> |
date |
Mon, 06 Jan 2020 22:56:40 -0800 |
parents |
430034d10981
|
children |
48a26e13c94f
|
branches/tags |
(none) |
files |
lisp/.lispwords lisp/batchcolor.lisp |
Changes
--- a/lisp/.lispwords Mon Jan 06 17:03:06 2020 -0800
+++ b/lisp/.lispwords Mon Jan 06 22:56:40 2020 -0800
@@ -1,1 +1,2 @@
(1 maybe-die-on-errors)
+(1 exit-on-error-unless)
--- a/lisp/batchcolor.lisp Mon Jan 06 17:03:06 2020 -0800
+++ b/lisp/batchcolor.lisp Mon Jan 06 22:56:40 2020 -0800
@@ -30,6 +30,13 @@
;;;; Functionality ------------------------------------------------------------
+(define-condition bad-regex (error) ()
+ (:report "Invalid regex."))
+
+(define-condition bad-regex-group-count (bad-regex) ()
+ (:report "Invalid regex: must contain exactly 1 register group, e.g. 'x (fo+) y'."))
+
+
(defun djb2 (string)
;; http://www.cse.yorku.ca/~oz/hash.html
(reduce (lambda (hash c)
@@ -53,7 +60,7 @@
(setf rs (remove nil rs)
re (remove nil re))
(when (/= 1 (length rs))
- (error "Regex must contain exactly 1 register group, e.g. 'x (fo+) y'."))
+ (error 'bad-regex-group-count))
(let* ((word-start (aref rs 0))
(word-end (aref re 0))
(word (subseq line word-start word-end))
@@ -68,7 +75,15 @@
;;;; Run ----------------------------------------------------------------------
(defun run% (scanner stream)
(loop :for line = (read-line stream nil)
- :while line :do (colorize-line scanner line)))
+ :while line
+ :do (tagbody retry
+ (restart-case (colorize-line scanner line)
+ (supply-new-regex (v)
+ :test (lambda (c) (typep c 'bad-regex))
+ :report "Supply a new regular expression as a string."
+ :interactive (lambda () (list (read-line *query-io*)))
+ (setf scanner (ppcre:create-scanner v))
+ (go retry))))))
(defun run (pattern paths)
(if (null paths)
@@ -153,21 +168,41 @@
*option-version*)))
+(defmacro without-debugger (&body body)
+ `(multiple-value-prog1
+ (progn
+ #+sbcl (sb-ext:disable-debugger)
+ (progn ,@body))
+ (progn
+ #+sbcl (sb-ext:enable-debugger))))
+
+(defmacro exit-on-error (&body body)
+ `(without-debugger
+ (handler-case (progn ,@body)
+ (error (c) (adopt:print-error-and-exit c)))))
+
+(defmacro exit-on-error-unless (expr &body body)
+ `(if ,expr
+ (progn ,@body)
+ (exit-on-error ,@body)))
+
+(defmacro exit-on-ctrl-c (&body body)
+ `(handler-case
+ (with-user-abort:with-user-abort (progn ,@body))
+ (with-user-abort:user-abort () (adopt:exit 130))))
+
+
(defun toplevel ()
- #+sbcl (sb-ext:disable-debugger)
- (handler-case
- (with-user-abort:with-user-abort
- (multiple-value-bind (arguments options) (adopt:parse-options *ui*)
- (cond
- ((gethash 'help options) (adopt:print-help-and-exit *ui*))
- ((gethash 'version options) (write-line *version*) (adopt:exit))
- (t (if (< (length arguments) 1)
- (adopt:print-help-and-exit *ui*)
- (destructuring-bind (pattern . files) arguments
- (let ((*start* (if (gethash 'randomize options)
- (random 256 (make-random-state t))
- 0)))
- (run pattern files))))))))
- (with-user-abort:user-abort () (adopt:exit 130))
- (error (c) (adopt:print-error-and-exit c))))
+ (exit-on-ctrl-c
+ (multiple-value-bind (arguments options) (adopt:parse-options-or-exit *ui*)
+ (exit-on-error-unless (gethash 'debug options)
+ (cond
+ ((gethash 'help options) (adopt:print-help-and-exit *ui*))
+ ((gethash 'version options) (write-line *version*) (adopt:exit))
+ ((null arguments) (error "A regular expression is required."))
+ (t (destructuring-bind (pattern . files) arguments
+ (let ((*start* (if (gethash 'randomize options)
+ (random 256 (make-random-state t))
+ 0)))
+ (run pattern files)))))))))