Skip to content

Commit

Permalink
Merge pull request #892 from ctaggart/tab
Browse files Browse the repository at this point in the history
add tab completion for installed packages
  • Loading branch information
forki committed Jun 22, 2015
2 parents b6fb6fb + 98b8828 commit bc7e6a8
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 50 deletions.
13 changes: 13 additions & 0 deletions src/Paket.PowerShell/ArgumentTabCompletion.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,24 @@ $findPackageVersions = {
}
}

$showInstalledPackages = {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
Paket-ShowInstalledPackages | % {
$name = $_.Name
createCompletionResult $name $name $name | write
}
}

# create and add $global:options to the list of completers
# http://www.powertheshell.com/dynamicargumentcompletion/
if (-not $global:options) { $global:options = @{CustomArgumentCompleters = @{};NativeArgumentCompleters = @{}}}

$global:options['CustomArgumentCompleters']['Paket-Add:NuGet'] = $findPackages
$global:options['CustomArgumentCompleters']['Paket-Add:Version'] = $findPackageVersions
$global:options['CustomArgumentCompleters']['Paket-Update:NuGet'] = $showInstalledPackages
$global:options['CustomArgumentCompleters']['Paket-Update:Version'] = $findPackageVersions
$global:options['CustomArgumentCompleters']['Paket-Remove:NuGet'] = $showInstalledPackages
$global:options['CustomArgumentCompleters']['Paket-FindPackageVersions:Name'] = $findPackages
$global:options['CustomArgumentCompleters']['Paket-FindRefs:NuGet'] = $showInstalledPackages

$function:tabexpansion2 = $function:tabexpansion2 -replace 'End\r\n{','End { if ($null -ne $options) { $options += $global:options} else {$options = $global:options}'
8 changes: 8 additions & 0 deletions src/Paket.PowerShell/EventSink.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,18 @@ type EventSink<'T>() =
let queue = new BlockingCollection<_>()
let subscriptions = List()

member __.Add state callback =
queue.Add((callback, state))

member __.Fill callback (source:IObservable<'T>) =
source |> Observable.subscribe (fun state -> queue.Add((callback, state)))
|> subscriptions.Add

/// converts the object to be compatible with the sink
member __.ConvertAndFill (converter:'S -> 'T) callback (source:IObservable<'S>) =
source |> Observable.subscribe (fun state -> queue.Add((callback, converter state)))
|> subscriptions.Add

member __.Drain() =
for callback, state in queue.GetConsumingEnumerable() do
callback state
Expand Down
98 changes: 64 additions & 34 deletions src/Paket.PowerShell/PowerShell.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,52 @@ open Paket.Commands
open Nessos.UnionArgParser
open System

// types exposed publicly by sending to output
type Package = { Name: string; Version: string }

[<AutoOpen>]
module PaketPs =

let processWithLogging (cmdlet:PSCmdlet) computation =
type PaketOutput =
| Trace of Logging.Trace
| Package of Package

/// runs the async computation and then a continuation on the result
let runWithLogging (cmdlet: PSCmdlet) (computation: Async<'T>) (cont: EventSink<PaketOutput> -> 'T -> unit) =
Environment.CurrentDirectory <- cmdlet.SessionState.Path.CurrentFileSystemLocation.Path
Logging.verbose <- cmdlet.Verbose
use sink = new EventSink<Logging.Trace>()

Logging.event.Publish |> sink.Fill (fun trace ->
match trace.Level with
| TraceLevel.Error -> cmdlet.WriteWarning trace.Text
| TraceLevel.Warning -> cmdlet.WriteWarning trace.Text
| TraceLevel.Verbose -> cmdlet.WriteVerbose trace.Text
| _ -> cmdlet.WriteObject trace.Text )

async {
try
do! Async.SwitchToNewThread()
// prevent an exception from killing the thread, PS thread, and PS exe
use sink = new EventSink<PaketOutput>()

Logging.event.Publish |> sink.ConvertAndFill PaketOutput.Trace (fun output ->
match output with
| Trace trace ->
match trace.Level with
| TraceLevel.Error -> cmdlet.WriteWarning trace.Text
| TraceLevel.Warning -> cmdlet.WriteWarning trace.Text
| TraceLevel.Verbose -> cmdlet.WriteVerbose trace.Text
| _ -> cmdlet.WriteObject trace.Text
| _ -> () )

let run =
async {
try
do! computation
with
| ex -> Logging.traceWarn ex.Message
finally
sink.StopFill()
} |> Async.Start
do! Async.SwitchToNewThread()
// prevent an exception from killing the thread, PS thread, and PS exe
try
let! v = computation
cont sink v
with
| ex -> Logging.traceWarn ex.Message
finally
sink.StopFill()
} |> Async.Start

sink.Drain()

/// runs the async computation, but no continuation is needed
let processWithLogging (cmdlet:PSCmdlet) (computation:Async<unit>) =
runWithLogging cmdlet computation (fun _ _ -> ())

[<Cmdlet("Paket", "Add")>]
type Add() =
inherit PSCmdlet()
Expand Down Expand Up @@ -69,7 +86,7 @@ type Add() =
]
|> parser.CreateParseResultsOfList
|> Program.add
} |> processWithLogging x
} |> processWithLogging x

