feat: powershell and nushell support
This PR adds support for Powershell and Nushell of piper.
I haven't worked with Lua before, so there may be some bugs, but please consider expanding shell support.
Thank you!
Thank you for your patch!
Is it possible to pass the file path as an argument to PowerShell or Nushell, just like with sh, and then use their respective $args[0] or $env.NU_ARGV[0] instead of replacing all of them with $1? Otherwise, there will be a lot of edge cases to consider, which would require a dedicated parser, which is pretty complicated - for example, the parser for cmd.exe is over 100 lines so that to cover all the cases, https://github.com/sxyazi/yazi/blob/7deeaa4356a0fa1eecd7264998a298866f31cb0a/yazi-scheduler/src/process/shell.rs#L77-L181
Also, based on my tests, PowerShell has poor startup speed and is much slower than cmd.exe, which is especially noticeable in scenarios like previewing, which require low latency. I'm not sure if it makes sense to support it here, maybe we can start by adding basic cmd.exe support first? I haven't used Nushell myself, so it would be nice to see some benchmark data.
My initial code was quite a mess 😅.
I've refactored it to pass the path via a pipeline instead of replacing $1. Unfortunately, I wasn't able to implement this for cmd.exe. (I don't have much experience with programming and have been relying heavily on Gemini and ChatGPT.)
Here are some simple performance test from my PC (Win11, Ryzen 5 9600X). Please let me know if there's a more appropriate benchmarking method.
local start_time = ya.time()
local child, err = Command(cmd)
:arg(args)
:env("w", job.area.w)
:env("h", job.area.h)
:stdout(Command.PIPED)
:stderr(Command.PIPED)
:spawn()
local elapsed_time = (ya.time() - start_time) * 1000
ya.notify({ title = "elapsed time", content = string.format("%.1f ms", elapsed_time), timeout = 1 })})
results:
| shell (yazi) | require("piper"): setup(shell = ) |
plugin.prepend_ previewers.run |
try | elapsed time (ms) |
|---|---|---|---|---|
| pwsh (powershell 7.5.3) | pwsh | piper -- echo $_ |
1 | 96.4 |
| pwsh (powershell 7.5.3) | pwsh | piper -- echo $_ |
2 | 52.4 |
| pwsh (powershell 7.5.3) | pwsh | piper -- echo $_ |
3 | 50.3 |
| pwsh (powershell 7.5.3) | pwsh | piper -- echo $_ |
4 | 50.4 |
| pwsh (powershell 7.5.3) | pwsh | piper -- echo $_ |
5 | 50.7 |
| powershell (powershell 5) | powershell | piper -- echo $_ |
1 | 5.0 |
| powershell (powershell 5) | powershell | piper -- echo $_ |
2 | 5.5 |
| powershell (powershell 5) | powershell | piper -- echo $_ |
3 | 6.0 |
| powershell (powershell 5) | powershell | piper -- echo $_ |
4 | 5.6 |
| powershell (powershell 5) | powershell | piper -- echo $_ |
5 | 5.2 |
| nushell | nushell | piper -- echo $in |
1 | 2.8 |
| nushell | nushell | piper -- echo $in |
2 | 3.4 |
| nushell | nushell | piper -- echo $in |
3 | 2.8 |
| nushell | nushell | piper -- echo $in |
4 | 2.8 |
| nushell | nushell | piper -- echo $in |
5 | 3.0 |
| git bash | sh | piper -- echo %1 |
1 | 10.6 |
| git bash | sh | piper -- echo %1 |
2 | 2.6 |
| git bash | sh | piper -- echo %1 |
3 | 3.1 |
| git bash | sh | piper -- echo %1 |
4 | 3.0 |
| git bash | sh | piper -- echo %1 |
5 | 2.5 |
| nushell | pwsh | piper -- echo $_ |
1 | 98.8 |
| nushell | pwsh | piper -- echo $_ |
2 | 52.2 |
| nushell | pwsh | piper -- echo $_ |
3 | 52.4 |
| nushell | pwsh | piper -- echo $_ |
4 | 51.0 |
| nushell | pwsh | piper -- echo $_ |
5 | 50.1 |
| pwsh (powershell 7.5.3) | nushell | piper -- echo $in |
1 | 2.7 |
| pwsh (powershell 7.5.3) | nushell | piper -- echo $in |
2 | 3.0 |
| pwsh (powershell 7.5.3) | nushell | piper -- echo $in |
3 | 2.6 |
| pwsh (powershell 7.5.3) | nushell | piper -- echo $in |
4 | 2.5 |
| pwsh (powershell 7.5.3) | nushell | piper -- echo $in |
5 | 3.0 |