# encoding: ascii
# api: powershell
# title: buffer/take
# description: Port of Perl 6’s gather/take but for appending to a string instead of to a list.
# version: 0.1
# type: function
# author: Public Domain
# license: CC0
# x-poshcode-id: 5132
# x-archived: 2014-05-05T02:13:50
# x-published: 2014-04-30T20:49:00
#
#
function buffer {
#.SYNOPSIS
#  Like gather/take but for strings
#.PARAMETER Using
#  An already existing StringBuilder to append to
#.EXAMPLE
#  buffer -Separator ' ' { 1 ; take "Hello" ; 3 ; take "World" }
#  Hello World
#.NOTES
#  Use [System.Environment]::NewLine as the Terminator to simulate Out-String
#.LINK
#  Out-String
	[CmdletBinding(DefaultParameterSetName = 'T')]
	param(
		[Parameter(Mandatory, Position = 0)]
		[scriptblock]$Script
,
		[Parameter(ParameterSetName='S')]
		[string]$Separator
,
		[Parameter(ParameterSetName='T')]
		[string]$Terminator
,
		[ValidateNotNull()]
		[System.Text.StringBuilder]$Using
	)
	try {
		${function:take} = (New-Object System.Management.Automation.PSModuleInfo $true).NewBoundScriptBlock({
			if (0 -clt $script:state) { $script:acc.Append($script:sep) }
			foreach ($null in $args) { $script:acc.Append([string]$foreach.Current) }
			if (0 -ceq $script:state) { $script:acc.Append($script:sep) } else { $script:state = 1 }
		})
		& ${function:take}.Module {
			$script:acc, $script:sep, $script:state = $args
		}	$(if ($PSBoundParameters.ContainsKey('Using')) { $Using } else { [System.Text.StringBuilder]0 }) `
			$(if ($PSCmdlet.ParameterSetName -ceq 'S') { $Separator } else { $Terminator }) `
			(-($PSCmdlet.ParameterSetName -ceq 'S'))
	} catch {
		throw
	}
	$null = & $Script
	if (-not $PSBoundParameters.ContainsKey('Using')) {
		& ${function:take}.Module { $script:acc.ToString() }
	}
}
