Languages/R/R-Language.ps.ps1

Language function R {
<#
.SYNOPSIS
    R PipeScript Language Definition.
.DESCRIPTION
    Allows PipeScript to generate R.

    Because R Scripts only allow single-line comments, this is done using a pair of comment markers.

    # { or # PipeScript{ begins a PipeScript block

    # } or # }PipeScript ends a PipeScript block

    ~~~r
    # {

    Uncommented lines between these two points will be ignored

    # # Commented lines will become PipeScript / PowerShell.
    # param($message = "hello world")
    # "puts `"$message`""

    # }
    ~~~
.EXAMPLE
    Invoke-PipeScript {
        $rScript = '
    # {

    Uncommented lines between these two points will be ignored

    # # Commented lines will become PipeScript / PowerShell.
    # param($message = "hello world")
    # "print(`"$message`")"

    # }
    '
    
        [OutputFile('.\HelloWorld.ps1.r')]$rScript
    }

    Invoke-PipeScript .\HelloWorld.ps1.r
#>

[ValidatePattern('\.r$')]
param()
    $FilePattern = '\.r$'

    $SingleLineCommentStart = '\#'
    # Any Language can be parsed with a series of regular expresssions.
    # For languages that only support single comments:
    # * The capture group IsSingleLine must be defined.
    # * Whitespace should not be allowed (it makes nested blocks hard to end)
    $startComment = "(?>(?<IsSingleLine>$SingleLineCommentStart)(?>PipeScript|PS)?\{)"
    $endComment   = "(?>$SingleLineCommentStart(?:PipeScript)?\})"

    # To support templates, a language has to declare `$StartPattern` and `$EndPattern`:
    $StartPattern = "(?<PSStart>${startComment})"
    $EndPattern   = "(?<PSEnd>${endComment})"
        # Using -LinePattern will skip any inline code not starting with #
    $LinePattern   = "^\s{0,}\#\s{0,}"

    # We might have to go looking for R's interpreter
    $interpreter = $(
        # (it may just be in the path)
        if ($ExecutionContext.SessionState.InvokeCommand.GetCommand('RScript', 'Application')) {
            $ExecutionContext.SessionState.InvokeCommand.GetCommand('RScript', 'Application')
        } elseif (
            # Or, if we're on Windows and there's a R ProgramFiles directory
            $IsWindows -and (Test-Path (Join-Path $env:ProgramFiles 'R'))
        ) {
            
            # We can look in there
            $ExecutionContext.SessionState.InvokeCommand.GetCommand("$(
                Join-Path $env:ProgramFiles 'R' |
                Get-ChildItem -Directory |
                # for the most recent version of R
                Sort-Object { ($_.Name -replace '^R-') -as [Version]} -Descending |
                Select-Object -First 1 |
                Join-Path -ChildPath "bin" |
                Join-Path -ChildPath "RScript.exe"
            )"
, "Application")
        }
    )
}