# HG changeset patch # User Steve Losh # Date 1570137982 14400 # Node ID f0254c404ef468238be4bfb0ec2b74415600a122 # Parent 3b355cd3164230b58fe372d77b6b9fb59ada9814 Move `sh` and friends from CACL into this repo diff -r 3b355cd31642 -r f0254c404ef4 DOCUMENTATION.markdown --- a/DOCUMENTATION.markdown Thu Oct 03 10:38:04 2019 -0400 +++ b/DOCUMENTATION.markdown Thu Oct 03 17:26:22 2019 -0400 @@ -2105,6 +2105,43 @@ +## Package `LOSH.SHELL` + +Utilities for interacting with external programs. + +### `PBCOPY` (function) + + (PBCOPY OBJECT) + +`pbcopy` the `aesthetic-string` of `object`. + +### `PBPASTE` (function) + + (PBPASTE) + +`pbpaste` the current clipboard as a string. + +### `SH` (function) + + (SH COMMAND &KEY INPUT OUTPUT (WAIT T)) + +Run `command`, piping `input` to it, optionally returning its output. + + `command` must be either a string (the program), or a list of the program and + its arguments. + + `wait` must be a boolean. If true, this function will block until the command + completes. If false, it will return immediately and allow the program to run + asynchronously. + + `input` must be a character input stream, a string, or `nil`. If non-`nil` + its contents will be sent to the program as its standard input. + + `output` must be one of `:string`, `:stream`, or `nil`. `:string` cannot be + used if `:wait` is `nil`. + + + ## Package `LOSH.WEIGHTLISTS` A simple data structure for choosing random items with weighted probabilities. diff -r 3b355cd31642 -r f0254c404ef4 losh.asd --- a/losh.asd Thu Oct 03 10:38:04 2019 -0400 +++ b/losh.asd Thu Oct 03 17:26:22 2019 -0400 @@ -10,8 +10,8 @@ :in-order-to ((asdf:test-op (asdf:test-op :losh/test))) :depends-on (:iterate - #+sbcl :sb-sprof - ) + :uiop + #+sbcl :sb-sprof) :serial t :components @@ -31,6 +31,7 @@ (:file "io") (:file "lists") (:file "mutation") + (:file "shell") ;; 1 --------------------------------------------------------- (:file "arrays" :depends-on ("chili-dogs")) diff -r 3b355cd31642 -r f0254c404ef4 make-docs.lisp --- a/make-docs.lisp Thu Oct 03 10:38:04 2019 -0400 +++ b/make-docs.lisp Thu Oct 03 17:26:22 2019 -0400 @@ -23,6 +23,7 @@ "LOSH.QUEUES" "LOSH.RANDOM" "LOSH.SEQUENCES" + "LOSH.SHELL" "LOSH.WEIGHTLISTS" )) diff -r 3b355cd31642 -r f0254c404ef4 package.lisp --- a/package.lisp Thu Oct 03 10:38:04 2019 -0400 +++ b/package.lisp Thu Oct 03 17:26:22 2019 -0400 @@ -17,7 +17,6 @@ :collect `(:export ,@(external-symbols parent-package))))) - (defpackage :losh.chili-dogs (:use :cl :iterate :losh.quickutils) (:documentation "Gotta go FAST.") @@ -107,6 +106,14 @@ :notf :callf)) +(defpackage :losh.shell + (:use :cl :iterate :losh.quickutils) + (:documentation "Utilities for interacting with external programs.") + (:export + :sh + :pbcopy + :pbpaste)) + (defpackage :losh.arrays (:use :cl :iterate :losh.quickutils @@ -395,6 +402,7 @@ :losh.queues :losh.random :losh.sequences + :losh.shell :losh.weightlists ) diff -r 3b355cd31642 -r f0254c404ef4 src/shell.lisp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/shell.lisp Thu Oct 03 17:26:22 2019 -0400 @@ -0,0 +1,53 @@ +(in-package :losh.shell) + +(defun sh (command &key input output (wait t)) + "Run `command`, piping `input` to it, optionally returning its output. + + `command` must be either a string (the program), or a list of the program and + its arguments. + + `wait` must be a boolean. If true, this function will block until the command + completes. If false, it will return immediately and allow the program to run + asynchronously. + + `input` must be a character input stream, a string, or `nil`. If non-`nil` + its contents will be sent to the program as its standard input. + + `output` must be one of `:string`, `:stream`, or `nil`. `:string` cannot be + used if `:wait` is `nil`. + + " + (ctypecase command + (string (setf command (list command))) + ((cons string list))) + (ctypecase input + (string (setf input (make-string-input-stream input))) + (stream) + (null)) + (let ((result (funcall (if wait #'uiop:run-program #'uiop:launch-program) + command + :output (when output + (if wait + (ccase output + (:string :string) + (:stream :string)) ; hack because uiop doesn't support this + (ccase output + (:string (error "`output` cannot be `:string` when not `wait`ing.")) + (:stream :stream)))) + :input input))) + (ecase output + ((nil) (values)) + (:stream (if wait + (make-string-input-stream result) + (uiop:process-info-output result))) + (:string result)))) + + +(defun pbcopy (object) + "`pbcopy` the `aesthetic-string` of `object`." + (sh "pbcopy" :input (format nil "~A" object) :wait nil) + (values)) + +(defun pbpaste () + "`pbpaste` the current clipboard as a string." + (values (sh "pbpaste" :output :string)))