# encoding: ascii
# api: powershell
# title: Get-Scope
# description: A script to help you figure out what scope you are in “right now” (you have to always call it like: . Get-Scope $MyInvocation)
# version: 0.1
# type: function
# author: Joel Bennett
# license: CC0
# function: Get-Scope
# x-poshcode-id: 3470
# x-archived: 2012-06-30T20:28:06
# x-published: 2012-06-20T21:45:00
#
# UPDATE:
# Fixed IsGlobalScope so that it’s right (as long as you dot-source the call to Get-Scope)
# Added IsInteractive calculation so you can tell if the caller was invoked from the command line (vs. from another script/function)
#
#function Get-Scope {
#.Synopsis 
#  Determine the scope of execution (are you in a module? how many scope layers deep are you?)
#.Parameter Invocation
#  In order to correctly determine the scope, this function requires that you pass in the $MyInvocation variable when you call it.
#.Parameter ToHost
#  If you just want to *see* the value in the console to debug something, you can pass this switch (and optionally, set the foreground/background colors)
#.Parameter Foreground
#  The Foreground color of host output
#.Parameter Background
#  The Background color of host output
#.Example
# $scope = Get-Scope $MyInvocation
#
# Description
# -----------
# Call Get-Scope and store the output so you can test if you're in module scope, etc.
#.Example
# Get-Scope $MyInvocation -ToHost Magenta DarkBlue
#
# Description
# -----------
# Call Get-Scope and write the output to host, specifying the foreground and background colors

[CmdletBinding()]
param(
   [Parameter(Position=0,Mandatory=$false)]
   [System.Management.Automation.InvocationInfo]$Invocation = $((Get-Variable -scope 1 'MyInvocation').Value)
,
   [Parameter(ParameterSetName="Debugging")]
   [Switch]$ToHost
,
   [Parameter(Position=1,ParameterSetName="Debugging")]
   [ConsoleColor]$Foreground = "Cyan"
,
   [Parameter(Position=2,ParameterSetName="Debugging")]
   [ConsoleColor]$Background = "Black"
)
end {
   function Get-ScopeDepth {
      trap { continue }
      $depth = 0
      do {
        Set-Variable scope_test -Value $depth -Scope ($depth++)
      } while($?)
      return $depth - 1
   }
   $depth = . Get-ScopeDepth
   $callstack = Get-PSCallStack
   
	$IsInteractive = $true
   foreach ($entry in $callStack[1..($callStack.Count - 1)]) {
      write-host $($entry | fl | out-string) -fore Cyan
      if((@('&','.','<ScriptBlock>') -contains $entry.Command)) { # @('&','.') -contains $entry.Position.Text[0]
         continue
      }
      if (($entry.Command -eq 'prompt') -or ($entry.Location -eq 'prompt')) {
         write-host "Found the prompt, we're done here"
         break
      }
      $IsInteractive = $false
      break
   }
   
   $IsGlobal = 0 -eq (Get-Variable scope_test -Scope global).Value

   Remove-Variable scope_test
   Remove-Variable scope_test -Scope global -EA 0

   $PSScope = New-Object PSObject -Property @{ 
      Module = $Invocation.MyCommand.Module
      IsModuleScope = [bool]$Invocation.MyCommand.Module
      IsGlobalScope = $IsGlobal
      IsInteractive = $IsInteractive
      ScopeDepth  = $depth
      PipelinePosition = $Invocation.PipelinePosition
      PipelineLength = $Invocation.PipelineLength
      StackDepth = $callstack.Count - 1
      Invocation = $Invocation
      CallStack = $callstack
   }
   
   if($ToHost) {
      &{
         $PSScope, $PSScope.Invocation | Out-String 
      } | Write-Host -Foreground $Foreground -Background $Background
   } else {
      $PSScope
   }
}
#}
