ShaunLawrie / PwshSpectreConsole

👻 PwshSpectreConsole is a PowerShell wrapper for the awesome Spectre.Console library
https://pwshspectreconsole.com/
MIT License
92 stars 6 forks source link

This wrapper around Spectre is really awesome. But I'm having trouble creating my own progress bar for a set of tasks. #7

Closed futuremotiondev closed 9 months ago

futuremotiondev commented 10 months ago

I have a script that installs several Python packages into a dynamically created VENV (Virtual Environment). Here's some simple example code:

param (
    [Parameter(Mandatory, Position = 0)]
    [String]
    $Folder,

    [Parameter(Mandatory=$false)]
    [String]
    $Version='3.10'
)

Set-Location -LiteralPath $Folder

$i = Get-ChildItem -Path $Folder
if ($i.Count -ne 0) {
    throw [System.Exception] "The target folder is not empty."
    exit
}

py -$Version -m venv $Folder | Out-Null

& "Scripts/Activate.ps1" | Out-Null

Set-SpectreColors -AccentColor White

Invoke-SpectreCommandWithProgress -ScriptBlock {
    param (
        $Context
    )

    $task1 = $Context.AddTask("Installing FontTools Environment Dependencies")
    python -m pip install brotli | Out-Null
    $task1.Increment(6.6)
    python -m pip install PyQt5 | Out-Null
    $task1.Increment(6.6)
    python -m pip install reportlab | Out-Null
    $task1.Increment(6.6)
    python -m pip install foundrytools-cli | Out-Null
    $task1.Increment(6.6)
    python -m pip install freetype-py | Out-Null
    $task1.Increment(6.6)
    python -m pip install uharfbuzz | Out-Null
    $task1.Increment(6.6)
    python -m pip install opentypesvg | Out-Null
    $task1.Increment(6.6)
    python -m pip install fonttools[ufo,lxml,woff,unicode,interpolatable,plot,pathops] | Out-Null
    $task1.Increment(6.6)
    python -m pip install python-fontbro | Out-Null
    $task1.Increment(6.6)
    python -m pip install filetype | Out-Null
    $task1.Increment(6.6)
    python -m pip install PyFontConverter | Out-Null
    $task1.Increment(6.6)
    python -m pip install fontmeta | Out-Null
    $task1.Increment(6.6)
    python -m pip install font-rename | Out-Null
    $task1.Increment(6.6)
    python -m pip install font-line | Out-Null
    $task1.Increment(6.6)
    python -m pip install font-v | Out-Null
    $task1.Increment(6.6)
    python -m pip install fleep | Out-Null

}

But this is what happens when I run the script:

https://github.com/ShaunLawrie/PwshSpectreConsole/assets/33441569/d34fb5a4-fc62-4eb9-a8c3-7c538b7d1176

Everything is installing correctly, but the progress bar is obviously not working at all.

Am I missing something?

I would really love to integrate this module in my scripts so any help would be greatly appreciated!

ShaunLawrie commented 10 months ago

Does Start-SpectreDemo work in your normal terminal? I'm wondering if the way it's being launched from the context menu is setting up the terminal environment with something incompatible.

Could you please run the following to see what spectre console thinks the terminal is capable of?

[Spectre.Console.AnsiConsole]::Profile
[Spectre.Console.AnsiConsole]::Profile.Capabilities

It should look something like this:

image

If you get Unable to find type [Spectre.Console.AnsiConsole] try Import-Module PwshSpectreConsole first.

ShaunLawrie commented 10 months ago

If your normal terminal looks fine try adding these lines to your script and run it from the context menu to see if it differs:

# ... the rest of your script
& "Scripts/Activate.ps1" | Out-Null

Set-SpectreColors -AccentColor White

+# Dump some debug output
+[Spectre.Console.AnsiConsole]::Profile | Out-Host
+[Spectre.Console.AnsiConsole]::Profile.Capabilities | Out-Host
+Read-Host -Prompt "Pausing so it's easy to take a screenshot"

