-
Notifications
You must be signed in to change notification settings - Fork 237
Add New-EditorFile #622
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add New-EditorFile #622
Changes from 2 commits
1a31c75
9cd7901
ddf3bb0
484c6c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,13 +77,91 @@ function Unregister-EditorCommand { | |
} | ||
} | ||
|
||
<# | ||
.SYNOPSIS | ||
Creates new files and opens them in your editor window | ||
.DESCRIPTION | ||
Creates new files and opens them in your editor window | ||
.EXAMPLE | ||
PS > New-EditorFile './foo.ps1' | ||
Creates and opens a new foo.ps1 in your editor | ||
.EXAMPLE | ||
PS > Get-Process | New-EditorFile proc.txt | ||
Creates and opens a new foo.ps1 in your editor with the contents of the call to Get-Process | ||
.EXAMPLE | ||
PS > Get-Process | New-EditorFile proc.txt -Force | ||
Creates and opens a new foo.ps1 in your editor with the contents of the call to Get-Process. Overwrites the file if it already exists | ||
.INPUTS | ||
Path | ||
an array of files you want to open in your editor | ||
Value | ||
The content you want in the new files | ||
Force | ||
Overwrites a file if it exists | ||
#> | ||
function New-EditorFile { | ||
[CmdletBinding()] | ||
param( | ||
[Parameter(Mandatory=$true)] | ||
[String[]] | ||
$Path, | ||
|
||
[Parameter(ValueFromPipeline=$true)] | ||
$Value, | ||
|
||
[Parameter()] | ||
[switch] | ||
$Force | ||
) | ||
|
||
begin { | ||
$container = @() | ||
} | ||
|
||
process { | ||
$container += $Value | ||
} | ||
|
||
end { | ||
foreach ($fileName in $Path) | ||
{ | ||
if (-not (Test-Path $fileName) -or $Force) { | ||
$container > $fileName | ||
$psEditor.Workspace.OpenFile($fileName) | ||
} else { | ||
$PSCmdlet.WriteError( ( | ||
New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList @( | ||
[System.Exception]'File already exists.' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we model this error record after New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList @(
[System.IO.IOException]"The file '$fileName' already exists.",
'NewEditorFileIOError',
[System.Management.Automation.ErrorCategory]::WriteError,
$fileName) |
||
$Null | ||
[System.Management.Automation.ErrorCategory]::ResourceExists | ||
$fileName ) ) ) | ||
} | ||
} | ||
} | ||
} | ||
|
||
function Open-EditorFile { | ||
param([Parameter(Mandatory=$true)]$FilePaths) | ||
[CmdletBinding()] | ||
param( | ||
[Parameter(Mandatory=$true, ValueFromPipeline=$true)] | ||
[ValidateNotNullOrEmpty()] | ||
$Path | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As long as this parameter supports this scenario There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So @rkeithhill ... as it turns out, this will proceed to open the file temporarily (with the italicized file name)... so what ends up happening is, it opens the file temporarily and then the next file opens and replaces the file temporarily. I'm not sure how to durably open files - if that's possible. I'll have to dig around. @daviwil any thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, yes. That's why I double-click the editor window tab. That converts it from a temp (resuable) window to a permanent one. Not sure how you do that programmatically though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exactly. Maybe if @SeeminglyScience or @daviwil know? Otherwise, can I convince you to call this out of scope 😄 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That would be my preference. Later we could update the openFile() method to take an optional "preview" Boolean parameter. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
What if I already have this working? Is it worth adding it now or saving it for when someone actually asks for that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll just push and you can judge whether we should keep it in or not There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like to have that option, so yeah, if it's working - go for it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @rkeithhill pushed that. Here's the vscode-powershell PR as well: |
||
) | ||
|
||
begin { | ||
$Paths = @() | ||
} | ||
|
||
Get-ChildItem $FilePaths -File | ForEach-Object { | ||
$psEditor.Workspace.OpenFile($_.FullName) | ||
process { | ||
$Paths += $Path | ||
} | ||
|
||
end { | ||
Get-ChildItem $Paths -File | ForEach-Object { | ||
$psEditor.Workspace.OpenFile($_.FullName) | ||
} | ||
} | ||
} | ||
Set-Alias psedit Open-EditorFile -Scope Global | ||
|
||
Export-ModuleMember -Function Open-EditorFile | ||
Export-ModuleMember -Function Open-EditorFile,New-EditorFile |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,55 +36,161 @@ public class RemoteFileManager | |
|
||
private const string RemoteSessionOpenFile = "PSESRemoteSessionOpenFile"; | ||
|
||
private const string PSEditFunctionScript = @" | ||
param ( | ||
[Parameter(Mandatory=$true)] [String[]] $FileNames | ||
) | ||
private const string PSEditModule = @"<# | ||
.SYNOPSIS | ||
Opens the specified files in your editor window | ||
.DESCRIPTION | ||
Opens the specified files in your editor window | ||
.EXAMPLE | ||
PS > Open-EditorFile './foo.ps1' | ||
Opens foo.ps1 in your editor | ||
.EXAMPLE | ||
PS > gci ./myDir | Open-EditorFile | ||
Opens everything in 'myDir' in your editor | ||
.INPUTS | ||
Path | ||
an array of files you want to open in your editor | ||
#> | ||
function Open-EditorFile { | ||
param ( | ||
[Parameter(Mandatory=$true, ValueFromPipeline=$true)] | ||
[String[]] | ||
$Path | ||
) | ||
|
||
begin { | ||
$Paths = @() | ||
} | ||
|
||
foreach ($fileName in $FileNames) | ||
{ | ||
dir $fileName | where { ! $_.PSIsContainer } | foreach { | ||
$filePathName = $_.FullName | ||
process { | ||
$Paths += $Path | ||
} | ||
|
||
# Get file contents | ||
$params = @{ Path=$filePathName; Raw=$true } | ||
if ($PSVersionTable.PSEdition -eq 'Core') | ||
end { | ||
foreach ($fileName in $Paths) | ||
{ | ||
$params['AsByteStream']=$true | ||
dir $fileName | where { ! $_.PSIsContainer } | foreach { | ||
$filePathName = $_.FullName | ||
|
||
# Get file contents | ||
$params = @{ Path=$filePathName; Raw=$true } | ||
if ($PSVersionTable.PSEdition -eq 'Core') | ||
{ | ||
$params['AsByteStream']=$true | ||
} | ||
else | ||
{ | ||
$params['Encoding']='Byte' | ||
} | ||
|
||
$contentBytes = Get-Content @params | ||
|
||
# Notify client for file open. | ||
New-Event -SourceIdentifier PSESRemoteSessionOpenFile -EventArguments @($filePathName, $contentBytes) > $null | ||
} | ||
} | ||
else | ||
} | ||
} | ||
|
||
<# | ||
.SYNOPSIS | ||
Creates new files and opens them in your editor window | ||
.DESCRIPTION | ||
Creates new files and opens them in your editor window | ||
.EXAMPLE | ||
PS > New-EditorFile './foo.ps1' | ||
Creates and opens a new foo.ps1 in your editor | ||
.EXAMPLE | ||
PS > Get-Process | New-EditorFile proc.txt | ||
Creates and opens a new foo.ps1 in your editor with the contents of the call to Get-Process | ||
.EXAMPLE | ||
PS > Get-Process | New-EditorFile proc.txt -Force | ||
Creates and opens a new foo.ps1 in your editor with the contents of the call to Get-Process. Overwrites the file if it already exists | ||
.INPUTS | ||
Path | ||
an array of files you want to open in your editor | ||
Value | ||
The content you want in the new files | ||
Force | ||
Overwrites a file if it exists | ||
#> | ||
function New-EditorFile { | ||
[CmdletBinding()] | ||
param ( | ||
[Parameter(Mandatory=$true)] | ||
[String[]] | ||
$Path, | ||
|
||
[Parameter(ValueFromPipeline=$true)] | ||
$Value, | ||
|
||
[Parameter()] | ||
[switch] | ||
$Force | ||
) | ||
|
||
begin { | ||
$container = @() | ||
} | ||
|
||
process { | ||
$container += $Value | ||
} | ||
|
||
end { | ||
foreach ($fileName in $Path) | ||
{ | ||
$params['Encoding']='Byte' | ||
} | ||
if (-not (Test-Path $fileName) -or $Force) { | ||
$container > $fileName | ||
|
||
$contentBytes = Get-Content @params | ||
# Get file contents | ||
$params = @{ Path=$fileName; Raw=$true } | ||
if ($PSVersionTable.PSEdition -eq 'Core') | ||
{ | ||
$params['AsByteStream']=$true | ||
} | ||
else | ||
{ | ||
$params['Encoding']='Byte' | ||
} | ||
|
||
# Notify client for file open. | ||
New-Event -SourceIdentifier PSESRemoteSessionOpenFile -EventArguments @($filePathName, $contentBytes) > $null | ||
$contentBytes = Get-Content @params | ||
|
||
# Notify client for file open. | ||
New-Event -SourceIdentifier PSESRemoteSessionOpenFile -EventArguments @($fileName, $contentBytes) > $null | ||
} else { | ||
$PSCmdlet.WriteError( ( | ||
New-Object -TypeName System.Management.Automation.ErrorRecord -ArgumentList @( | ||
[System.Exception]'File already exists.' | ||
$Null | ||
[System.Management.Automation.ErrorCategory]::ResourceExists | ||
$fileName ) ) ) | ||
} | ||
} | ||
} | ||
} | ||
|
||
Set-Alias psedit Open-EditorFile -Scope Global | ||
Export-ModuleMember -Function Open-EditorFile, New-EditorFile | ||
"; | ||
|
||
// This script is templated so that the '-Forward' parameter can be added | ||
// to the script when in non-local sessions | ||
private const string CreatePSEditFunctionScript = @" | ||
param ( | ||
[string] $PSEditFunction | ||
[string] $PSEditModule | ||
) | ||
|
||
Register-EngineEvent -SourceIdentifier PSESRemoteSessionOpenFile -Forward | ||
|
||
if ((Test-Path -Path 'function:\global:Open-EditorFile') -eq $false) | ||
{{ | ||
Set-Item -Path 'function:\global:Open-EditorFile' -Value $PSEditFunction | ||
Set-Alias psedit Open-EditorFile -Scope Global | ||
}} | ||
$psedit = New-Module -ScriptBlock ([Scriptblock]::Create($PSEditModule)) -Name PSEdit | ||
$psedit.ExportedFunctions.Keys | ForEach-Object { | ||
Set-Item -Path function:\global:$_ -Value $asdf.ExportedFunctions[$_].Definition -Force | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we're going the module route, can we pipe this into There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @SeeminglyScience I tried There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tylerl0706 try |
||
"; | ||
|
||
private const string RemovePSEditFunctionScript = @" | ||
if (Test-Path -Path 'function:\global:Open-EditorFile') | ||
{ | ||
Remove-Item -Path 'function:\global:Open-EditorFile' -Force | ||
Get-Command | Where-Object {$_.Source -eq 'PSEdit'} | ForEach-Object { | ||
Remove-Item -Path function:\global:$($_.Name) -Force | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, |
||
} | ||
|
||
if (Test-Path -Path 'alias:\psedit') | ||
|
@@ -488,17 +594,10 @@ private void RegisterPSEditFunction(RunspaceDetails runspaceDetails) | |
{ | ||
runspaceDetails.Runspace.Events.ReceivedEvents.PSEventReceived += HandlePSEventReceived; | ||
|
||
var createScript = | ||
string.Format( | ||
CreatePSEditFunctionScript, | ||
(runspaceDetails.Location == RunspaceLocation.Local && | ||
runspaceDetails.Context == RunspaceContext.Original) | ||
? string.Empty : "-Forward"); | ||
|
||
PSCommand createCommand = new PSCommand(); | ||
createCommand | ||
.AddScript(createScript) | ||
.AddParameter("PSEditFunction", PSEditFunctionScript); | ||
.AddScript(CreatePSEditFunctionScript) | ||
.AddParameter("PSEditModule", PSEditModule); | ||
|
||
if (runspaceDetails.Context == RunspaceContext.DebuggedRunspace) | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd really like to see this edit the file through
$psEditor
instead of directly.