Skip to content

Commit 23ccd1f

Browse files
committed
Refactored completers to respect a timeout of default 2 seconds. Added completer for Get-PnPPage
1 parent e94c7b3 commit 23ccd1f

File tree

8 files changed

+111
-6
lines changed

8 files changed

+111
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
1010

1111
### Added
1212

13+
- Added tab completers for all cmdlets using a ListPipeBind parameter (e.g. `Get-PnPList -Identity`), all cmdlets using a FieldPipeBind parameter (e.g. `Get-PnPField -Identity`), `Get-PnPPropertyBag` and `Get-PnPPage` cmdlets. The argument lookup will timeout after 2 seconds. This value can controlled by setting an environment variables called "PNPPSCOMPLETERTIMEOUT" and set the value to a number specifying milliseconds (e.g. 2000 is 2 seconds)
1314
- Added `Reset-PnPDocumentID` cmdlet to request resetting the document ID for a document [#4238](https://github.com/pnp/powershell/pull/4238)
1415
- Added `Get-PnPPriviledgedIdentityManagementEligibleAssignment`, `Get-PnPPriviledgedIdentityManagementRole` and `Enable-PnPPriviledgedIdentityManagement` cmdlets to allow scripting of enabling Privileged Identity Management roles for a user [#4039](https://github.com/pnp/powershell/pull/4039)
1516
- Added `Add-PnPTenantRestrictedSearchAllowedList` which allows setting up a list of allowed URLs for Restricted SharePoint Search [#3993](https://github.com/pnp/powershell/pull/3993)

src/Commands/Base/Completers/ContentTypeCompleter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99

1010
namespace PnP.PowerShell.Commands.Base.Completers
1111
{
12-
public sealed class ContentTypeCompleter : IArgumentCompleter
12+
public sealed class ContentTypeCompleter : PnPArgumentCompleter
1313
{
14-
public IEnumerable<CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters)
14+
public override IEnumerable<CompletionResult> GetArguments(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters)
1515
{
1616
wordToComplete = wordToComplete.Trim('"');
1717

src/Commands/Base/Completers/FieldInternalNameCompleter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@
99

1010
namespace PnP.PowerShell.Commands.Base.Completers
1111
{
12-
public sealed class FieldInternalNameCompleter : IArgumentCompleter
12+
public sealed class FieldInternalNameCompleter : PnPArgumentCompleter
1313
{
14-
public IEnumerable<CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters)
14+
public override IEnumerable<CompletionResult> GetArguments(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters)
1515
{
1616
wordToComplete = wordToComplete.Trim('"');
1717

src/Commands/Base/Completers/ListNameCompleter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

99
namespace PnP.PowerShell.Commands.Base.Completers
1010
{
11-
public sealed class ListNameCompleter : IArgumentCompleter
11+
public sealed class ListNameCompleter : PnPArgumentCompleter
1212
{
13-
public IEnumerable<CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters)
13+
public override IEnumerable<CompletionResult> GetArguments(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters)
1414
{
1515
wordToComplete = wordToComplete.Trim('"');
1616

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Management.Automation;
6+
using System.Management.Automation.Language;
7+
using System.Reflection.Metadata;
8+
using System.Threading;
9+
using System.Threading.Tasks;
10+
using AngleSharp.Css.Values;
11+
using Microsoft.SharePoint.Client;
12+
using PnP.Core.Transformation.Model;
13+
using PnP.PowerShell.Commands.Extensions;
14+
15+
namespace PnP.PowerShell.Commands.Base.Completers
16+
{
17+
public sealed class PageCompleter : PnPArgumentCompleter
18+
{
19+
public override IEnumerable<CompletionResult> GetArguments(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters)
20+
{
21+
List<CompletionResult> results = new List<CompletionResult>();
22+
wordToComplete = wordToComplete.Trim('"');
23+
wordToComplete = wordToComplete.Replace('\\', '/');
24+
var pages = PnPConnection.Current.PnPContext.Web.GetPages(wordToComplete.TrimStart('/'));
25+
foreach (var page in pages.OrderBy(p => p.Name))
26+
{
27+
var result = string.IsNullOrEmpty(page.Folder) ? page.Name : page.Folder + "/" + page.Name;
28+
results.Add(new CompletionResult($"\"{result}\""));
29+
}
30+
return results;
31+
}
32+
}
33+
34+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Management.Automation;
5+
using System.Management.Automation.Language;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using PnP.PowerShell.Commands.Extensions;
9+
10+
public abstract class PnPArgumentCompleter : IArgumentCompleter
11+
{
12+
private const int Timeout = 2000;
13+
public IEnumerable<CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters)
14+
{
15+
var task = Task.Run(() => GetArguments(commandName, parameterName, wordToComplete, commandAst, fakeBoundParameters));
16+
return task.TimeoutAfter(TimeSpan.FromMilliseconds(GetTimeOut())).GetAwaiter().GetResult();
17+
}
18+
19+
public abstract IEnumerable<CompletionResult> GetArguments(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters);
20+
21+
private Int32 GetTimeOut()
22+
{
23+
var timeOutFromEnv = Environment.GetEnvironmentVariable("PNPPSCOMPLETERTIMEOUT");
24+
if (!string.IsNullOrEmpty(timeOutFromEnv))
25+
{
26+
try
27+
{
28+
return Convert.ToInt32(timeOutFromEnv);
29+
}
30+
catch (FormatException)
31+
{
32+
return Timeout;
33+
}
34+
}
35+
else
36+
{
37+
return Timeout;
38+
}
39+
}
40+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace PnP.PowerShell.Commands.Extensions
6+
{
7+
public static class TaskExtensions
8+
{
9+
public static async Task<TResult> TimeoutAfter<TResult>(this Task<TResult> task, TimeSpan timeout)
10+
{
11+
12+
using (var timeoutCancellationTokenSource = new CancellationTokenSource())
13+
{
14+
15+
var completedTask = await Task.WhenAny(task, Task.Delay(timeout, timeoutCancellationTokenSource.Token));
16+
if (completedTask == task)
17+
{
18+
timeoutCancellationTokenSource.Cancel();
19+
return await task; // Very important in order to propagate exceptions
20+
}
21+
else
22+
{
23+
throw new TimeoutException("The operation has timed out.");
24+
}
25+
}
26+
}
27+
}
28+
}

src/Commands/Pages/GetPage.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11

2+
using PnP.PowerShell.Commands.Base.Completers;
23
using PnP.PowerShell.Commands.Base.PipeBinds;
34
using System;
45
using System.Management.Automation;
@@ -11,6 +12,7 @@ namespace PnP.PowerShell.Commands.Pages
1112
public class GetPage : PnPWebCmdlet
1213
{
1314
[Parameter(Mandatory = true, ValueFromPipeline = true, Position = 0)]
15+
[ArgumentCompleter(typeof(PCompleter))]
1416
public PagePipeBind Identity;
1517

1618
protected override void ExecuteCmdlet()

0 commit comments

Comments
 (0)