[<Cmdlet("Paket", "AutoRestore")>]
type AutoRestoreCmdlet() =
Expand Down Expand Up @@ -363,19 +380,32 @@ type ShowInstalledPackagesCmdlet() =
[<Parameter>] member val Silent = SwitchParameter() with get, set

override x.ProcessRecord() =
async {
let parser = UnionArgParser.Create<ShowInstalledPackagesArgs>()
[
if x.All.IsPresent then
yield ShowInstalledPackagesArgs.All
if String.IsNullOrEmpty x.Project = false then
yield ShowInstalledPackagesArgs.Project x.Project
if x.Silent.IsPresent then
yield ShowInstalledPackagesArgs.Silent
]
|> parser.CreateParseResultsOfList
|> Program.showInstalledPackages
} |> processWithLogging x
let computation =
async {
let packages =
let parser = UnionArgParser.Create<ShowInstalledPackagesArgs>()
[
if x.All.IsPresent then
yield ShowInstalledPackagesArgs.All
if String.IsNullOrEmpty x.Project = false then
yield ShowInstalledPackagesArgs.Project x.Project
if x.Silent.IsPresent then
yield ShowInstalledPackagesArgs.Silent
]
|> parser.CreateParseResultsOfList
|> Program.getInstalledPackages
return packages
}

runWithLogging x computation
(fun sink packages ->
for name,version in packages do
sink.Add
(PaketOutput.Package {Name=name; Version=version})
(fun po ->
match po with
| Package p -> x.WriteObject p
| _ -> () ) )

[<Cmdlet("Paket", "Update")>]
type UpdateCmdlet() =
Expand Down
2 changes: 1 addition & 1 deletion src/Paket.PowerShell/init.ps1
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
param($installPath, $toolsPath, $package)
Import-Module (Join-Path $toolsPath 'Paket.PowerShell\Paket.PowerShell.dll') -DisableNameChecking
Import-Module (Join-Path $toolsPath 'Paket.PowerShell\Paket.PowerShell.psd1') -DisableNameChecking
32 changes: 17 additions & 15 deletions src/Paket/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -213,24 +213,25 @@ let findPackages (results : ArgParseResults<_>) =

| Some searchText -> searchAndPrint searchText

let showInstalledPackages (results : ArgParseResults<_>) =
// separated out from showInstalledPackages to allow Paket.PowerShell to get the types
let getInstalledPackages (results : ArgParseResults<_>) =
let project = results.TryGetResult <@ ShowInstalledPackagesArgs.Project @>
let showAll = results.Contains <@ ShowInstalledPackagesArgs.All @>
let dependenciesFile = Dependencies.Locate()
let packages =
match project with
| None ->
if showAll then dependenciesFile.GetInstalledPackages()
else dependenciesFile.GetDirectDependencies()
| Some project ->
match ProjectFile.FindReferencesFile(FileInfo project) with
| None -> []
| Some referencesFile ->
let referencesFile = ReferencesFile.FromFile referencesFile
if showAll then dependenciesFile.GetInstalledPackages(referencesFile)
else dependenciesFile.GetDirectDependencies(referencesFile)

for name,version in packages do
match project with
| None ->
if showAll then dependenciesFile.GetInstalledPackages()
else dependenciesFile.GetDirectDependencies()
| Some project ->
match ProjectFile.FindReferencesFile(FileInfo project) with
| None -> []
| Some referencesFile ->
let referencesFile = ReferencesFile.FromFile referencesFile
if showAll then dependenciesFile.GetInstalledPackages(referencesFile)
else dependenciesFile.GetDirectDependencies(referencesFile)

let showInstalledPackages (results : ArgParseResults<_>) =
for name,version in getInstalledPackages results do
tracefn "%s - %s" name version

let findPackageVersions (results : ArgParseResults<_>) =
Expand Down Expand Up @@ -290,6 +291,7 @@ let main() =
let args = args.[1..]

handler command args
()
| [] ->
Environment.ExitCode <- 1
traceError "Command was:"
Expand Down

0 comments on commit bc7e6a8

Please sign in to comment.