JanDeDobbeleer / oh-my-posh

The most customisable and low-latency cross platform/shell prompt renderer
https://ohmyposh.dev
MIT License
16.7k stars 2.34k forks source link

[`pwsh`] - `debug_prompt` Not Showing During Module ( `psm1` ) Debugging #2483

Closed mattcargile closed 2 years ago

mattcargile commented 2 years ago

Code of Conduct

What happened?

debug_prompt isn't shown when debugging psm1 file. The Test-PSDebugContext returns $false within debugging context. The $PSDebugContext is loaded. Below is the applicable function.

https://github.com/JanDeDobbeleer/oh-my-posh/blob/65192cb065eba4e129e7bbea0d59f72987a73e14/src/shell/scripts/omp.ps1#L17

Repro

ni t.psm1 -Value @'
function t {
$x = 'hello world'
write-output $x
}
'@; sbp t.psm1 -Line 3; ipmo .\t.psm1; t

Theme

All Themes.

What OS are you seeing the problem on?

Windows

Which shell are you using?

powershell

Log output

N/A
JanDeDobbeleer commented 2 years ago

@mattcargile what does Test-Path Variable:/PSDebugContext say? Maybe we should try $PSDebugContext -ne $null?

mattcargile commented 2 years ago

Test-Path Variable:/PSDebugContext returns $true.

And yeah maybe $global:PSDebugContext or maybe function global:Test-PSDebugContext { return Test-Path Variable:/Global:PSDebugContext }. I'm not exactly sure on the second example.

mattcargile commented 2 years ago

I was playing around with function global:Test-PSDebugContext { return Test-Path Variable:/global:PSDebugContext } and couldn't get it to work. $global:PSDebugContext doesn't return anything either.

mattcargile commented 2 years ago

This sample worked.

ni t.psm1 -force -Value @'
function global:Test-PSDebugContext { Test-Path Variable:/PSDebugContext }
function t {
$x = 'hello world'
write-output $x
}
'@; gbp|rbp; sbp t.psm1 -Line 3; ipmo .\t.psm1 -Force; t

So I added function global:Test-PSDebugContext { return Test-Path Variable:/PSDebugContext } inside the New-Module declaration and it appears to have worked at least for modules.

I was currently attempting to define the function in both outside the New-Module scope and within.

EDIT 1: I still couldn't ever get it to work with all global and module scopes. My next attempt would involved moving the prompt function out of the New-Module.

lewis-yeung commented 2 years ago

@mattcargile

So I added function global:Test-PSDebugContext { return Test-Path Variable:/PSDebugContext } inside the New-Module declaration and it appears to have worked at least for modules.

Once again, PowerShell has showed us how magical and tricky it can be. 😅 Possibly related: about Scopes - PowerShell | Microsoft Docs.

My next attempt would involved moving the prompt function out of the New-Module.

I have tested this and it failed to work because of the scope constraints. Just write a simple prompt function as below:

function prompt { $null -ne $PSDebugContext }
# function prompt { Test-Path Variable:/PSDebugContext } // same effect as above

Frustratingly, it always shows False when debugging in a module. 😭

~I'm trying to find a better solution to handle both. Not sure if there is such one.~ Now I doubt whether there is a trick to get a variable belonging to the scope of the module being debugged, from another scope.

mattcargile commented 2 years ago

😭 It's like every module would have to expose there own PSDebugContext for the prompt to latch on to. Debugging a module with the default prompt will work though and add the [DBG].

I guess it is an Issue to PowerShell repo?

lewis-yeung commented 2 years ago

Debugging a module with the default prompt will work though and add the [DBG].

In a context of debugging a module (in PowerShell v7.2.5), I ran $Function:prompt to see what the default prompt function does, the first and the only effective line is

"[DBG]: PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) ";

While outside the module, the effective line is

"PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) ";

The [DBG]: is hard coded here. No clue yet. 😶

mattcargile commented 2 years ago

I'm thinking now maybe using Get-PSCallStack instead of $PSDebugContext. I'm able to get the below to actually return information in the debugging context. Not sure if this is reasonable though.

function prompt { (get-pscallStack).Location[0] }
lewis-yeung commented 2 years ago
function prompt { (get-pscallStack).Location[0] }

Nice thought. However this shows the script/module name, which cannot tell if it's in a debug context.

mattcargile commented 2 years ago
function prompt { (get-pscallStack).Location[0] }

Nice thought. However this shows the script/module name, which cannot tell if it's in a debug context.

So the idea is that normally when you run it, it has <No file> in the context of the prompt function while in debugging context it shows a file. Seems like a useable workaround.

JanDeDobbeleer commented 2 years ago

@mattcargile I'll try that. See if it works.

JanDeDobbeleer commented 2 years ago

@mattcargile solved:

image
github-actions[bot] commented 8 months ago

This issue has been automatically locked since there has not been any recent activity (i.e. last half year) after it was closed. It helps our maintainers focus on the active issues. If you have found a problem that seems similar, please open a discussion first, complete the body with all the details necessary to reproduce, and mention this issue as reference.