typed-process docs
This commit is contained in:
parent
1f9956a4b6
commit
97f12b697a
17 changed files with 2145 additions and 0 deletions
63
static/typed-process/System-Process-Typed.html
Normal file
63
static/typed-process/System-Process-Typed.html
Normal file
File diff suppressed because one or more lines are too long
4
static/typed-process/doc-index.html
Normal file
4
static/typed-process/doc-index.html
Normal file
File diff suppressed because one or more lines are too long
30
static/typed-process/frames.html
Normal file
30
static/typed-process/frames.html
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<!DOCTYPE html
|
||||||
|
PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<title></title>
|
||||||
|
<script src="haddock-util.js" type="text/javascript"></script>
|
||||||
|
<script type="text/javascript"><!--
|
||||||
|
/*
|
||||||
|
|
||||||
|
The synopsis frame needs to be updated using javascript, so we hide
|
||||||
|
it by default and only show it if javascript is enabled.
|
||||||
|
|
||||||
|
TODO: provide some means to disable it.
|
||||||
|
*/
|
||||||
|
function load() {
|
||||||
|
var d = document.getElementById("inner-fs");
|
||||||
|
d.rows = "50%,50%";
|
||||||
|
postReframe();
|
||||||
|
}
|
||||||
|
--></script>
|
||||||
|
</head>
|
||||||
|
<frameset id="outer-fs" cols="25%,75%" onload="load()">
|
||||||
|
<frameset id="inner-fs" rows="100%,0%">
|
||||||
|
<frame src="index-frames.html" name="modules" />
|
||||||
|
<frame src="" name="synopsis" />
|
||||||
|
</frameset>
|
||||||
|
<frame src="index.html" name="main" />
|
||||||
|
</frameset>
|
||||||
|
</html>
|
344
static/typed-process/haddock-util.js
Normal file
344
static/typed-process/haddock-util.js
Normal file
|
@ -0,0 +1,344 @@
|
||||||
|
// Haddock JavaScript utilities
|
||||||
|
|
||||||
|
var rspace = /\s\s+/g,
|
||||||
|
rtrim = /^\s+|\s+$/g;
|
||||||
|
|
||||||
|
function spaced(s) { return (" " + s + " ").replace(rspace, " "); }
|
||||||
|
function trim(s) { return s.replace(rtrim, ""); }
|
||||||
|
|
||||||
|
function hasClass(elem, value) {
|
||||||
|
var className = spaced(elem.className || "");
|
||||||
|
return className.indexOf( " " + value + " " ) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addClass(elem, value) {
|
||||||
|
var className = spaced(elem.className || "");
|
||||||
|
if ( className.indexOf( " " + value + " " ) < 0 ) {
|
||||||
|
elem.className = trim(className + " " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeClass(elem, value) {
|
||||||
|
var className = spaced(elem.className || "");
|
||||||
|
className = className.replace(" " + value + " ", " ");
|
||||||
|
elem.className = trim(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleClass(elem, valueOn, valueOff, bool) {
|
||||||
|
if (bool == null) { bool = ! hasClass(elem, valueOn); }
|
||||||
|
if (bool) {
|
||||||
|
removeClass(elem, valueOff);
|
||||||
|
addClass(elem, valueOn);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
removeClass(elem, valueOn);
|
||||||
|
addClass(elem, valueOff);
|
||||||
|
}
|
||||||
|
return bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function makeClassToggle(valueOn, valueOff)
|
||||||
|
{
|
||||||
|
return function(elem, bool) {
|
||||||
|
return toggleClass(elem, valueOn, valueOff, bool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleShow = makeClassToggle("show", "hide");
|
||||||
|
toggleCollapser = makeClassToggle("collapser", "expander");
|
||||||
|
|
||||||
|
function toggleSection(id)
|
||||||
|
{
|
||||||
|
var b = toggleShow(document.getElementById("section." + id));
|
||||||
|
toggleCollapser(document.getElementById("control." + id), b);
|
||||||
|
rememberCollapsed(id, b);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
var collapsed = {};
|
||||||
|
function rememberCollapsed(id, b)
|
||||||
|
{
|
||||||
|
if(b)
|
||||||
|
delete collapsed[id]
|
||||||
|
else
|
||||||
|
collapsed[id] = null;
|
||||||
|
|
||||||
|
var sections = [];
|
||||||
|
for(var i in collapsed)
|
||||||
|
{
|
||||||
|
if(collapsed.hasOwnProperty(i))
|
||||||
|
sections.push(i);
|
||||||
|
}
|
||||||
|
// cookie specific to this page; don't use setCookie which sets path=/
|
||||||
|
document.cookie = "collapsed=" + escape(sections.join('+'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreCollapsed()
|
||||||
|
{
|
||||||
|
var cookie = getCookie("collapsed");
|
||||||
|
if(!cookie)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var ids = cookie.split('+');
|
||||||
|
for(var i in ids)
|
||||||
|
{
|
||||||
|
if(document.getElementById("section." + ids[i]))
|
||||||
|
toggleSection(ids[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCookie(name, value) {
|
||||||
|
document.cookie = name + "=" + escape(value) + ";path=/;";
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearCookie(name) {
|
||||||
|
document.cookie = name + "=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT;";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCookie(name) {
|
||||||
|
var nameEQ = name + "=";
|
||||||
|
var ca = document.cookie.split(';');
|
||||||
|
for(var i=0;i < ca.length;i++) {
|
||||||
|
var c = ca[i];
|
||||||
|
while (c.charAt(0)==' ') c = c.substring(1,c.length);
|
||||||
|
if (c.indexOf(nameEQ) == 0) {
|
||||||
|
return unescape(c.substring(nameEQ.length,c.length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var max_results = 75; // 50 is not enough to search for map in the base libraries
|
||||||
|
var shown_range = null;
|
||||||
|
var last_search = null;
|
||||||
|
|
||||||
|
function quick_search()
|
||||||
|
{
|
||||||
|
perform_search(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function full_search()
|
||||||
|
{
|
||||||
|
perform_search(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function perform_search(full)
|
||||||
|
{
|
||||||
|
var text = document.getElementById("searchbox").value.toLowerCase();
|
||||||
|
if (text == last_search && !full) return;
|
||||||
|
last_search = text;
|
||||||
|
|
||||||
|
var table = document.getElementById("indexlist");
|
||||||
|
var status = document.getElementById("searchmsg");
|
||||||
|
var children = table.firstChild.childNodes;
|
||||||
|
|
||||||
|
// first figure out the first node with the prefix
|
||||||
|
var first = bisect(-1);
|
||||||
|
var last = (first == -1 ? -1 : bisect(1));
|
||||||
|
|
||||||
|
if (first == -1)
|
||||||
|
{
|
||||||
|
table.className = "";
|
||||||
|
status.innerHTML = "No results found, displaying all";
|
||||||
|
}
|
||||||
|
else if (first == 0 && last == children.length - 1)
|
||||||
|
{
|
||||||
|
table.className = "";
|
||||||
|
status.innerHTML = "";
|
||||||
|
}
|
||||||
|
else if (last - first >= max_results && !full)
|
||||||
|
{
|
||||||
|
table.className = "";
|
||||||
|
status.innerHTML = "More than " + max_results + ", press Search to display";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// decide what you need to clear/show
|
||||||
|
if (shown_range)
|
||||||
|
setclass(shown_range[0], shown_range[1], "indexrow");
|
||||||
|
setclass(first, last, "indexshow");
|
||||||
|
shown_range = [first, last];
|
||||||
|
table.className = "indexsearch";
|
||||||
|
status.innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function setclass(first, last, status)
|
||||||
|
{
|
||||||
|
for (var i = first; i <= last; i++)
|
||||||
|
{
|
||||||
|
children[i].className = status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// do a binary search, treating 0 as ...
|
||||||
|
// return either -1 (no 0's found) or location of most far match
|
||||||
|
function bisect(dir)
|
||||||
|
{
|
||||||
|
var first = 0, finish = children.length - 1;
|
||||||
|
var mid, success = false;
|
||||||
|
|
||||||
|
while (finish - first > 3)
|
||||||
|
{
|
||||||
|
mid = Math.floor((finish + first) / 2);
|
||||||
|
|
||||||
|
var i = checkitem(mid);
|
||||||
|
if (i == 0) i = dir;
|
||||||
|
if (i == -1)
|
||||||
|
finish = mid;
|
||||||
|
else
|
||||||
|
first = mid;
|
||||||
|
}
|
||||||
|
var a = (dir == 1 ? first : finish);
|
||||||
|
var b = (dir == 1 ? finish : first);
|
||||||
|
for (var i = b; i != a - dir; i -= dir)
|
||||||
|
{
|
||||||
|
if (checkitem(i) == 0) return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// from an index, decide what the result is
|
||||||
|
// 0 = match, -1 is lower, 1 is higher
|
||||||
|
function checkitem(i)
|
||||||
|
{
|
||||||
|
var s = getitem(i).toLowerCase().substr(0, text.length);
|
||||||
|
if (s == text) return 0;
|
||||||
|
else return (s > text ? -1 : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// from an index, get its string
|
||||||
|
// this abstracts over alternates
|
||||||
|
function getitem(i)
|
||||||
|
{
|
||||||
|
for ( ; i >= 0; i--)
|
||||||
|
{
|
||||||
|
var s = children[i].firstChild.firstChild.data;
|
||||||
|
if (s.indexOf(' ') == -1)
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return ""; // should never be reached
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSynopsis(filename) {
|
||||||
|
if (parent.window.synopsis && parent.window.synopsis.location) {
|
||||||
|
if (parent.window.synopsis.location.replace) {
|
||||||
|
// In Firefox this avoids adding the change to the history.
|
||||||
|
parent.window.synopsis.location.replace(filename);
|
||||||
|
} else {
|
||||||
|
parent.window.synopsis.location = filename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMenuItem(html) {
|
||||||
|
var menu = document.getElementById("page-menu");
|
||||||
|
if (menu) {
|
||||||
|
var btn = menu.firstChild.cloneNode(false);
|
||||||
|
btn.innerHTML = html;
|
||||||
|
menu.appendChild(btn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function adjustForFrames() {
|
||||||
|
var bodyCls;
|
||||||
|
|
||||||
|
if (parent.location.href == window.location.href) {
|
||||||
|
// not in frames, so add Frames button
|
||||||
|
addMenuItem("<a href='#' onclick='reframe();return true;'>Frames</a>");
|
||||||
|
bodyCls = "no-frame";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bodyCls = "in-frame";
|
||||||
|
}
|
||||||
|
addClass(document.body, bodyCls);
|
||||||
|
}
|
||||||
|
|
||||||
|
function reframe() {
|
||||||
|
setCookie("haddock-reframe", document.URL);
|
||||||
|
window.location = "frames.html";
|
||||||
|
}
|
||||||
|
|
||||||
|
function postReframe() {
|
||||||
|
var s = getCookie("haddock-reframe");
|
||||||
|
if (s) {
|
||||||
|
parent.window.main.location = s;
|
||||||
|
clearCookie("haddock-reframe");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function styles() {
|
||||||
|
var i, a, es = document.getElementsByTagName("link"), rs = [];
|
||||||
|
for (i = 0; a = es[i]; i++) {
|
||||||
|
if(a.rel.indexOf("style") != -1 && a.title) {
|
||||||
|
rs.push(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addStyleMenu() {
|
||||||
|
var as = styles();
|
||||||
|
var i, a, btns = "";
|
||||||
|
for(i=0; a = as[i]; i++) {
|
||||||
|
btns += "<li><a href='#' onclick=\"setActiveStyleSheet('"
|
||||||
|
+ a.title + "'); return false;\">"
|
||||||
|
+ a.title + "</a></li>"
|
||||||
|
}
|
||||||
|
if (as.length > 1) {
|
||||||
|
var h = "<div id='style-menu-holder'>"
|
||||||
|
+ "<a href='#' onclick='styleMenu(); return false;'>Style ▾</a>"
|
||||||
|
+ "<ul id='style-menu' class='hide'>" + btns + "</ul>"
|
||||||
|
+ "</div>";
|
||||||
|
addMenuItem(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setActiveStyleSheet(title) {
|
||||||
|
var as = styles();
|
||||||
|
var i, a, found;
|
||||||
|
for(i=0; a = as[i]; i++) {
|
||||||
|
a.disabled = true;
|
||||||
|
// need to do this always, some browsers are edge triggered
|
||||||
|
if(a.title == title) {
|
||||||
|
found = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
found.disabled = false;
|
||||||
|
setCookie("haddock-style", title);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
as[0].disabled = false;
|
||||||
|
clearCookie("haddock-style");
|
||||||
|
}
|
||||||
|
styleMenu(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetStyle() {
|
||||||
|
var s = getCookie("haddock-style");
|
||||||
|
if (s) setActiveStyleSheet(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function styleMenu(show) {
|
||||||
|
var m = document.getElementById('style-menu');
|
||||||
|
if (m) toggleShow(m, show);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function pageLoad() {
|
||||||
|
addStyleMenu();
|
||||||
|
adjustForFrames();
|
||||||
|
resetStyle();
|
||||||
|
restoreCollapsed();
|
||||||
|
}
|
||||||
|
|
BIN
static/typed-process/hslogo-16.png
Normal file
BIN
static/typed-process/hslogo-16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
4
static/typed-process/index-frames.html
Normal file
4
static/typed-process/index-frames.html
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>typed-process-0.1.0.0: Alternative API for processes, featuring more type safety</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
|
||||||
|
window.onload = function () {pageLoad();};
|
||||||
|
//]]>
|
||||||
|
</script></head><body id="mini"><div id="module-list"><p class="caption">Modules</p><ul><li class="module"><a href="System-Process-Typed.html" target="main">System.Process.Typed</a></li></ul></div></body></html>
|
4
static/typed-process/index.html
Normal file
4
static/typed-process/index.html
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>typed-process-0.1.0.0: Alternative API for processes, featuring more type safety</title><link href="ocean.css" rel="stylesheet" type="text/css" title="Ocean" /><script src="haddock-util.js" type="text/javascript"></script><script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" type="text/javascript"></script><script type="text/javascript">//<![CDATA[
|
||||||
|
window.onload = function () {pageLoad();};
|
||||||
|
//]]>
|
||||||
|
</script></head><body><div id="package-header"><ul class="links" id="page-menu"><li><a href="index.html">Contents</a></li><li><a href="doc-index.html">Index</a></li></ul><p class="caption">typed-process-0.1.0.0: Alternative API for processes, featuring more type safety</p></div><div id="content"><div id="description"><h1>typed-process-0.1.0.0: Alternative API for processes, featuring more type safety</h1><div class="doc"><p>Please see README.md</p></div></div><div id="module-list"><p class="caption">Modules</p><ul><li><span id="control.n.1" class="module collapser" onclick="toggleSection('n.1')">System</span><ul id="section.n.1" class="show"><li><span id="control.n.1.1" class="module collapser" onclick="toggleSection('n.1.1')">Process</span><ul id="section.n.1.1" class="show"><li><span class="module"><a href="System-Process-Typed.html">System.Process.Typed</a></span></li></ul></li></ul></li></ul></div></div><div id="footer"><p>Produced by <a href="http://www.haskell.org/haddock/">Haddock</a> version 2.17.2</p></div></body></html>
|
4
static/typed-process/mini_System-Process-Typed.html
Normal file
4
static/typed-process/mini_System-Process-Typed.html
Normal file
File diff suppressed because one or more lines are too long
BIN
static/typed-process/minus.gif
Normal file
BIN
static/typed-process/minus.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 B |
610
static/typed-process/ocean.css
Normal file
610
static/typed-process/ocean.css
Normal file
|
@ -0,0 +1,610 @@
|
||||||
|
/* @group Fundamentals */
|
||||||
|
|
||||||
|
* { margin: 0; padding: 0 }
|
||||||
|
|
||||||
|
/* Is this portable? */
|
||||||
|
html {
|
||||||
|
background-color: white;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: white;
|
||||||
|
color: black;
|
||||||
|
text-align: left;
|
||||||
|
min-height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0.8em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul, ol {
|
||||||
|
margin: 0.8em 0 0.8em 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl {
|
||||||
|
margin: 0.8em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
dd {
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a { text-decoration: none; }
|
||||||
|
a[href]:link { color: rgb(196,69,29); }
|
||||||
|
a[href]:visited { color: rgb(171,105,84); }
|
||||||
|
a[href]:hover { text-decoration:underline; }
|
||||||
|
|
||||||
|
a[href].def:link, a[href].def:visited { color: black; }
|
||||||
|
a[href].def:hover { color: rgb(78, 98, 114); }
|
||||||
|
|
||||||
|
/* @end */
|
||||||
|
|
||||||
|
/* @group Fonts & Sizes */
|
||||||
|
|
||||||
|
/* Basic technique & IE workarounds from YUI 3
|
||||||
|
For reasons, see:
|
||||||
|
http://yui.yahooapis.com/3.1.1/build/cssfonts/fonts.css
|
||||||
|
*/
|
||||||
|
|
||||||
|
body {
|
||||||
|
font:13px/1.4 sans-serif;
|
||||||
|
*font-size:small; /* for IE */
|
||||||
|
*font:x-small; /* for IE in quirks mode */
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 { font-size: 146.5%; /* 19pt */ }
|
||||||
|
h2 { font-size: 131%; /* 17pt */ }
|
||||||
|
h3 { font-size: 116%; /* 15pt */ }
|
||||||
|
h4 { font-size: 100%; /* 13pt */ }
|
||||||
|
h5 { font-size: 100%; /* 13pt */ }
|
||||||
|
|
||||||
|
select, input, button, textarea {
|
||||||
|
font:99% sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
font-size:inherit;
|
||||||
|
font:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre, code, kbd, samp, tt, .src {
|
||||||
|
font-family:monospace;
|
||||||
|
*font-size:108%;
|
||||||
|
line-height: 124%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.links, .link {
|
||||||
|
font-size: 85%; /* 11pt */
|
||||||
|
}
|
||||||
|
|
||||||
|
#module-header .caption {
|
||||||
|
font-size: 182%; /* 24pt */
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
font-size: 85%; /* 11pt */
|
||||||
|
}
|
||||||
|
|
||||||
|
#table-of-contents, #synopsis {
|
||||||
|
/* font-size: 85%; /* 11pt */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* @end */
|
||||||
|
|
||||||
|
/* @group Common */
|
||||||
|
|
||||||
|
.caption, h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-weight: bold;
|
||||||
|
color: rgb(78,98,114);
|
||||||
|
margin: 0.8em 0 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
* + h1, * + h2, * + h3, * + h4, * + h5, * + h6 {
|
||||||
|
margin-top: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 + h2, h2 + h3, h3 + h4, h4 + h5, h5 + h6 {
|
||||||
|
margin-top: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.links {
|
||||||
|
list-style: none;
|
||||||
|
text-align: left;
|
||||||
|
float: right;
|
||||||
|
display: inline-table;
|
||||||
|
margin: 0 0 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.links li {
|
||||||
|
display: inline;
|
||||||
|
border-left: 1px solid #d5d5d5;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.links li a {
|
||||||
|
padding: 0.2em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide { display: none; }
|
||||||
|
.show { display: inherit; }
|
||||||
|
.clear { clear: both; }
|
||||||
|
|
||||||
|
.collapser {
|
||||||
|
background-image: url(minus.gif);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
.expander {
|
||||||
|
background-image: url(plus.gif);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
.collapser, .expander {
|
||||||
|
padding-left: 14px;
|
||||||
|
margin-left: -14px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
p.caption.collapser,
|
||||||
|
p.caption.expander {
|
||||||
|
background-position: 0 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instance.collapser, .instance.expander {
|
||||||
|
margin-left: 0px;
|
||||||
|
background-position: left center;
|
||||||
|
min-width: 9px;
|
||||||
|
min-height: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pre {
|
||||||
|
padding: 0.25em;
|
||||||
|
margin: 0.8em 0;
|
||||||
|
background: rgb(229,237,244);
|
||||||
|
overflow: auto;
|
||||||
|
border-bottom: 0.25em solid white;
|
||||||
|
/* white border adds some space below the box to compensate
|
||||||
|
for visual extra space that paragraphs have between baseline
|
||||||
|
and the bounding box */
|
||||||
|
}
|
||||||
|
|
||||||
|
.src {
|
||||||
|
background: #f0f0f0;
|
||||||
|
padding: 0.2em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.keyword { font-weight: normal; }
|
||||||
|
.def { font-weight: bold; }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
#footer { display: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @end */
|
||||||
|
|
||||||
|
/* @group Page Structure */
|
||||||
|
|
||||||
|
#content {
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 2em 6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#package-header {
|
||||||
|
background: rgb(41,56,69);
|
||||||
|
border-top: 5px solid rgb(78,98,114);
|
||||||
|
color: #ddd;
|
||||||
|
padding: 0.2em;
|
||||||
|
position: relative;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#package-header .caption {
|
||||||
|
background: url(hslogo-16.png) no-repeat 0em;
|
||||||
|
color: white;
|
||||||
|
margin: 0 2em;
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#package-header a:link, #package-header a:visited { color: white; }
|
||||||
|
#package-header a:hover { background: rgb(78,98,114); }
|
||||||
|
|
||||||
|
#module-header .caption {
|
||||||
|
color: rgb(78,98,114);
|
||||||
|
font-weight: bold;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.info {
|
||||||
|
float: right;
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
color: rgb(78,98,114);
|
||||||
|
background-color: #fff;
|
||||||
|
max-width: 40%;
|
||||||
|
border-spacing: 0;
|
||||||
|
position: relative;
|
||||||
|
top: -0.5em;
|
||||||
|
margin: 0 0 0 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info th {
|
||||||
|
padding: 0 1em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#style-menu-holder {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#style-menu {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
overflow: visible;
|
||||||
|
background: #374c5e;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
right: 0;
|
||||||
|
padding: 0;
|
||||||
|
top: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#style-menu li {
|
||||||
|
display: list-item;
|
||||||
|
border-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
color: #000;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#style-menu li + li {
|
||||||
|
border-top: 1px solid #919191;
|
||||||
|
}
|
||||||
|
|
||||||
|
#style-menu a {
|
||||||
|
width: 6em;
|
||||||
|
padding: 3px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
background: #ddd;
|
||||||
|
border-top: 1px solid #aaa;
|
||||||
|
padding: 0.5em 0;
|
||||||
|
color: #666;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @end */
|
||||||
|
|
||||||
|
/* @group Front Matter */
|
||||||
|
|
||||||
|
#table-of-contents {
|
||||||
|
float: right;
|
||||||
|
clear: right;
|
||||||
|
background: #faf9dc;
|
||||||
|
border: 1px solid #d8d7ad;
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
max-width: 20em;
|
||||||
|
margin: 0.5em 0 1em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#table-of-contents .caption {
|
||||||
|
text-align: center;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#table-of-contents ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#table-of-contents ul ul {
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#description .caption {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#synopsis {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-frame #synopsis {
|
||||||
|
display: block;
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
height: 80%;
|
||||||
|
top: 10%;
|
||||||
|
padding: 0;
|
||||||
|
max-width: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#synopsis .caption {
|
||||||
|
float: left;
|
||||||
|
width: 29px;
|
||||||
|
color: rgba(255,255,255,0);
|
||||||
|
height: 110px;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1px;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#synopsis p.caption.collapser {
|
||||||
|
background: url(synopsis.png) no-repeat -64px -8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#synopsis p.caption.expander {
|
||||||
|
background: url(synopsis.png) no-repeat 0px -8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#synopsis ul {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
padding: 0.5em;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#synopsis ul ul {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#synopsis ul,
|
||||||
|
#synopsis ul li.src {
|
||||||
|
background-color: #faf9dc;
|
||||||
|
white-space: nowrap;
|
||||||
|
list-style: none;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @end */
|
||||||
|
|
||||||
|
/* @group Main Content */
|
||||||
|
|
||||||
|
#interface div.top { margin: 2em 0; }
|
||||||
|
#interface h1 + div.top,
|
||||||
|
#interface h2 + div.top,
|
||||||
|
#interface h3 + div.top,
|
||||||
|
#interface h4 + div.top,
|
||||||
|
#interface h5 + div.top {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
#interface .src .selflink,
|
||||||
|
#interface .src .link {
|
||||||
|
float: right;
|
||||||
|
color: #919191;
|
||||||
|
background: #f0f0f0;
|
||||||
|
padding: 0 0.5em 0.2em;
|
||||||
|
margin: 0 -0.5em 0 0;
|
||||||
|
}
|
||||||
|
#interface .src .selflink {
|
||||||
|
border-left: 1px solid #919191;
|
||||||
|
margin: 0 -0.5em 0 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#interface span.fixity {
|
||||||
|
color: #919191;
|
||||||
|
border-left: 1px solid #919191;
|
||||||
|
padding: 0.2em 0.5em 0.2em 0.5em;
|
||||||
|
margin: 0 -1em 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#interface span.rightedge {
|
||||||
|
border-left: 1px solid #919191;
|
||||||
|
padding: 0.2em 0 0.2em 0;
|
||||||
|
margin: 0 0 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#interface table { border-spacing: 2px; }
|
||||||
|
#interface td {
|
||||||
|
vertical-align: top;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
#interface td.src {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
#interface td.doc p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
#interface td.doc p + p {
|
||||||
|
margin-top: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearfix:after {
|
||||||
|
clear: both;
|
||||||
|
content: " ";
|
||||||
|
display: block;
|
||||||
|
height: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subs ul {
|
||||||
|
list-style: none;
|
||||||
|
display: table;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subs ul li {
|
||||||
|
display: table-row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subs ul li dfn {
|
||||||
|
display: table-cell;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 1px 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subs ul li > .doc {
|
||||||
|
display: table-cell;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subs ul li > .doc p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Render short-style data instances */
|
||||||
|
.inst ul {
|
||||||
|
height: 100%;
|
||||||
|
padding: 0.5em;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inst, .inst li {
|
||||||
|
list-style: none;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Workaround for bug in Firefox (issue #384) */
|
||||||
|
.inst-left {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top p.src {
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subs, .doc {
|
||||||
|
/* use this selector for one level of indent */
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arguments {
|
||||||
|
margin-top: -0.4em;
|
||||||
|
}
|
||||||
|
.arguments .caption {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fields { padding-left: 1em; }
|
||||||
|
|
||||||
|
.fields .caption { display: none; }
|
||||||
|
|
||||||
|
.fields p { margin: 0 0; }
|
||||||
|
|
||||||
|
/* this seems bulky to me
|
||||||
|
.methods, .constructors {
|
||||||
|
background: #f8f8f8;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* @end */
|
||||||
|
|
||||||
|
/* @group Auxillary Pages */
|
||||||
|
|
||||||
|
|
||||||
|
.extension-list {
|
||||||
|
list-style-type: none;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mini {
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mini > * {
|
||||||
|
font-size: 93%; /* 12pt */
|
||||||
|
}
|
||||||
|
|
||||||
|
#mini #module-list .caption,
|
||||||
|
#mini #module-header .caption {
|
||||||
|
font-size: 125%; /* 15pt */
|
||||||
|
}
|
||||||
|
|
||||||
|
#mini #interface h1,
|
||||||
|
#mini #interface h2,
|
||||||
|
#mini #interface h3,
|
||||||
|
#mini #interface h4 {
|
||||||
|
font-size: 109%; /* 13pt */
|
||||||
|
margin: 1em 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mini #interface .top,
|
||||||
|
#mini #interface .src {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mini #module-list ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#alphabet ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0.5em 0 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#alphabet li {
|
||||||
|
display: inline;
|
||||||
|
margin: 0 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#alphabet a {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#index .caption,
|
||||||
|
#module-list .caption { font-size: 131%; /* 17pt */ }
|
||||||
|
|
||||||
|
#index table {
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#index .src {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
#index .alt {
|
||||||
|
font-size: 77%; /* 10pt */
|
||||||
|
font-style: italic;
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#index td + td {
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#module-list ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0 0 0 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#module-list li {
|
||||||
|
clear: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#module-list span.collapser,
|
||||||
|
#module-list span.expander {
|
||||||
|
background-position: 0 0.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#module-list .package {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @end */
|
BIN
static/typed-process/plus.gif
Normal file
BIN
static/typed-process/plus.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 59 B |
728
static/typed-process/src/System.Process.Typed.html
Normal file
728
static/typed-process/src/System.Process.Typed.html
Normal file
|
@ -0,0 +1,728 @@
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><link rel="stylesheet" type="text/css" href="style.css" /><script type="text/javascript" src="highlight.js"></script></head><body><pre><span class="hs-pragma">{-# LANGUAGE CPP #-}</span><span>
|
||||||
|
</span><a name="line-2"></a><span class="hs-pragma">{-# LANGUAGE TypeFamilies #-}</span><span>
|
||||||
|
</span><a name="line-3"></a><span class="hs-pragma">{-# LANGUAGE DeriveDataTypeable #-}</span><span>
|
||||||
|
</span><a name="line-4"></a><span class="hs-pragma">{-# LANGUAGE RecordWildCards #-}</span><span>
|
||||||
|
</span><a name="line-5"></a><span class="hs-pragma">{-# LANGUAGE DataKinds #-}</span><span>
|
||||||
|
</span><a name="line-6"></a><span class="hs-pragma">{-# LANGUAGE KindSignatures #-}</span><span>
|
||||||
|
</span><a name="line-7"></a><span class="hs-pragma">{-# LANGUAGE DeriveFunctor #-}</span><span>
|
||||||
|
</span><a name="line-8"></a><span class="hs-comment">-- | Please see the README.md file for examples of using this API.</span><span>
|
||||||
|
</span><a name="line-9"></a><span class="hs-keyword">module</span><span> </span><span class="hs-identifier">System</span><span class="hs-operator">.</span><span class="hs-identifier">Process</span><span class="hs-operator">.</span><span class="hs-identifier">Typed</span><span>
|
||||||
|
</span><a name="line-10"></a><span> </span><span class="hs-special">(</span><span> </span><span class="hs-comment">-- * Types</span><span>
|
||||||
|
</span><a name="line-11"></a><span> </span><a href="System.Process.Typed.html#ProcessConfig"><span class="hs-identifier hs-type">ProcessConfig</span></a><span>
|
||||||
|
</span><a name="line-12"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#StreamSpec"><span class="hs-identifier hs-type">StreamSpec</span></a><span>
|
||||||
|
</span><a name="line-13"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#StreamType"><span class="hs-identifier hs-type">StreamType</span></a><span> </span><span class="hs-special">(</span><span class="hs-glyph">..</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-14"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#Process"><span class="hs-identifier hs-type">Process</span></a><span>
|
||||||
|
</span><a name="line-15"></a><span>
|
||||||
|
</span><a name="line-16"></a><span> </span><span class="hs-comment">-- * ProcessConfig</span><span>
|
||||||
|
</span><a name="line-17"></a><span> </span><span class="hs-comment">-- ** Smart constructors</span><span>
|
||||||
|
</span><a name="line-18"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#proc"><span class="hs-identifier hs-var">proc</span></a><span>
|
||||||
|
</span><a name="line-19"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#shell"><span class="hs-identifier hs-var">shell</span></a><span>
|
||||||
|
</span><a name="line-20"></a><span>
|
||||||
|
</span><a name="line-21"></a><span> </span><span class="hs-comment">-- ** Setters</span><span>
|
||||||
|
</span><a name="line-22"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setStdin"><span class="hs-identifier hs-var">setStdin</span></a><span>
|
||||||
|
</span><a name="line-23"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setStdout"><span class="hs-identifier hs-var">setStdout</span></a><span>
|
||||||
|
</span><a name="line-24"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setStderr"><span class="hs-identifier hs-var">setStderr</span></a><span>
|
||||||
|
</span><a name="line-25"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setWorkingDir"><span class="hs-identifier hs-var">setWorkingDir</span></a><span>
|
||||||
|
</span><a name="line-26"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setEnv"><span class="hs-identifier hs-var">setEnv</span></a><span>
|
||||||
|
</span><a name="line-27"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setCloseFds"><span class="hs-identifier hs-var">setCloseFds</span></a><span>
|
||||||
|
</span><a name="line-28"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setCreateGroup"><span class="hs-identifier hs-var">setCreateGroup</span></a><span>
|
||||||
|
</span><a name="line-29"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setDelegateCtlc"><span class="hs-identifier hs-var">setDelegateCtlc</span></a><span>
|
||||||
|
</span><a name="line-30"></a><span class="hs-cpp">#if MIN_VERSION_process(1, 3, 0)</span><span>
|
||||||
|
</span><a name="line-31"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setDetachConsole"><span class="hs-identifier hs-var">setDetachConsole</span></a><span>
|
||||||
|
</span><a name="line-32"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setCreateNewConsole"><span class="hs-identifier hs-var">setCreateNewConsole</span></a><span>
|
||||||
|
</span><a name="line-33"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setNewSession"><span class="hs-identifier hs-var">setNewSession</span></a><span>
|
||||||
|
</span><a name="line-34"></a><span class="hs-cpp">#endif</span><span>
|
||||||
|
</span><a name="line-35"></a><span class="hs-cpp">#if MIN_VERSION_process(1, 4, 0) && !WINDOWS</span><span>
|
||||||
|
</span><a name="line-36"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setChildGroup"><span class="hs-identifier hs-var">setChildGroup</span></a><span>
|
||||||
|
</span><a name="line-37"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setChildUser"><span class="hs-identifier hs-var">setChildUser</span></a><span>
|
||||||
|
</span><a name="line-38"></a><span class="hs-cpp">#endif</span><span>
|
||||||
|
</span><a name="line-39"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#setCheckExitCode"><span class="hs-identifier hs-var">setCheckExitCode</span></a><span>
|
||||||
|
</span><a name="line-40"></a><span>
|
||||||
|
</span><a name="line-41"></a><span> </span><span class="hs-comment">-- * Stream specs</span><span>
|
||||||
|
</span><a name="line-42"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#mkStreamSpec"><span class="hs-identifier hs-var">mkStreamSpec</span></a><span>
|
||||||
|
</span><a name="line-43"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#inherit"><span class="hs-identifier hs-var">inherit</span></a><span>
|
||||||
|
</span><a name="line-44"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#closed"><span class="hs-identifier hs-var">closed</span></a><span>
|
||||||
|
</span><a name="line-45"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#byteStringInput"><span class="hs-identifier hs-var">byteStringInput</span></a><span>
|
||||||
|
</span><a name="line-46"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#byteStringOutput"><span class="hs-identifier hs-var">byteStringOutput</span></a><span>
|
||||||
|
</span><a name="line-47"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#createPipe"><span class="hs-identifier hs-var">createPipe</span></a><span>
|
||||||
|
</span><a name="line-48"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#useHandleOpen"><span class="hs-identifier hs-var">useHandleOpen</span></a><span>
|
||||||
|
</span><a name="line-49"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#useHandleClose"><span class="hs-identifier hs-var">useHandleClose</span></a><span>
|
||||||
|
</span><a name="line-50"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#sink"><span class="hs-identifier hs-var">sink</span></a><span>
|
||||||
|
</span><a name="line-51"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#source"><span class="hs-identifier hs-var">source</span></a><span>
|
||||||
|
</span><a name="line-52"></a><span>
|
||||||
|
</span><a name="line-53"></a><span> </span><span class="hs-comment">-- * Launch a process</span><span>
|
||||||
|
</span><a name="line-54"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#startProcess"><span class="hs-identifier hs-var">startProcess</span></a><span>
|
||||||
|
</span><a name="line-55"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#stopProcess"><span class="hs-identifier hs-var">stopProcess</span></a><span>
|
||||||
|
</span><a name="line-56"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#withProcess"><span class="hs-identifier hs-var">withProcess</span></a><span>
|
||||||
|
</span><a name="line-57"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#readProcess"><span class="hs-identifier hs-var">readProcess</span></a><span>
|
||||||
|
</span><a name="line-58"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#runProcess"><span class="hs-identifier hs-var">runProcess</span></a><span>
|
||||||
|
</span><a name="line-59"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#runProcess_"><span class="hs-identifier hs-var">runProcess_</span></a><span>
|
||||||
|
</span><a name="line-60"></a><span>
|
||||||
|
</span><a name="line-61"></a><span> </span><span class="hs-comment">-- * Interact with a process</span><span>
|
||||||
|
</span><a name="line-62"></a><span>
|
||||||
|
</span><a name="line-63"></a><span> </span><span class="hs-comment">-- ** Process exit code</span><span>
|
||||||
|
</span><a name="line-64"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#waitExitCode"><span class="hs-identifier hs-var">waitExitCode</span></a><span>
|
||||||
|
</span><a name="line-65"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#waitExitCodeSTM"><span class="hs-identifier hs-var">waitExitCodeSTM</span></a><span>
|
||||||
|
</span><a name="line-66"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#checkExitCode"><span class="hs-identifier hs-var">checkExitCode</span></a><span>
|
||||||
|
</span><a name="line-67"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#checkExitCodeSTM"><span class="hs-identifier hs-var">checkExitCodeSTM</span></a><span>
|
||||||
|
</span><a name="line-68"></a><span>
|
||||||
|
</span><a name="line-69"></a><span> </span><span class="hs-comment">-- ** Process streams</span><span>
|
||||||
|
</span><a name="line-70"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#getStdin"><span class="hs-identifier hs-var">getStdin</span></a><span>
|
||||||
|
</span><a name="line-71"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#getStdout"><span class="hs-identifier hs-var">getStdout</span></a><span>
|
||||||
|
</span><a name="line-72"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#getStderr"><span class="hs-identifier hs-var">getStderr</span></a><span>
|
||||||
|
</span><a name="line-73"></a><span>
|
||||||
|
</span><a name="line-74"></a><span> </span><span class="hs-comment">-- * Exceptions</span><span>
|
||||||
|
</span><a name="line-75"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#ExitCodeException"><span class="hs-identifier hs-type">ExitCodeException</span></a><span> </span><span class="hs-special">(</span><span class="hs-glyph">..</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-76"></a><span> </span><span class="hs-special">,</span><span> </span><a href="System.Process.Typed.html#ByteStringOutputException"><span class="hs-identifier hs-type">ByteStringOutputException</span></a><span> </span><span class="hs-special">(</span><span class="hs-glyph">..</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-77"></a><span> </span><span class="hs-special">)</span><span> </span><span class="hs-keyword">where</span><span>
|
||||||
|
</span><a name="line-78"></a><span>
|
||||||
|
</span><a name="line-79"></a><span class="hs-keyword">import</span><span> </span><span class="hs-keyword">qualified</span><span> </span><span class="hs-identifier">Data</span><span class="hs-operator">.</span><span class="hs-identifier">ByteString</span><span> </span><span class="hs-keyword">as</span><span> </span><span class="hs-identifier">S</span><span>
|
||||||
|
</span><a name="line-80"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">Data</span><span class="hs-operator">.</span><span class="hs-identifier">ByteString</span><span class="hs-operator">.</span><span class="hs-identifier">Lazy</span><span class="hs-operator">.</span><span class="hs-identifier">Internal</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-var">defaultChunkSize</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-81"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">Control</span><span class="hs-operator">.</span><span class="hs-identifier">Exception</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-var">throw</span><span class="hs-special">,</span><span> </span><span class="hs-identifier hs-var">throwIO</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-82"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">Control</span><span class="hs-operator">.</span><span class="hs-identifier">Monad</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-var">void</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-83"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">Control</span><span class="hs-operator">.</span><span class="hs-identifier">Monad</span><span class="hs-operator">.</span><span class="hs-identifier">IO</span><span class="hs-operator">.</span><span class="hs-identifier">Class</span><span>
|
||||||
|
</span><a name="line-84"></a><span class="hs-keyword">import</span><span> </span><span class="hs-keyword">qualified</span><span> </span><span class="hs-identifier">System</span><span class="hs-operator">.</span><span class="hs-identifier">Process</span><span> </span><span class="hs-keyword">as</span><span> </span><span class="hs-identifier">P</span><span>
|
||||||
|
</span><a name="line-85"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">Control</span><span class="hs-operator">.</span><span class="hs-identifier">Monad</span><span class="hs-operator">.</span><span class="hs-identifier">Catch</span><span> </span><span class="hs-keyword">as</span><span> </span><span class="hs-identifier">C</span><span>
|
||||||
|
</span><a name="line-86"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">Data</span><span class="hs-operator">.</span><span class="hs-identifier">Typeable</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-type">Typeable</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-87"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">System</span><span class="hs-operator">.</span><span class="hs-identifier">IO</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-type">Handle</span><span class="hs-special">,</span><span> </span><span class="hs-identifier hs-var">hClose</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-88"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">Control</span><span class="hs-operator">.</span><span class="hs-identifier">Concurrent</span><span class="hs-operator">.</span><span class="hs-identifier">Async</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-var">async</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-89"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">Control</span><span class="hs-operator">.</span><span class="hs-identifier">Concurrent</span><span class="hs-operator">.</span><span class="hs-identifier">STM</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-var">newEmptyTMVarIO</span><span class="hs-special">,</span><span> </span><span class="hs-identifier hs-var">atomically</span><span class="hs-special">,</span><span> </span><span class="hs-identifier hs-var">putTMVar</span><span class="hs-special">,</span><span> </span><span class="hs-identifier hs-type">TMVar</span><span class="hs-special">,</span><span> </span><span class="hs-identifier hs-var">readTMVar</span><span class="hs-special">,</span><span> </span><span class="hs-identifier hs-var">tryReadTMVar</span><span class="hs-special">,</span><span> </span><span class="hs-identifier hs-type">STM</span><span class="hs-special">,</span><span> </span><span class="hs-identifier hs-var">tryPutTMVar</span><span class="hs-special">,</span><span> </span><span class="hs-identifier hs-var">throwSTM</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-90"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">System</span><span class="hs-operator">.</span><span class="hs-identifier">Exit</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-type">ExitCode</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-var">ExitSuccess</span><span class="hs-special">)</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-91"></a><span class="hs-keyword">import</span><span> </span><span class="hs-keyword">qualified</span><span> </span><span class="hs-identifier">Data</span><span class="hs-operator">.</span><span class="hs-identifier">ByteString</span><span class="hs-operator">.</span><span class="hs-identifier">Lazy</span><span> </span><span class="hs-keyword">as</span><span> </span><span class="hs-identifier">L</span><span>
|
||||||
|
</span><a name="line-92"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">Data</span><span class="hs-operator">.</span><span class="hs-identifier">String</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-type">IsString</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-var">fromString</span><span class="hs-special">)</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-93"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">Data</span><span class="hs-operator">.</span><span class="hs-identifier">Conduit</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-type">ConduitM</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-94"></a><span class="hs-keyword">import</span><span> </span><span class="hs-keyword">qualified</span><span> </span><span class="hs-identifier">Data</span><span class="hs-operator">.</span><span class="hs-identifier">Conduit</span><span> </span><span class="hs-keyword">as</span><span> </span><span class="hs-identifier">C</span><span>
|
||||||
|
</span><a name="line-95"></a><span class="hs-keyword">import</span><span> </span><span class="hs-keyword">qualified</span><span> </span><span class="hs-identifier">Data</span><span class="hs-operator">.</span><span class="hs-identifier">Conduit</span><span class="hs-operator">.</span><span class="hs-identifier">Binary</span><span> </span><span class="hs-keyword">as</span><span> </span><span class="hs-identifier">CB</span><span>
|
||||||
|
</span><a name="line-96"></a><span>
|
||||||
|
</span><a name="line-97"></a><span class="hs-cpp">#if MIN_VERSION_process(1, 4, 0) && !WINDOWS</span><span>
|
||||||
|
</span><a name="line-98"></a><span class="hs-keyword">import</span><span> </span><span class="hs-identifier">System</span><span class="hs-operator">.</span><span class="hs-identifier">Posix</span><span class="hs-operator">.</span><span class="hs-identifier">Types</span><span> </span><span class="hs-special">(</span><span class="hs-identifier hs-type">GroupID</span><span class="hs-special">,</span><span> </span><span class="hs-identifier hs-type">UserID</span><span class="hs-special">)</span><span>
|
||||||
|
</span><a name="line-99"></a><span class="hs-cpp">#endif</span><span>
|
||||||
|
</span><a name="line-100"></a><span>
|
||||||
|
</span><a name="line-101"></a><span class="hs-comment">-- | An abstract configuration for a process, which can then be</span><span>
|
||||||
|
</span><a name="line-102"></a><span class="hs-comment">-- launched into an actual running 'Process'. Takes three type</span><span>
|
||||||
|
</span><a name="line-103"></a><span class="hs-comment">-- parameters, providing the types of standard input, standard output,</span><span>
|
||||||
|
</span><a name="line-104"></a><span class="hs-comment">-- and standard error, respectively.</span><span>
|
||||||
|
</span><a name="line-105"></a><span class="hs-comment">--</span><span>
|
||||||
|
</span><a name="line-106"></a><span class="hs-comment">-- There are three ways to construct a value of this type:</span><span>
|
||||||
|
</span><a name="line-107"></a><span class="hs-comment">--</span><span>
|
||||||
|
</span><a name="line-108"></a><span class="hs-comment">-- * With the 'proc' smart constructor, which takes a command name and</span><span>
|
||||||
|
</span><a name="line-109"></a><span class="hs-comment">-- a list of arguments.</span><span>
|
||||||
|
</span><a name="line-110"></a><span class="hs-comment">--</span><span>
|
||||||
|
</span><a name="line-111"></a><span class="hs-comment">-- * With the 'shell' smart constructor, which takes a shell string</span><span>
|
||||||
|
</span><a name="line-112"></a><span class="hs-comment">--</span><span>
|
||||||
|
</span><a name="line-113"></a><span class="hs-comment">-- * With the 'IsString' instance via OverloadedStrings. If you</span><span>
|
||||||
|
</span><a name="line-114"></a><span class="hs-comment">-- provide it a string with no spaces (e.g., @"date"@), it will</span><span>
|
||||||
|
</span><a name="line-115"></a><span class="hs-comment">-- treat it as a raw command with no arguments (e.g., @proc "date"</span><span>
|
||||||
|
</span><a name="line-116"></a><span class="hs-comment">-- []@). If it has spaces, it will use @shell@.</span><span>
|
||||||
|
</span><a name="line-117"></a><span class="hs-comment">--</span><span>
|
||||||
|
</span><a name="line-118"></a><span class="hs-comment">-- In all cases, the default for all three streams is to inherit the</span><span>
|
||||||
|
</span><a name="line-119"></a><span class="hs-comment">-- streams from the parent process. For other settings, see the</span><span>
|
||||||
|
</span><a name="line-120"></a><span class="hs-comment">-- setters below for default values.</span><span>
|
||||||
|
</span><a name="line-121"></a><span class="hs-comment">--</span><span>
|
||||||
|
</span><a name="line-122"></a><span class="hs-comment">-- @since 0.1.0.0</span><span>
|
||||||
|
</span><a name="line-123"></a><span class="hs-keyword">data</span><span> </span><a name="ProcessConfig"><a href="System.Process.Typed.html#ProcessConfig"><span class="hs-identifier">ProcessConfig</span></a></a><span> </span><a name="local-1627412638"><a href="#local-1627412638"><span class="hs-identifier">stdin</span></a></a><span> </span><a name="local-1627412639"><a href="#local-1627412639"><span class="hs-identifier">stdout</span></a></a><span> </span><a name="local-1627412640"><a href="#local-1627412640"><span class="hs-identifier">stderr</span></a></a><span> </span><span class="hs-glyph">=</span><span> </span><a name="ProcessConfig"><a href="System.Process.Typed.html#ProcessConfig"><span class="hs-identifier">ProcessConfig</span></a></a><span>
|
||||||
|
</span><a name="line-124"></a><span> </span><span class="hs-special">{</span><span> </span><a name="pcCmdSpec"><a href="System.Process.Typed.html#pcCmdSpec"><span class="hs-identifier">pcCmdSpec</span></a></a><span> </span><span class="hs-glyph">::</span><span> </span><span class="hs-glyph">!</span><span class="hs-identifier hs-type">P</span><span class="hs-operator hs-type">.</span><span class="hs-identifier hs-type">CmdSpec</span><span>
|
||||||
|
</span><a name="line-125"></a><span> </span><span class="hs-special">,</span><span> </span><a name="pcStdin"><a href="System.Process.Typed.html#pcStdin"><span class="hs-identifier">pcStdin</span></a></a><span> </span><span class="hs-glyph">::</span><span> </span><span class="hs-glyph">!</span><span class="hs-special">(</span><a href="System.Process.Typed.html#StreamSpec"><span class="hs-identifier hs-type">StreamSpec</span></a><span> </span><span class="hs-char">'STInput stdin)
|
||||||
|
, pcStdout :: !(StreamSpec 'STOutput stdout)
|
||||||
|
, pcStderr :: !(StreamSpec 'STOutput stderr)
|
||||||
|
, pcWorkingDir :: !(Maybe FilePath)
|
||||||
|
, pcEnv :: !(Maybe [(String, String)])
|
||||||
|
, pcCloseFds :: !Bool
|
||||||
|
, pcCreateGroup :: !Bool
|
||||||
|
, pcDelegateCtlc :: !Bool
|
||||||
|
|
||||||
|
#if MIN_VERSION_process(1, 3, 0)
|
||||||
|
, pcDetachConsole :: !Bool
|
||||||
|
, pcCreateNewConsole :: !Bool
|
||||||
|
, pcNewSession :: !Bool
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MIN_VERSION_process(1, 4, 0) && !WINDOWS
|
||||||
|
, pcChildGroup :: !(Maybe GroupID)
|
||||||
|
, pcChildUser :: !(Maybe UserID)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
, pcCheckExitCode :: !Bool
|
||||||
|
}
|
||||||
|
instance (stdin ~ (), stdout ~ (), stderr ~ ())
|
||||||
|
=> IsString (ProcessConfig stdin stdout stderr) where
|
||||||
|
fromString s
|
||||||
|
| any (== ' ') s = shell s
|
||||||
|
| otherwise = proc s []
|
||||||
|
|
||||||
|
-- | Whether a stream is an input stream or output stream. Note that
|
||||||
|
-- this is from the perspective of the /child process/, so that a
|
||||||
|
-- child's standard input stream is an @STInput@, even though the
|
||||||
|
-- parent process will be writing to it.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
data StreamType = STInput | STOutput
|
||||||
|
|
||||||
|
-- | A specification for how to create one of the three standard child
|
||||||
|
-- streams. See examples below.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
data StreamSpec (streamType :: StreamType) a = StreamSpec
|
||||||
|
{ ssStream :: !P.StdStream
|
||||||
|
, ssCreate :: !(Maybe Handle -> Cleanup a)
|
||||||
|
}
|
||||||
|
deriving Functor
|
||||||
|
|
||||||
|
-- | This instance uses 'byteStringInput' to convert a raw string into
|
||||||
|
-- a stream of input for a child process.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
instance (streamType ~ 'STInput, res ~ ())
|
||||||
|
=> IsString (StreamSpec streamType res) where
|
||||||
|
fromString = byteStringInput . fromString
|
||||||
|
|
||||||
|
-- | Internal type, to make for easier composition of cleanup actions.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
newtype Cleanup a = Cleanup { runCleanup :: IO (a, IO ()) }
|
||||||
|
deriving Functor
|
||||||
|
instance Applicative Cleanup where
|
||||||
|
pure x = Cleanup (return (x, return ()))
|
||||||
|
Cleanup f <*> Cleanup x = Cleanup $ do
|
||||||
|
(f', c1) <- f
|
||||||
|
(`onException` c1) $ do
|
||||||
|
(x', c2) <- x
|
||||||
|
return (f' x', c1 `finally` c2)
|
||||||
|
|
||||||
|
-- | A running process. The three type parameters provide the type of
|
||||||
|
-- the standard input, standard output, and standard error streams.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
data Process stdin stdout stderr = Process
|
||||||
|
{ pCleanup :: !(IO ())
|
||||||
|
, pStdin :: !stdin
|
||||||
|
, pStdout :: !stdout
|
||||||
|
, pStderr :: !stderr
|
||||||
|
, pHandle :: !P.ProcessHandle
|
||||||
|
, pExitCode :: !(TMVar ExitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
-- | Internal helper
|
||||||
|
defaultProcessConfig :: ProcessConfig () () ()
|
||||||
|
defaultProcessConfig = ProcessConfig
|
||||||
|
{ pcCmdSpec = P.ShellCommand ""
|
||||||
|
, pcStdin = inherit
|
||||||
|
, pcStdout = inherit
|
||||||
|
, pcStderr = inherit
|
||||||
|
, pcWorkingDir = Nothing
|
||||||
|
, pcEnv = Nothing
|
||||||
|
, pcCloseFds = False
|
||||||
|
, pcCreateGroup = False
|
||||||
|
, pcDelegateCtlc = False
|
||||||
|
|
||||||
|
#if MIN_VERSION_process(1, 3, 0)
|
||||||
|
, pcDetachConsole = False
|
||||||
|
, pcCreateNewConsole = False
|
||||||
|
, pcNewSession = False
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MIN_VERSION_process(1, 4, 0) && !WINDOWS
|
||||||
|
, pcChildGroup = Nothing
|
||||||
|
, pcChildUser = Nothing
|
||||||
|
#endif
|
||||||
|
|
||||||
|
, pcCheckExitCode = False
|
||||||
|
}
|
||||||
|
|
||||||
|
-- | Create a 'ProcessConfig' from the given command and arguments.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
proc :: FilePath -> [String] -> ProcessConfig () () ()
|
||||||
|
proc cmd args = setProc cmd args defaultProcessConfig
|
||||||
|
|
||||||
|
-- | Internal helper
|
||||||
|
setProc :: FilePath -> [String]
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setProc cmd args p = p { pcCmdSpec = P.RawCommand cmd args }
|
||||||
|
|
||||||
|
-- | Create a 'ProcessConfig' from the given shell command.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
shell :: String -> ProcessConfig () () ()
|
||||||
|
shell cmd = setShell cmd defaultProcessConfig
|
||||||
|
|
||||||
|
-- | Internal helper
|
||||||
|
setShell :: String
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setShell cmd p = p { pcCmdSpec = P.ShellCommand cmd }
|
||||||
|
|
||||||
|
-- | Set the child's standard input stream to the given 'StreamSpec'.
|
||||||
|
--
|
||||||
|
-- Default: 'inherit'
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setStdin :: StreamSpec 'STInput stdin
|
||||||
|
-> ProcessConfig stdin0 stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setStdin spec pc = pc { pcStdin = spec }
|
||||||
|
|
||||||
|
-- | Set the child's standard output stream to the given 'StreamSpec'.
|
||||||
|
--
|
||||||
|
-- Default: 'inherit'
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setStdout :: StreamSpec 'STOutput stdout
|
||||||
|
-> ProcessConfig stdin stdout0 stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setStdout spec pc = pc { pcStdout = spec }
|
||||||
|
|
||||||
|
-- | Set the child's standard error stream to the given 'StreamSpec'.
|
||||||
|
--
|
||||||
|
-- Default: 'inherit'
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setStderr :: StreamSpec 'STOutput stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr0
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setStderr spec pc = pc { pcStderr = spec }
|
||||||
|
|
||||||
|
-- | Set the working directory of the child process.
|
||||||
|
--
|
||||||
|
-- Default: current process's working directory.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setWorkingDir :: FilePath
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setWorkingDir dir pc = pc { pcWorkingDir = Just dir }
|
||||||
|
|
||||||
|
-- | Set the environment variables of the child process.
|
||||||
|
--
|
||||||
|
-- Default: current process's environment.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setEnv :: [(String, String)]
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setEnv env pc = pc { pcEnv = Just env }
|
||||||
|
|
||||||
|
-- | Should we close all file descriptors besides stdin, stdout, and
|
||||||
|
-- stderr? See 'P.close_fds' for more information.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setCloseFds
|
||||||
|
:: Bool
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setCloseFds x pc = pc { pcCloseFds = x }
|
||||||
|
|
||||||
|
-- | Should we create a new process group?
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setCreateGroup
|
||||||
|
:: Bool
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setCreateGroup x pc = pc { pcCreateGroup = x }
|
||||||
|
|
||||||
|
-- | Delegate handling of Ctrl-C to the child. For more information,
|
||||||
|
-- see 'P.delegate_ctlc'.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setDelegateCtlc
|
||||||
|
:: Bool
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setDelegateCtlc x pc = pc { pcDelegateCtlc = x }
|
||||||
|
|
||||||
|
#if MIN_VERSION_process(1, 3, 0)
|
||||||
|
|
||||||
|
-- | Detach console on Windows, see 'P.detach_console'.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setDetachConsole
|
||||||
|
:: Bool
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setDetachConsole x pc = pc { pcDetachConsole = x }
|
||||||
|
|
||||||
|
-- | Create new console on Windows, see 'P.create_new_console'.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setCreateNewConsole
|
||||||
|
:: Bool
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setCreateNewConsole x pc = pc { pcCreateNewConsole = x }
|
||||||
|
|
||||||
|
-- | Set a new session with the POSIX @setsid@ syscall, does nothing
|
||||||
|
-- on non-POSIX. See 'P.new_session'.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setNewSession
|
||||||
|
:: Bool
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setNewSession x pc = pc { pcNewSession = x }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MIN_VERSION_process(1, 4, 0) && !WINDOWS
|
||||||
|
-- | Set the child process's group ID with the POSIX @setgid@ syscall,
|
||||||
|
-- does nothing on non-POSIX. See 'P.child_group'.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setChildGroup
|
||||||
|
:: GroupID
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setChildGroup x pc = pc { pcChildGroup = Just x }
|
||||||
|
|
||||||
|
-- | Set the child process's user ID with the POSIX @setuid@ syscall,
|
||||||
|
-- does nothing on non-POSIX. See 'P.child_user'.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setChildUser
|
||||||
|
:: UserID
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setChildUser x pc = pc { pcChildUser = Just x }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-- | Should we throw an exception when the process exits with a
|
||||||
|
-- non-success code?
|
||||||
|
--
|
||||||
|
-- If set to 'True', then when 'stopProcess' is called - either
|
||||||
|
-- directly or via 'withProcess' or other wrappers - the processes
|
||||||
|
-- exit code will be checked. Any exit code besides 'ExitSuccess' will
|
||||||
|
-- result in an 'ExitCodeException' being thrown.
|
||||||
|
--
|
||||||
|
-- Default: 'False'
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
setCheckExitCode :: Bool
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
-> ProcessConfig stdin stdout stderr
|
||||||
|
setCheckExitCode x p = p { pcCheckExitCode = x }
|
||||||
|
|
||||||
|
-- TODO: Instead of having this setting, we could consider just having
|
||||||
|
-- alternatives to readProcess, runProcess, etc, that check the exit
|
||||||
|
-- code. This could actually be a really nice convention: readProcess
|
||||||
|
-- does not check, readProcess_ or readProcessCheck does.
|
||||||
|
|
||||||
|
-- | Create a new 'StreamSpec' from the given 'P.StdStream' and a
|
||||||
|
-- helper function. This function:
|
||||||
|
--
|
||||||
|
-- * Takes as input the raw @Maybe Handle@ returned by the
|
||||||
|
-- 'P.createProcess' function. This will be determined by the
|
||||||
|
-- 'P.StdStream' argument.
|
||||||
|
--
|
||||||
|
-- * Returns the actual stream value @a@, as well as a cleanup
|
||||||
|
-- * function to be run when calling 'stopProcess'.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
mkStreamSpec :: P.StdStream
|
||||||
|
-> (Maybe Handle -> IO (a, IO ()))
|
||||||
|
-> StreamSpec streamType a
|
||||||
|
mkStreamSpec ss f = StreamSpec ss (Cleanup . f)
|
||||||
|
|
||||||
|
-- | A stream spec which simply inherits the stream of the parent
|
||||||
|
-- process.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
inherit :: StreamSpec anyStreamType ()
|
||||||
|
inherit = mkStreamSpec P.Inherit (\Nothing -> pure ((), return ()))
|
||||||
|
|
||||||
|
-- | A stream spec which will close the stream for the child process.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
closed :: StreamSpec anyStreamType ()
|
||||||
|
#if MIN_VERSION_process(1, 4, 0)
|
||||||
|
closed = mkStreamSpec P.NoStream (\Nothing -> pure ((), return ()))
|
||||||
|
#else
|
||||||
|
closed = mkStreamSpec P.CreatePipe (\(Just h) -> (((), return ()) <$ hClose h))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
-- | An input stream spec which sets the input to the given
|
||||||
|
-- 'L.ByteString'. A separate thread will be forked to write the
|
||||||
|
-- contents to the child process.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
byteStringInput :: L.ByteString -> StreamSpec 'STInput ()
|
||||||
|
byteStringInput lbs = StreamSpec P.CreatePipe $ \(Just h) -> Cleanup $ do
|
||||||
|
void $ async $ do
|
||||||
|
L.hPut h lbs
|
||||||
|
hClose h
|
||||||
|
return ((), hClose h)
|
||||||
|
|
||||||
|
-- | Capture the output of a process in a 'L.ByteString'.
|
||||||
|
--
|
||||||
|
-- This function will fork a separate thread to consume all input from
|
||||||
|
-- the process, and will only make the results available when the
|
||||||
|
-- underlying 'Handle' is closed. As this is provided as an 'STM'
|
||||||
|
-- action, you can either check if the result is available, or block
|
||||||
|
-- until it's ready.
|
||||||
|
--
|
||||||
|
-- In the event of any exception occurring when reading from the
|
||||||
|
-- 'Handle', the result of this function will be a 'Left' value
|
||||||
|
-- containing a 'ByteStringOutputException'.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
byteStringOutput :: StreamSpec 'STOutput (STM (Either ByteStringOutputException L.ByteString))
|
||||||
|
byteStringOutput = StreamSpec P.CreatePipe $ \(Just h) -> Cleanup $ do
|
||||||
|
mvar <- newEmptyTMVarIO
|
||||||
|
|
||||||
|
void $ async $ do
|
||||||
|
let loop front = do
|
||||||
|
bs <- S.hGetSome h defaultChunkSize
|
||||||
|
if S.null bs
|
||||||
|
then atomically $ putTMVar mvar $ Right $ L.fromChunks $ front []
|
||||||
|
else loop $ front . (bs:)
|
||||||
|
loop id `catch` \e -> do
|
||||||
|
atomically $ void $ tryPutTMVar mvar $ Left $ ByteStringOutputException e
|
||||||
|
throwIO e
|
||||||
|
|
||||||
|
return (readTMVar mvar, hClose h)
|
||||||
|
|
||||||
|
-- | Create a new pipe between this process and the child, and return
|
||||||
|
-- a 'Handle' to communicate with the child.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
createPipe :: StreamSpec anyStreamType Handle
|
||||||
|
createPipe = StreamSpec P.CreatePipe $ \(Just h) -> Cleanup $ return (h, hClose h)
|
||||||
|
|
||||||
|
-- | Use the provided 'Handle' for the child process, and when the
|
||||||
|
-- process exits, do /not/ close it. This is useful if, for example,
|
||||||
|
-- you want to have multiple processes write to the same log file
|
||||||
|
-- sequentially.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
useHandleOpen :: Handle -> StreamSpec anyStreamType ()
|
||||||
|
useHandleOpen h = StreamSpec (P.UseHandle h) $ \Nothing -> Cleanup $ return ((), return ())
|
||||||
|
|
||||||
|
-- | Use the provided 'Handle' for the child process, and when the
|
||||||
|
-- process exits, close it. If you have no reason to keep the 'Handle'
|
||||||
|
-- open, you should use this over 'useHandleOpen'.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
useHandleClose :: Handle -> StreamSpec anyStreamType ()
|
||||||
|
useHandleClose h = StreamSpec (P.UseHandle h) $ \Nothing -> Cleanup $ return ((), hClose h)
|
||||||
|
|
||||||
|
-- | Provide input to a process by writing to a conduit.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
sink :: MonadIO m => StreamSpec 'STInput (ConduitM S.ByteString o m ())
|
||||||
|
sink =
|
||||||
|
(\h -> C.addCleanup (\_ -> liftIO $ hClose h) (CB.sinkHandle h))
|
||||||
|
<$> createPipe
|
||||||
|
|
||||||
|
-- | Read output from a process by read from a conduit.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
source :: MonadIO m => StreamSpec 'STOutput (ConduitM i S.ByteString m ())
|
||||||
|
source =
|
||||||
|
(\h -> C.addCleanup (\_ -> liftIO $ hClose h) (CB.sourceHandle h))
|
||||||
|
<$> createPipe
|
||||||
|
|
||||||
|
-- | Launch a process based on the given 'ProcessConfig'. You should
|
||||||
|
-- ensure that you close 'stopProcess' on the result. It's usually
|
||||||
|
-- better to use one of the functions in this module which ensures
|
||||||
|
-- 'stopProcess' is called, such as 'withProcess'.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
startProcess :: MonadIO m
|
||||||
|
=> ProcessConfig stdin stdout stderr
|
||||||
|
-> m (Process stdin stdout stderr)
|
||||||
|
startProcess ProcessConfig {..} = liftIO $ do
|
||||||
|
let cp0 =
|
||||||
|
case pcCmdSpec of
|
||||||
|
P.ShellCommand cmd -> P.shell cmd
|
||||||
|
P.RawCommand cmd args -> P.proc cmd args
|
||||||
|
cp = cp0
|
||||||
|
{ P.std_in = ssStream pcStdin
|
||||||
|
, P.std_out = ssStream pcStdout
|
||||||
|
, P.std_err = ssStream pcStderr
|
||||||
|
, P.cwd = pcWorkingDir
|
||||||
|
, P.env = pcEnv
|
||||||
|
, P.close_fds = pcCloseFds
|
||||||
|
, P.create_group = pcCreateGroup
|
||||||
|
, P.delegate_ctlc = pcDelegateCtlc
|
||||||
|
|
||||||
|
#if MIN_VERSION_process(1, 3, 0)
|
||||||
|
, P.detach_console = pcDetachConsole
|
||||||
|
, P.create_new_console = pcCreateNewConsole
|
||||||
|
, P.new_session = pcNewSession
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MIN_VERSION_process(1, 4, 0) && !WINDOWS
|
||||||
|
, P.child_group = pcChildGroup
|
||||||
|
, P.child_user = pcChildUser
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
(minH, moutH, merrH, pHandle) <- P.createProcess_ "startProcess" cp
|
||||||
|
|
||||||
|
((pStdin, pStdout, pStderr), pCleanup1) <- runCleanup $ (,,)
|
||||||
|
<$> ssCreate pcStdin minH
|
||||||
|
<*> ssCreate pcStdout moutH
|
||||||
|
<*> ssCreate pcStderr merrH
|
||||||
|
|
||||||
|
pExitCode <- newEmptyTMVarIO
|
||||||
|
void $ async $ do
|
||||||
|
ec <- P.waitForProcess pHandle
|
||||||
|
atomically $ putTMVar pExitCode ec
|
||||||
|
|
||||||
|
let pCleanup2 = pCleanup1 `finally` do
|
||||||
|
mec <- atomically $ tryReadTMVar pExitCode
|
||||||
|
case mec of
|
||||||
|
Nothing -> do
|
||||||
|
P.terminateProcess pHandle
|
||||||
|
-- TODO: should we put in a timeout and then send
|
||||||
|
-- a SIGKILL on Unix?
|
||||||
|
void $ atomically $ readTMVar pExitCode
|
||||||
|
Just _ -> return ()
|
||||||
|
pCleanup
|
||||||
|
| pcCheckExitCode = do
|
||||||
|
eres <- try pCleanup2
|
||||||
|
ec <- atomically $ readTMVar pExitCode
|
||||||
|
case (ec, eres) of
|
||||||
|
(ExitSuccess, Right ()) -> return ()
|
||||||
|
(ExitSuccess, Left e) -> throwIO e
|
||||||
|
_ -> throwIO $ ExitCodeException ec $ either Just (const Nothing) eres
|
||||||
|
| otherwise = pCleanup2
|
||||||
|
|
||||||
|
return Process {..}
|
||||||
|
|
||||||
|
-- | Close a process and release any resources acquired. This will
|
||||||
|
-- ensure 'P.terminateProcess' is called, wait for the process to
|
||||||
|
-- actually exit, and then close out resources allocated for the
|
||||||
|
-- streams. In the event of any cleanup exceptions being thrown, or if
|
||||||
|
-- a non-success exit code was received and 'setCheckExitCode' was
|
||||||
|
-- used, this will throw an exception.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
stopProcess :: MonadIO m
|
||||||
|
=> Process stdin stdout stderr
|
||||||
|
-> m ()
|
||||||
|
stopProcess = liftIO . pCleanup
|
||||||
|
|
||||||
|
-- | Use the bracket pattern to call 'startProcess' and ensure
|
||||||
|
-- 'stopProcess' is called.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
withProcess :: (MonadIO m, C.MonadMask m)
|
||||||
|
=> ProcessConfig stdin stdout stderr
|
||||||
|
-> (Process stdin stdout stderr -> m a)
|
||||||
|
-> m a
|
||||||
|
withProcess config = C.bracket (startProcess config) stopProcess
|
||||||
|
|
||||||
|
-- | Run a process, capture its standard output and error as a
|
||||||
|
-- 'L.ByteString', wait for it to complete, and then return its exit
|
||||||
|
-- code, output, and error.
|
||||||
|
--
|
||||||
|
-- Note that any previously used 'setStdout' or 'setStderr' will be
|
||||||
|
-- overridden.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
readProcess :: MonadIO m
|
||||||
|
=> ProcessConfig stdin stdoutIgnored stderrIgnored
|
||||||
|
-> m (ExitCode, L.ByteString, L.ByteString)
|
||||||
|
readProcess pc =
|
||||||
|
liftIO $ withProcess pc' $ \p -> atomically $ (,,)
|
||||||
|
<$> waitExitCodeSTM p
|
||||||
|
<*> (getStdout p >>= either throwSTM return)
|
||||||
|
<*> (getStderr p >>= either throwSTM return)
|
||||||
|
where
|
||||||
|
pc' = setStdout byteStringOutput
|
||||||
|
$ setStderr byteStringOutput pc
|
||||||
|
|
||||||
|
-- | Run the given process, wait for it to exit, and returns its
|
||||||
|
-- 'ExitCode'.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
runProcess :: MonadIO m
|
||||||
|
=> ProcessConfig stdin stdout stderr
|
||||||
|
-> m ExitCode
|
||||||
|
runProcess pc = liftIO $ withProcess pc waitExitCode
|
||||||
|
|
||||||
|
-- | Same as 'runProcess', but ignores the 'ExitCode'.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
runProcess_ :: MonadIO m
|
||||||
|
=> ProcessConfig stdin stdout stderr
|
||||||
|
-> m ()
|
||||||
|
runProcess_ = void . runProcess
|
||||||
|
|
||||||
|
-- | Wait for the process to exit and then return its 'ExitCode'.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
waitExitCode :: MonadIO m => Process stdin stdout stderr -> m ExitCode
|
||||||
|
waitExitCode = liftIO . atomically . waitExitCodeSTM
|
||||||
|
|
||||||
|
-- | Same as 'waitExitCode', but in 'STM'.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
waitExitCodeSTM :: Process stdin stdout stderr -> STM ExitCode
|
||||||
|
waitExitCodeSTM = readTMVar . pExitCode
|
||||||
|
|
||||||
|
-- | Check if a process has exited and, if so, return its 'ExitCode'.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
checkExitCode :: MonadIO m => Process stdin stdout stderr -> m (Maybe ExitCode)
|
||||||
|
checkExitCode = liftIO . atomically . checkExitCodeSTM
|
||||||
|
|
||||||
|
-- | Same as 'checkExitCode', but in 'STM'.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
checkExitCodeSTM :: Process stdin stdout stderr -> STM (Maybe ExitCode)
|
||||||
|
checkExitCodeSTM = tryReadTMVar . pExitCode
|
||||||
|
|
||||||
|
-- | Get the child's standard input stream value.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
getStdin :: Process stdin stdout stderr -> stdin
|
||||||
|
getStdin = pStdin
|
||||||
|
|
||||||
|
-- | Get the child's standard output stream value.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
getStdout :: Process stdin stdout stderr -> stdout
|
||||||
|
getStdout = pStdout
|
||||||
|
|
||||||
|
-- | Get the child's standard error stream value.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
getStderr :: Process stdin stdout stderr -> stderr
|
||||||
|
getStderr = pStderr
|
||||||
|
|
||||||
|
-- | Exit code generated by 'stopProcess' when 'setCheckExitCode' is
|
||||||
|
-- 'True' and a process exits with a non-success code. Contains the
|
||||||
|
-- non-success code, and if any other exceptions occur during cleanup,
|
||||||
|
-- that exception.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
data ExitCodeException = ExitCodeException ExitCode (Maybe SomeException)
|
||||||
|
deriving (Show, Typeable)
|
||||||
|
instance Exception ExitCodeException
|
||||||
|
|
||||||
|
-- | Wrapper for when an exception is thrown when reading from a child
|
||||||
|
-- process, used by 'byteStringOutput'.
|
||||||
|
--
|
||||||
|
-- @since 0.1.0.0
|
||||||
|
newtype ByteStringOutputException = ByteStringOutputException SomeException
|
||||||
|
deriving (Show, Typeable)
|
||||||
|
instance Exception ByteStringOutputException
|
||||||
|
</span></pre></body></html>
|
27
static/typed-process/src/highlight.js
Normal file
27
static/typed-process/src/highlight.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
|
||||||
|
var highlight = function (on) {
|
||||||
|
return function () {
|
||||||
|
var links = document.getElementsByTagName('a');
|
||||||
|
for (var i = 0; i < links.length; i++) {
|
||||||
|
var that = links[i];
|
||||||
|
|
||||||
|
if (this.href != that.href) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (on) {
|
||||||
|
that.classList.add("hover-highlight");
|
||||||
|
} else {
|
||||||
|
that.classList.remove("hover-highlight");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.onload = function () {
|
||||||
|
var links = document.getElementsByTagName('a');
|
||||||
|
for (var i = 0; i < links.length; i++) {
|
||||||
|
links[i].onmouseover = highlight(true);
|
||||||
|
links[i].onmouseout = highlight(false);
|
||||||
|
}
|
||||||
|
};
|
55
static/typed-process/src/style.css
Normal file
55
static/typed-process/src/style.css
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
body {
|
||||||
|
background-color: #fdf6e3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-identifier {
|
||||||
|
color: #073642;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-identifier.hs-var {
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-identifier.hs-type {
|
||||||
|
color: #5f5faf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-keyword {
|
||||||
|
color: #af005f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-string, .hs-char {
|
||||||
|
color: #cb4b16;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-number {
|
||||||
|
color: #268bd2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-operator {
|
||||||
|
color: #d33682;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-glyph, .hs-special {
|
||||||
|
color: #dc322f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-comment {
|
||||||
|
color: #8a8a8a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-pragma {
|
||||||
|
color: #2aa198;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hs-cpp {
|
||||||
|
color: #859900;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:link, a:visited {
|
||||||
|
text-decoration: none;
|
||||||
|
border-bottom: 1px solid #eee8d5;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover, a.hover-highlight {
|
||||||
|
background-color: #eee8d5;
|
||||||
|
}
|
BIN
static/typed-process/synopsis.png
Normal file
BIN
static/typed-process/synopsis.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
static/typed-process/typed-process.haddock
Normal file
BIN
static/typed-process/typed-process.haddock
Normal file
Binary file not shown.
272
static/typed-process/typed-process.txt
Normal file
272
static/typed-process/typed-process.txt
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
-- Hoogle documentation, generated by Haddock
|
||||||
|
-- See Hoogle, http://www.haskell.org/hoogle/
|
||||||
|
|
||||||
|
|
||||||
|
-- | Alternative API for processes, featuring more type safety
|
||||||
|
--
|
||||||
|
-- Please see README.md
|
||||||
|
@package typed-process
|
||||||
|
@version 0.1.0.0
|
||||||
|
|
||||||
|
|
||||||
|
-- | Please see the README.md file for examples of using this API.
|
||||||
|
module System.Process.Typed
|
||||||
|
|
||||||
|
-- | An abstract configuration for a process, which can then be launched
|
||||||
|
-- into an actual running <a>Process</a>. Takes three type parameters,
|
||||||
|
-- providing the types of standard input, standard output, and standard
|
||||||
|
-- error, respectively.
|
||||||
|
--
|
||||||
|
-- There are three ways to construct a value of this type:
|
||||||
|
--
|
||||||
|
-- <ul>
|
||||||
|
-- <li>With the <a>proc</a> smart constructor, which takes a command name
|
||||||
|
-- and a list of arguments.</li>
|
||||||
|
-- <li>With the <a>shell</a> smart constructor, which takes a shell
|
||||||
|
-- string</li>
|
||||||
|
-- <li>With the <a>IsString</a> instance via OverloadedStrings. If you
|
||||||
|
-- provide it a string with no spaces (e.g., <tt>"date"</tt>), it will
|
||||||
|
-- treat it as a raw command with no arguments (e.g., <tt>proc "date"
|
||||||
|
-- []</tt>). If it has spaces, it will use <tt>shell</tt>.</li>
|
||||||
|
-- </ul>
|
||||||
|
--
|
||||||
|
-- In all cases, the default for all three streams is to inherit the
|
||||||
|
-- streams from the parent process. For other settings, see the setters
|
||||||
|
-- below for default values.
|
||||||
|
data ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | A specification for how to create one of the three standard child
|
||||||
|
-- streams. See examples below.
|
||||||
|
data StreamSpec (streamType :: StreamType) a
|
||||||
|
|
||||||
|
-- | Whether a stream is an input stream or output stream. Note that this
|
||||||
|
-- is from the perspective of the <i>child process</i>, so that a child's
|
||||||
|
-- standard input stream is an <tt>STInput</tt>, even though the parent
|
||||||
|
-- process will be writing to it.
|
||||||
|
data StreamType
|
||||||
|
STInput :: StreamType
|
||||||
|
STOutput :: StreamType
|
||||||
|
|
||||||
|
-- | A running process. The three type parameters provide the type of the
|
||||||
|
-- standard input, standard output, and standard error streams.
|
||||||
|
data Process stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Create a <a>ProcessConfig</a> from the given command and arguments.
|
||||||
|
proc :: FilePath -> [String] -> ProcessConfig () () ()
|
||||||
|
|
||||||
|
-- | Create a <a>ProcessConfig</a> from the given shell command.
|
||||||
|
shell :: String -> ProcessConfig () () ()
|
||||||
|
|
||||||
|
-- | Set the child's standard input stream to the given <a>StreamSpec</a>.
|
||||||
|
--
|
||||||
|
-- Default: <a>inherit</a>
|
||||||
|
setStdin :: StreamSpec STInput stdin -> ProcessConfig stdin0 stdout stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Set the child's standard output stream to the given <a>StreamSpec</a>.
|
||||||
|
--
|
||||||
|
-- Default: <a>inherit</a>
|
||||||
|
setStdout :: StreamSpec STOutput stdout -> ProcessConfig stdin stdout0 stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Set the child's standard error stream to the given <a>StreamSpec</a>.
|
||||||
|
--
|
||||||
|
-- Default: <a>inherit</a>
|
||||||
|
setStderr :: StreamSpec STOutput stderr -> ProcessConfig stdin stdout stderr0 -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Set the working directory of the child process.
|
||||||
|
--
|
||||||
|
-- Default: current process's working directory.
|
||||||
|
setWorkingDir :: FilePath -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Set the environment variables of the child process.
|
||||||
|
--
|
||||||
|
-- Default: current process's environment.
|
||||||
|
setEnv :: [(String, String)] -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Should we close all file descriptors besides stdin, stdout, and
|
||||||
|
-- stderr? See <a>close_fds</a> for more information.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
setCloseFds :: Bool -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Should we create a new process group?
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
setCreateGroup :: Bool -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Delegate handling of Ctrl-C to the child. For more information, see
|
||||||
|
-- <a>delegate_ctlc</a>.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
setDelegateCtlc :: Bool -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Detach console on Windows, see <a>detach_console</a>.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
setDetachConsole :: Bool -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Create new console on Windows, see <a>create_new_console</a>.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
setCreateNewConsole :: Bool -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Set a new session with the POSIX <tt>setsid</tt> syscall, does nothing
|
||||||
|
-- on non-POSIX. See <a>new_session</a>.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
setNewSession :: Bool -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Set the child process's group ID with the POSIX <tt>setgid</tt>
|
||||||
|
-- syscall, does nothing on non-POSIX. See <a>child_group</a>.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
setChildGroup :: GroupID -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Set the child process's user ID with the POSIX <tt>setuid</tt>
|
||||||
|
-- syscall, does nothing on non-POSIX. See <a>child_user</a>.
|
||||||
|
--
|
||||||
|
-- Default: False
|
||||||
|
setChildUser :: UserID -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Should we throw an exception when the process exits with a non-success
|
||||||
|
-- code?
|
||||||
|
--
|
||||||
|
-- If set to <a>True</a>, then when <a>stopProcess</a> is called - either
|
||||||
|
-- directly or via <a>withProcess</a> or other wrappers - the processes
|
||||||
|
-- exit code will be checked. Any exit code besides <a>ExitSuccess</a>
|
||||||
|
-- will result in an <a>ExitCodeException</a> being thrown.
|
||||||
|
--
|
||||||
|
-- Default: <a>False</a>
|
||||||
|
setCheckExitCode :: Bool -> ProcessConfig stdin stdout stderr -> ProcessConfig stdin stdout stderr
|
||||||
|
|
||||||
|
-- | Create a new <a>StreamSpec</a> from the given <a>StdStream</a> and a
|
||||||
|
-- helper function. This function:
|
||||||
|
--
|
||||||
|
-- <ul>
|
||||||
|
-- <li>Takes as input the raw <tt>Maybe Handle</tt> returned by the
|
||||||
|
-- <a>createProcess</a> function. This will be determined by the
|
||||||
|
-- <a>StdStream</a> argument.</li>
|
||||||
|
-- <li>Returns the actual stream value <tt>a</tt>, as well as a
|
||||||
|
-- cleanup</li>
|
||||||
|
-- <li>function to be run when calling <a>stopProcess</a>.</li>
|
||||||
|
-- </ul>
|
||||||
|
mkStreamSpec :: StdStream -> (Maybe Handle -> IO (a, IO ())) -> StreamSpec streamType a
|
||||||
|
|
||||||
|
-- | A stream spec which simply inherits the stream of the parent process.
|
||||||
|
inherit :: StreamSpec anyStreamType ()
|
||||||
|
|
||||||
|
-- | A stream spec which will close the stream for the child process.
|
||||||
|
closed :: StreamSpec anyStreamType ()
|
||||||
|
|
||||||
|
-- | An input stream spec which sets the input to the given
|
||||||
|
-- <a>ByteString</a>. A separate thread will be forked to write the
|
||||||
|
-- contents to the child process.
|
||||||
|
byteStringInput :: ByteString -> StreamSpec STInput ()
|
||||||
|
|
||||||
|
-- | Capture the output of a process in a <a>ByteString</a>.
|
||||||
|
--
|
||||||
|
-- This function will fork a separate thread to consume all input from
|
||||||
|
-- the process, and will only make the results available when the
|
||||||
|
-- underlying <a>Handle</a> is closed. As this is provided as an
|
||||||
|
-- <a>STM</a> action, you can either check if the result is available, or
|
||||||
|
-- block until it's ready.
|
||||||
|
--
|
||||||
|
-- In the event of any exception occurring when reading from the
|
||||||
|
-- <a>Handle</a>, the result of this function will be a <a>Left</a> value
|
||||||
|
-- containing a <a>ByteStringOutputException</a>.
|
||||||
|
byteStringOutput :: StreamSpec STOutput (STM (Either ByteStringOutputException ByteString))
|
||||||
|
|
||||||
|
-- | Create a new pipe between this process and the child, and return a
|
||||||
|
-- <a>Handle</a> to communicate with the child.
|
||||||
|
createPipe :: StreamSpec anyStreamType Handle
|
||||||
|
|
||||||
|
-- | Use the provided <a>Handle</a> for the child process, and when the
|
||||||
|
-- process exits, do <i>not</i> close it. This is useful if, for example,
|
||||||
|
-- you want to have multiple processes write to the same log file
|
||||||
|
-- sequentially.
|
||||||
|
useHandleOpen :: Handle -> StreamSpec anyStreamType ()
|
||||||
|
|
||||||
|
-- | Use the provided <a>Handle</a> for the child process, and when the
|
||||||
|
-- process exits, close it. If you have no reason to keep the
|
||||||
|
-- <a>Handle</a> open, you should use this over <a>useHandleOpen</a>.
|
||||||
|
useHandleClose :: Handle -> StreamSpec anyStreamType ()
|
||||||
|
|
||||||
|
-- | Provide input to a process by writing to a conduit.
|
||||||
|
sink :: MonadIO m => StreamSpec STInput (ConduitM ByteString o m ())
|
||||||
|
|
||||||
|
-- | Read output from a process by read from a conduit.
|
||||||
|
source :: MonadIO m => StreamSpec STOutput (ConduitM i ByteString m ())
|
||||||
|
|
||||||
|
-- | Launch a process based on the given <a>ProcessConfig</a>. You should
|
||||||
|
-- ensure that you close <a>stopProcess</a> on the result. It's usually
|
||||||
|
-- better to use one of the functions in this module which ensures
|
||||||
|
-- <a>stopProcess</a> is called, such as <a>withProcess</a>.
|
||||||
|
startProcess :: MonadIO m => ProcessConfig stdin stdout stderr -> m (Process stdin stdout stderr)
|
||||||
|
|
||||||
|
-- | Close a process and release any resources acquired. This will ensure
|
||||||
|
-- <a>terminateProcess</a> is called, wait for the process to actually
|
||||||
|
-- exit, and then close out resources allocated for the streams. In the
|
||||||
|
-- event of any cleanup exceptions being thrown, or if a non-success exit
|
||||||
|
-- code was received and <a>setCheckExitCode</a> was used, this will
|
||||||
|
-- throw an exception.
|
||||||
|
stopProcess :: MonadIO m => Process stdin stdout stderr -> m ()
|
||||||
|
|
||||||
|
-- | Use the bracket pattern to call <a>startProcess</a> and ensure
|
||||||
|
-- <a>stopProcess</a> is called.
|
||||||
|
withProcess :: (MonadIO m, MonadMask m) => ProcessConfig stdin stdout stderr -> (Process stdin stdout stderr -> m a) -> m a
|
||||||
|
|
||||||
|
-- | Run a process, capture its standard output and error as a
|
||||||
|
-- <a>ByteString</a>, wait for it to complete, and then return its exit
|
||||||
|
-- code, output, and error.
|
||||||
|
--
|
||||||
|
-- Note that any previously used <a>setStdout</a> or <a>setStderr</a>
|
||||||
|
-- will be overridden.
|
||||||
|
readProcess :: MonadIO m => ProcessConfig stdin stdoutIgnored stderrIgnored -> m (ExitCode, ByteString, ByteString)
|
||||||
|
|
||||||
|
-- | Run the given process, wait for it to exit, and returns its
|
||||||
|
-- <a>ExitCode</a>.
|
||||||
|
runProcess :: MonadIO m => ProcessConfig stdin stdout stderr -> m ExitCode
|
||||||
|
|
||||||
|
-- | Same as <a>runProcess</a>, but ignores the <a>ExitCode</a>.
|
||||||
|
runProcess_ :: MonadIO m => ProcessConfig stdin stdout stderr -> m ()
|
||||||
|
|
||||||
|
-- | Wait for the process to exit and then return its <a>ExitCode</a>.
|
||||||
|
waitExitCode :: MonadIO m => Process stdin stdout stderr -> m ExitCode
|
||||||
|
|
||||||
|
-- | Same as <a>waitExitCode</a>, but in <a>STM</a>.
|
||||||
|
waitExitCodeSTM :: Process stdin stdout stderr -> STM ExitCode
|
||||||
|
|
||||||
|
-- | Check if a process has exited and, if so, return its <a>ExitCode</a>.
|
||||||
|
checkExitCode :: MonadIO m => Process stdin stdout stderr -> m (Maybe ExitCode)
|
||||||
|
|
||||||
|
-- | Same as <a>checkExitCode</a>, but in <a>STM</a>.
|
||||||
|
checkExitCodeSTM :: Process stdin stdout stderr -> STM (Maybe ExitCode)
|
||||||
|
|
||||||
|
-- | Get the child's standard input stream value.
|
||||||
|
getStdin :: Process stdin stdout stderr -> stdin
|
||||||
|
|
||||||
|
-- | Get the child's standard output stream value.
|
||||||
|
getStdout :: Process stdin stdout stderr -> stdout
|
||||||
|
|
||||||
|
-- | Get the child's standard error stream value.
|
||||||
|
getStderr :: Process stdin stdout stderr -> stderr
|
||||||
|
|
||||||
|
-- | Exit code generated by <a>stopProcess</a> when <a>setCheckExitCode</a>
|
||||||
|
-- is <a>True</a> and a process exits with a non-success code. Contains
|
||||||
|
-- the non-success code, and if any other exceptions occur during
|
||||||
|
-- cleanup, that exception.
|
||||||
|
data ExitCodeException
|
||||||
|
ExitCodeException :: ExitCode -> (Maybe SomeException) -> ExitCodeException
|
||||||
|
|
||||||
|
-- | Wrapper for when an exception is thrown when reading from a child
|
||||||
|
-- process, used by <a>byteStringOutput</a>.
|
||||||
|
newtype ByteStringOutputException
|
||||||
|
ByteStringOutputException :: SomeException -> ByteStringOutputException
|
||||||
|
instance GHC.Show.Show System.Process.Typed.ByteStringOutputException
|
||||||
|
instance GHC.Show.Show System.Process.Typed.ExitCodeException
|
||||||
|
instance GHC.Base.Functor (System.Process.Typed.StreamSpec streamType)
|
||||||
|
instance GHC.Base.Functor System.Process.Typed.Cleanup
|
||||||
|
instance (stdin ~ (), stdout ~ (), stderr ~ ()) => Data.String.IsString (System.Process.Typed.ProcessConfig stdin stdout stderr)
|
||||||
|
instance (streamType ~ 'System.Process.Typed.STInput, res ~ ()) => Data.String.IsString (System.Process.Typed.StreamSpec streamType res)
|
||||||
|
instance GHC.Base.Applicative System.Process.Typed.Cleanup
|
||||||
|
instance GHC.Exception.Exception System.Process.Typed.ExitCodeException
|
||||||
|
instance GHC.Exception.Exception System.Process.Typed.ByteStringOutputException
|
Loading…
Reference in a new issue