User defined pipe and redirection operators: Difference between revisions

Content added Content deleted
m (Task titles don't go in the task template (even for drafts))
Line 617: Line 617:


print while $_ = $chain->readline;</lang>
print while $_ = $chain->readline;</lang>

=={{header|Racket}}==

<lang racket>
#lang racket

(module racksh racket

(require (for-syntax racket/syntax))

(provide (except-out (all-from-out racket) #%app sort)
(rename-out [shell-app #%app]))

(define-syntax (shell-app stx)
(define (=? x y)
(eq? (if (syntax? x) (syntax-e x) x) (if (syntax? y) (syntax-e y) y)))
(define (err msg) (raise-syntax-error 'shell msg stx))
(define (make-call xs)
(cond [(null? xs) (err "empty form")]
[(string? (syntax-e (car xs))) #`(shell #,(car xs) #,@(cdr xs))]
[(eq? #\{ (syntax-property (car xs) 'paren-shape)) (cons #'void xs)]
[else xs]))
(syntax-case stx ()
[(_ x ...) (eq? #\{ (syntax-property stx 'paren-shape))
(let loop ([xs (reverse (syntax->list #'(\; x ...)))]
[form '()] [thunks '()] [I #f] [O #f] [seq '()])
(cond [(null? xs) #`(begin #,@seq)]
[(=? '\; (car xs))
(loop (cdr xs) '() '() #f #f
(if (and (null? form) (null? thunks)) seq
(let* ([form (make-call form)]
[r (if (null? thunks) form
#`(pipe (list (λ() #,form) #,@thunks)))]
[r (if I #`(#,@I (λ() #,r)) r)]
[r (if O #`(#,@O (λ() #,r)) r)])
(cons r seq))))]
[(=? '\| (car xs))
(loop (cdr xs) '() (cons #`(λ() #,(make-call form)) thunks) I O
seq)]
[(or (=? '< (car xs)) (=? '<< (car xs)))
(cond [(null? form) (err "missing expression after < or <<")]
[I (err "duplicate < or << specified")]
[else (loop (cdr xs) (cdr form) thunks
(if (=? '< (car xs))
#`(with-input-from-file #,(car form))
#`(with-input-from-string #,(car form)))
O seq)])]
[(or (=? '> (car xs)) (=? '>> (car xs)))
(cond [(null? form) (err "missing expression after > or >>")]
[O (err "duplicate > or >> specified")]
[else (loop (cdr xs) (cdr form) thunks I
#`(with-output-to-file #,(cadr xs) #:exists
'#,(if (=? '> (car xs)) 'truncate 'append))
seq)])]
[else (loop (cdr xs) (cons (car xs) form) thunks I O seq)]))]
[(_ x ...) #'(x ...)]))

(define (pipe thunks)
(if (null? (cdr thunks)) ((car thunks))
(let-values ([(I O) (make-pipe)])
(parameterize ([current-output-port O])
(thread (λ() (dynamic-wind void (car thunks)
(λ() (close-output-port O))))))
(parameterize ([current-input-port I]) (pipe (cdr thunks))))))

(define (shell cmd . args)
(apply system* (find-executable-path cmd)
(map (λ(x) (if (string? x) x
(with-output-to-string (λ() (display x)))))
args)))

;; implements a common interface of reading a bunch of files; '- means
;; stdin; no files means just stdin
(define (call/files files proc)
(if (null? files) (proc (current-input-port))
(let-values ([(I O) (make-pipe)])
(thread
(λ() (for ([file (in-list files)])
(if (eq? '- file)
(copy-port (current-input-port) O)
(call-with-input-file file (λ(i) (copy-port i O)))))
(close-output-port O)))
(proc I))))

(define-syntax (define-io stx)
(syntax-case stx ()
[(_ (name . xs) E ...)
(with-syntax ([io-name (format-id #'name "io-~a" #'name)])
#'(begin (provide (rename-out [io-name name]))
(define (io-name . xs) E ...)))]))

(define-io (echo . xs)
(for-each display (add-between xs " "))
(newline))
(define-io (cat . files)
(call/files files (λ(I) (copy-port I (current-output-port)))))
(define-io (sort . files)
(display-lines (sort (call/files files port->lines) string<?)))
(define-io (head n . files)
(call/files files
(λ(I) (for ([l (in-lines I)] [i (in-range n)]) (displayln l)))))
(define-io (tail n . files)
(display-lines (take-right (call/files files port->lines) n)))
(define-io (grep rx . files)
(call/files files
(λ(I) (for ([l (in-lines I)] #:when (regexp-match? rx l)) (displayln l)))))
(define-io (uniq . files)
(call/files files
(λ(I) (let loop ([last #f])
(define line (read-line I))
(unless (eof-object? line)
(unless (equal? line last) (displayln line))
(loop line))))))
(define-io (tee file)
(call-with-output-file file #:exists 'truncate
(λ(O) (for ([l (in-lines (current-input-port))])
(displayln l O) (displayln l)))))

(provide $)
(define-syntax-rule ($ E ...)
(with-output-to-string (λ() E ...))))

(module sample (submod ".." racksh)
{\;
define file "List_of_computer_scientists.lst" \;
define aa ($
{{ head 4 < file \;
cat file \| grep "ALGOL" \;
tail 4 < file \;
} \| sort \| uniq \| tee "the_important_scientists.lst" \| grep "aa"
}) \;
echo "Pioneer:" aa}
)

(require 'sample)
</lang>


=={{header|Tcl}}==
=={{header|Tcl}}==