|
139 | 139 | (if (pair? result) (cadar result) #f)) |
140 | 140 | #f)) |
141 | 141 |
|
142 | | -(define (fix-command cmd file) |
| 142 | +(define (fix-command cmd file pattern) |
143 | 143 | (define (helper cmd file escape?) |
144 | 144 | (define (escape f) |
145 | 145 | (if escape? |
|
155 | 155 | (set! str (substring-replace str "%f" (escape file))) |
156 | 156 | (set! str (substring-replace str "%F" (escape (path->abs file)))) |
157 | 157 | (set! str (substring-replace str "%u" (escape (path->uri file)))) |
| 158 | + ;; Replace capture groups with %0 %1 %2... |
| 159 | + (set! pattern (pattern-exec pattern file)) |
| 160 | + (when pattern |
| 161 | + (for-each |
| 162 | + (λ (i) (let ((captured (match:substring pattern i))) |
| 163 | + (when captured |
| 164 | + (set! str (substring-replace |
| 165 | + str |
| 166 | + (string-append "%" (number->string i)) |
| 167 | + captured))))) |
| 168 | + (iota (match:count pattern)))) |
158 | 169 | str)))) |
159 | 170 | (helper cmd file (string? cmd))) |
160 | 171 |
|
|
236 | 247 | (newline)) |
237 | 248 | (opener file #t))))) |
238 | 249 |
|
239 | | -(define* (execute-after exit-code file #:optional on-success on-error) |
| 250 | +(define* (execute-after exit-code file pattern #:optional on-success on-error) |
240 | 251 | (cond |
241 | 252 | ((or (and (number? exit-code) |
242 | 253 | (= exit-code 0)) |
243 | 254 | (and (not (number? exit-code)) |
244 | 255 | (not (equal? exit-code #f)))) (if on-success |
245 | | - (run-fn-or-system on-success file) |
| 256 | + (run-fn-or-system on-success file pattern) |
246 | 257 | #t)) |
247 | | - (on-error (run-fn-or-system on-error file)) |
| 258 | + (on-error (run-fn-or-system on-error file pattern)) |
248 | 259 | (else #f))) |
249 | 260 |
|
250 | | -(define* (run-fn-or-system x file #:optional on-success on-error) |
| 261 | +(define* (run-fn-or-system x file pattern #:optional on-success on-error) |
| 262 | + (define fixed-command (fix-command x file pattern)) |
251 | 263 | (cond |
252 | 264 | ((procedure? x) (if cold-run |
253 | 265 | (begin (display "(call) ") (display x) (newline)) |
254 | | - (execute-after (x file current-mime) file on-success on-error))) |
| 266 | + (execute-after (x file current-mime) file pattern on-success on-error))) |
255 | 267 | ((list? x) (if cold-run |
256 | 268 | (begin (display "(run) ") (display (string-join x " ")) (newline)) |
257 | | - (execute-after (apply system* (fix-command x file)) file on-success on-error))) |
| 269 | + (execute-after (apply system* fixed-command) file pattern on-success on-error))) |
258 | 270 | ((string? x) (if cold-run |
259 | 271 | (begin (display "(run) ") (display x) (newline)) |
260 | | - (execute-after (system (fix-command x file)) file on-success on-error))))) |
| 272 | + (execute-after (system fixed-command) file pattern on-success on-error))))) |
261 | 273 |
|
262 | 274 | ;; TODO: inline this? |
263 | | -(define (execute program term tmux screen standalone on-success on-error rest file) |
| 275 | +(define (execute program pattern term tmux screen standalone on-success on-error rest file) |
264 | 276 | (let ((command program)) |
265 | 277 | (when (and term (not (isatty? (current-output-port)))) |
266 | 278 | (set! command (append-command term program standalone))) |
|
272 | 284 | (when (and runner-program (not (eqv? runner-program #t))) |
273 | 285 | (set! command runner-program)) |
274 | 286 | (if (not (xor runner-program runner-method)) |
275 | | - (run-fn-or-system command file on-success on-error) |
| 287 | + (run-fn-or-system command file pattern on-success on-error) |
276 | 288 | (begin |
277 | 289 | (display (string-append "No #:" |
278 | 290 | (symbol->string (keyword->symbol runner-method)) |
|
283 | 295 | (define (pattern-exec pattern file) |
284 | 296 | (define (match-with fn) |
285 | 297 | (or (if current-mime (fn pattern current-mime) #f) |
286 | | - (string-match pattern file))) |
287 | | - |
| 298 | + (fn pattern file))) |
288 | 299 | (cond |
289 | 300 | ((string? pattern) (match-with string-match)) |
290 | 301 | ((regexp? pattern) (match-with regexp-exec)) |
291 | 302 | ((list? pattern) (any identity (map (λ (ptrn) (pattern-exec ptrn file)) pattern))))) |
292 | 303 |
|
| 304 | +(define (compile-pattern pattern) |
| 305 | + (cond |
| 306 | + ((string? pattern) (make-regexp pattern)) |
| 307 | + ((regexp? pattern) pattern) |
| 308 | + ((list? pattern) (map (λ (ptrn) (compile-pattern ptrn)) pattern)))) |
| 309 | + |
293 | 310 | (define* (assoc #:key |
294 | 311 | name |
295 | 312 | program |
|
307 | 324 | #:rest r) |
308 | 325 | (define x |
309 | 326 | (lambda* (file #:optional pass-test) |
| 327 | + (set! pattern (compile-pattern pattern)) |
310 | 328 | (if (or pass-test (pattern-exec pattern file)) |
311 | 329 | (let ((rest (make-paired r)) |
312 | | - (test-result (not (xor test (if test (run-fn-or-system test file) #f))))) |
| 330 | + (test-result (not (xor test (if test (run-fn-or-system test file pattern) #f))))) |
313 | 331 | (when (and (not test-result) on-fail) |
314 | 332 | (set! program on-fail)) |
315 | 333 | (if (or test-result on-fail) |
316 | | - (let ((exit-status (execute program term tmux screen standalone on-success on-error rest file))) |
| 334 | + (let ((exit-status (execute program pattern term tmux screen standalone on-success on-error rest file))) |
317 | 335 | (if (and (not (equal? exit-status 0)) continue-on-error) |
318 | 336 | #f |
319 | 337 | (begin |
|
0 commit comments