Invoke-SpectreCommandWithProgress -ScriptBlock {
# ... the rest of your script
futuremotiondev commented 10 months ago

Does Start-SpectreDemo work in your normal terminal? I'm wondering if the way it's being launched from the context menu is setting up the terminal environment with something incompatible.

Yep, Start-SpectreDemo does work. It looks great too.

Could you please run the following to see what spectre console thinks the terminal is capable of?

[Spectre.Console.AnsiConsole]::Profile
[Spectre.Console.AnsiConsole]::Profile.Capabilities

[Spectre.Console.AnsiConsole]::Profile

11-03 13:12:50 D:\Dev\Powershell> [Spectre.Console.AnsiConsole]::Profile

Enrichers    : {Default}
Out          : Spectre.Console.AnsiConsoleOutput
Encoding     : System.Text.UTF8Encoding
Width        : 98
Height       : 23
Capabilities : Spectre.Console.Capabilities 

[Spectre.Console.AnsiConsole]::Profile.Capabilities

ColorSystem     : TrueColor
Ansi            : True     
Links           : True     
Legacy          : False    
IsTerminal      : False    
Interactive     : True     
Unicode         : True     
AlternateBuffer : True

Code_XSIGymDmSv

It should look something like this: image

If you get Unable to find type [Spectre.Console.AnsiConsole] try Import-Module PwshSpectreConsole first.

futuremotiondev commented 10 months ago

If your normal terminal looks fine try adding these lines to your script and run it from the context menu to see if it differs:

# ... the rest of your script
& "Scripts/Activate.ps1" | Out-Null

Set-SpectreColors -AccentColor White

+# Dump some debug output
+[Spectre.Console.AnsiConsole]::Profile | Out-Host
+[Spectre.Console.AnsiConsole]::Profile.Capabilities | Out-Host
+Read-Host -Prompt "Pausing so it's easy to take a screenshot"

Invoke-SpectreCommandWithProgress -ScriptBlock {
# ... the rest of your script

I'll give it a shot now. Thanks for the help.

futuremotiondev commented 10 months ago

Just tried it now, and got the same glitched out progress bar.

Code:

param (
    [Parameter(Mandatory, Position = 0)]
    [String]
    $Folder,

    [Parameter(Mandatory=$false)]
    [String]
    $Version='3.10'
)

Set-Location -LiteralPath $Folder

$i = Get-ChildItem -Path $Folder
if ($i.Count -ne 0) {
    throw [System.Exception] "The target folder is not empty."
    exit
}

py -$Version -m venv $Folder | Out-Null

& "Scripts/Activate.ps1" | Out-Null

Set-SpectreColors -AccentColor White

# Dump some debug output
[Spectre.Console.AnsiConsole]::Profile | Out-Host
[Spectre.Console.AnsiConsole]::Profile.Capabilities | Out-Host
Read-Host -Prompt "Pausing so it's easy to take a screenshot"

Invoke-SpectreCommandWithProgress -ScriptBlock {
    param (
        $Context
    )

    $task1 = $Context.AddTask("Installing FontTools Environment Dependencies")

    python.exe -m pip install --upgrade pip
    $task1.Increment(6.6)
    python -m pip install brotli
    $task1.Increment(6.6)
    python -m pip install PyQt5
    $task1.Increment(6.6)
    python -m pip install reportlab
    $task1.Increment(6.6)
    python -m pip install foundrytools-cli
    $task1.Increment(6.6)
    python -m pip install freetype-py
    $task1.Increment(6.6)
    python -m pip install uharfbuzz
    $task1.Increment(6.6)
    python -m pip install opentypesvg
    $task1.Increment(6.6)
    python -m pip install fonttools[ufo,lxml,woff,unicode,interpolatable,plot,pathops]
    $task1.Increment(6.6)
    python -m pip install python-fontbro
    $task1.Increment(6.6)
    python -m pip install filetype
    $task1.Increment(6.6)
    python -m pip install PyFontConverter
    $task1.Increment(6.6)
    python -m pip install fontmeta
    $task1.Increment(6.6)
    python -m pip install font-rename
    $task1.Increment(6.6)
    python -m pip install font-line
    $task1.Increment(6.6)
    python -m pip install font-v
    $task1.Increment(6.6)
    python -m pip install fleep
    $task1.Increment(6.6)
}

Screenshot of debug info:

pwsh_OPdtxIfTF9

futuremotiondev commented 10 months ago

Ok, some progress. I swapped out the python -m pip install commands and replaced them with Start-Sleep -Seconds 1 and the progress bar works as expected. I think the problem lies in the python calls (python -m pip install opentypesvg) etc.

pwsh_Voh7NxagrZ

I'm hoping this can be fixed, not sure what the remedy would be though.

trackd commented 10 months ago

does the same thing happen if you try this?


function Start-PythonInstallwProgress {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string[]]$PackageName
    )
    $inc = 100 / $PackageName.Count
    Invoke-SpectreCommandWithProgress -ScriptBlock {
        param (
            $Context
        )
        $task1 = $Context.AddTask("Installing FontTools Environment Dependencies")
        foreach ($item in $PackageName) {
            $params = @(
                '-m'
                'pip' 
                'install'
                "$item"
            )
            $null = & python $params
            $task1.Increment($inc)
        }
    }
}

