ebc3de263271

Dick around with batchcolor a bit more
[view raw] [browse files]
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)))))))))