$MyPackages = 'brotli','PyQt5','reportlab','foundrytools-cli','freetype-py','uharfbuzz','opentypesvg','fonttools[ufo,lxml,woff,unicode,interpolatable,plot,pathops]','python-fontbro','filetype','PyFontConverter','fontmeta','font-rename','font-line','font-v','fleep'

Start-PythonInstallwProgress -PackageName $MyPackages 
ShaunLawrie commented 10 months ago

@trackd's suggestion should work but you'll need to redirect stderr to stdout at the end of the & python command. You can try:

$null = & python $params 2>&1

2>&1 means to send the second stream of data to the first stream. The first stream is success messages and the second stream is errors, because linux only had two streams it's common for CLI tools to use the error stream for debug data or warnings. https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_redirection?view=powershell-7.3#example-3-send-success-warning-and-error-streams-to-a-file

This resolved it for me, pip was outputting debug info which was messing up the terminal output.

I'll update the docs for working with native commands like python assuming this fix works for you thanks.

futuremotiondev commented 10 months ago

Thanks for all the suggestions. Unfortunately it's still happening despite implementing your code. I tried:

  1. Null assignment and stream redirection ($null = & python -m pip install Pillow 2>&1)
  2. Disabling the prompt modification that occurs when activating a virtual environment:
    $Env:VIRTUAL_ENV_DISABLE_PROMPT = $true
    & "Scripts/Activate.ps1" -Prompt $null | Out-Null
  3. Redirecting all streams to a text file: $null = & python $params 3>&1 2>&1 > C:\Temp\redirection.log

First variation: https://gist.github.com/fmotion1/d1ef0983fd7c074190af835bde68bd79 https://gist.github.com/fmotion1/c8eafeb4d11d8a1ed30e86bef18f604b

There may be a clue hidden in the output of my terminal though.

pwsh_dFFllts4FT

[38;5;15m is a gray. [38;5;11m is a yellow.

These could be just the ansi colors from the progress bar, or something else is injecting them. To be sure, I disabled everything in my profile that has to do with prompt modification, like posh-git. Still no dice.

I then completely nuked my profile temporarily and only included Import-Module PwshSpectreConsole. STILL not working.

So I'm completely at a loss as to what's going on.

EDIT!

It works in Windows Terminal!

WindowsTerminal_RjbVJY7Voh

While not ideal for me (I really like using the regular terminals since they are a bit snappier) it's good to know its possible for this to work. I just need to figure out what's going on with the normal terminal. Not sure where to go from here, but will keep investigating.

futuremotiondev commented 10 months ago

Just dropping this link here. It's interesting https://devblogs.microsoft.com/commandline/new-experimental-console-features/

The first significant version of the Console’s new VT engine shipped in Windows 10 1609 (Anniversary Update), and was quickly followed in the 1703 (Creators Update) release which contained much richer support for a wider range of VT sequences. This allowed Console to render many of even the most complex text-based UI’s generated by tools like Tmux (a great tutorial here for the uninitiated) and Midnight Commander … or even vim, bash, Midnight Commander and htop running simultaneously in separate Tmux panes:

Unfortunately despite these accomplishments, I can't render a progress bar. :(

ShaunLawrie commented 10 months ago

Hi @fmotion1 sorry this has been a pain. I’m really interested to understand what’s happening when it’s run in the older terminal so I can fix or document it. If you want to jump on a call to see if we can sort it out flick me an invite through this https://calendly.com/shaunlawrie/30min

futuremotiondev commented 10 months ago

Hi @fmotion1 sorry this has been a pain. I’m really interested to understand what’s happening when it’s run in the older terminal so I can fix or document it.

I'm really interested too. Are you able to reproduce what I'm seeing in the regular console as well (not Windows Terminal)?

If you want to jump on a call to see if we can sort it out flick me an invite through this https://calendly.com/shaunlawrie/30min

This is going to sound crazy, but I don't own a cellphone. Nor do I have a microphone. I wouldn't mind doing a chat on Discord or Skype or whatever though.

Let me know, Jay

ShaunLawrie commented 10 months ago

This is going to sound crazy, but I don't own a cellphone. Nor do I have a microphone. I wouldn't mind doing a chat on Discord or Skype or whatever though.

Let me know, Jay

No worries, I'm @shaunlawrie on discord. If you send an invite through the calendly link it will remind me when to jump in. I think we're in quite different timezones so it will help you pick a time I'm not asleep 😆

I did reproduce a similar issue in he regular console but I don't know how similar the setup was because I got it to go away with redirects.