private Collection <CompletionResult> FilterCompletions(CommandCompletion completion, string completionFilter) { var newMatches = new Collection <CompletionResult>(); var matches = completion.CompletionMatches; bool consistentQuoting = IsConsistentQuoting(matches); // add possible first quote to userCompletionText if (consistentQuoting) { var quote = matches[0].CompletionText[0]; if (IsSingleQuote(quote) || IsDoubleQuote(quote)) { completionFilter = quote + completionFilter; } } foreach (CompletionResult item in matches) { if (item.ListItemText.StartsWith(completionFilter, StringComparison.OrdinalIgnoreCase) || GetUnquotedText(item, consistentQuoting).StartsWith(completionFilter, StringComparison.OrdinalIgnoreCase)) { newMatches.Add(item); } } return(newMatches); }
public void Completion_NoMatch_Test() { var completion = new CommandCompletion(_TestCommands); completion.Completion("foo").Is("foo"); completion.Completion("foo").Is("foo"); }
private CommandCompletion GetCompletions() { if (_tabCommandCount == 0) { try { _tabCompletions = null; // Could use the overload that takes an AST as it's faster (we've already parsed the // input for coloring) but that overload is a little more complicated in passing in the // cursor position. System.Management.Automation.PowerShell ps; if (!_mockableMethods.RunspaceIsRemote(_runspace)) { ps = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace); } else { ps = System.Management.Automation.PowerShell.Create(); ps.Runspace = _runspace; } _tabCompletions = _mockableMethods.CompleteInput(_buffer.ToString(), _current, null, ps); if (_tabCompletions.CompletionMatches.Count == 0) { return(null); } } catch (Exception) { } } return(_tabCompletions); }
public object GetAutoCompletionPrefix(string guid, string command) { if (!IsLoggedInUserAuthorized || !SessionElevationManager.IsSessionTokenElevated(ApplicationNames.ISE)) { return(string.Empty); } PowerShellLog.Info($"Auto completion requested in session '{guid}' by user: '******'"); var serializer = new JavaScriptSerializer(); var session = GetScriptSession(guid); try { var result = serializer.Serialize(CommandCompletion.GetPrefix(session, command)); return(result); } finally { if (string.IsNullOrEmpty(guid)) { ScriptSessionManager.RemoveSession(session); } } }
/// <summary> /// Gets completions for a statement contained in the given /// script file at the specified line and column position. /// </summary> /// <param name="scriptFile"> /// The script file in which completions will be gathered. /// </param> /// <param name="lineNumber"> /// The 1-based line number at which completions will be gathered. /// </param> /// <param name="columnNumber"> /// The 1-based column number at which completions will be gathered. /// </param> /// <returns> /// A CommandCompletion instance completions for the identified statement. /// </returns> internal async Task <IEnumerable <CompletionItem> > GetCompletionsInFileAsync( ScriptFile scriptFile, int lineNumber, int columnNumber, CancellationToken cancellationToken) { Validate.IsNotNull(nameof(scriptFile), scriptFile); CommandCompletion result = await AstOperations.GetCompletionsAsync( scriptFile.ScriptAst, scriptFile.ScriptTokens, scriptFile.GetOffsetAtPosition(lineNumber, columnNumber), _executionService, _logger, cancellationToken).ConfigureAwait(false); if (result.CompletionMatches.Count == 0) { return(Array.Empty <CompletionItem>()); } BufferRange replacedRange = scriptFile.GetRangeBetweenOffsets( result.ReplacementIndex, result.ReplacementIndex + result.ReplacementLength); // Create OmniSharp CompletionItems from PowerShell CompletionResults. We use a for loop // because the index is used for sorting. CompletionItem[] completionItems = new CompletionItem[result.CompletionMatches.Count]; for (int i = 0; i < result.CompletionMatches.Count; i++) { completionItems[i] = CreateCompletionItem(result.CompletionMatches[i], replacedRange, i + 1); } return(completionItems); }
/// <summary> /// Completion lists calculator. /// </summary> /// <param name="script">The active script.</param> /// <param name="caretPosition">The caret position.</param> /// <param name="runspace">Runspace for completion computing.</param> /// <returns></returns> public static CommandCompletion GetCommandCompletionList(string script, int caretPosition, Runspace runspace) { Ast ast; Token[] tokens; IScriptPosition cursorPosition; GetCommandCompletionParameters(script, caretPosition, out ast, out tokens, out cursorPosition); if (ast == null) { return(null); } CommandCompletion commandCompletion = null; if (runspace.RunspaceAvailability == RunspaceAvailability.Available) { using (_currentPowerShell = PowerShell.Create()) { _currentPowerShell.Runspace = runspace; commandCompletion = CommandCompletion.CompleteInput(ast, tokens, cursorPosition, null, _currentPowerShell); } } return(commandCompletion); }
private CommandCompletion GetCompletions() { if (_tabCommandCount == 0) { try { _tabCompletions = null; // Could use the overload that takes an AST as it's faster (we've already parsed the // input for coloring) but that overload is a little more complicated in passing in the // cursor position. var ps = PowerShell.Create(RunspaceMode.CurrentRunspace); _tabCompletions = CommandCompletion.CompleteInput(_buffer.ToString(), _current, null, ps); if (_tabCompletions.CompletionMatches.Count == 0) { return(null); } } catch (Exception) { } } return(_tabCompletions); }
public async Task<string> GetCompletion( string input, int index, bool forward) { // Suggest a file if the input is blank. if (string.IsNullOrWhiteSpace(input)) { input = PATH_BEGIN; index = PATH_BEGIN.Length; } if (index == 0) return null; // Check the user has altered the input and we need to update our // completion list. if (completionListNeedsUpdate(input, index)) { cachedCompletions = await Task.Run( () => CommandCompletion.CompleteInput( input, index, null, ps)); } var result = await Task.Run( () => cachedCompletions.GetNextResult(forward)); if (result == null) return null; expectedInput = input.Substring( 0, cachedCompletions.ReplacementIndex); expectedInput += result.CompletionText; expectedInputIndex = expectedInput.Length; return expectedInput; }
int getCurrentReplacementLength(CommandCompletion completions) { var matchIndex = completions.CurrentMatchIndex; return matchIndex == -1 ? completions.ReplacementLength : completions.CompletionMatches[matchIndex] .CompletionText.Length; }
internal static CompletionResults Create( CommandCompletion commandCompletion) { return(new CompletionResults { Completions = GetCompletionsArray(commandCompletion), }); }
/// <summary> /// Gets completions for a statement contained in the given /// script file at the specified line and column position. /// </summary> /// <param name="scriptFile"> /// The script file in which completions will be gathered. /// </param> /// <param name="lineNumber"> /// The 1-based line number at which completions will be gathered. /// </param> /// <param name="columnNumber"> /// The 1-based column number at which completions will be gathered. /// </param> /// <returns> /// A CommandCompletion instance completions for the identified statement. /// </returns> public async Task <CompletionResults> GetCompletionsInFileAsync( ScriptFile scriptFile, int lineNumber, int columnNumber) { Validate.IsNotNull(nameof(scriptFile), scriptFile); // Get the offset at the specified position. This method // will also validate the given position. int fileOffset = scriptFile.GetOffsetAtPosition( lineNumber, columnNumber); CommandCompletion commandCompletion = null; using (var cts = new CancellationTokenSource(DefaultWaitTimeoutMilliseconds)) { commandCompletion = await AstOperations.GetCompletionsAsync( scriptFile.ScriptAst, scriptFile.ScriptTokens, fileOffset, _powerShellContextService, _logger, cts.Token).ConfigureAwait(false); } if (commandCompletion == null) { return(new CompletionResults()); } try { CompletionResults completionResults = CompletionResults.Create( scriptFile, commandCompletion); // save state of most recent completion _mostRecentCompletions = completionResults; _mostRecentRequestFile = scriptFile.Id; _mostRecentRequestLine = lineNumber; _mostRecentRequestOffest = columnNumber; return(completionResults); } catch (ArgumentException e) { // Bad completion results could return an invalid // replacement range, catch that here _logger.LogError( $"Caught exception while trying to create CompletionResults:\n\n{e.ToString()}"); return(new CompletionResults()); } }
private static CompletionDetails[] GetCompletionsArray( CommandCompletion commandCompletion) { IEnumerable<CompletionDetails> completionList = commandCompletion.CompletionMatches.Select( CompletionDetails.Create); return completionList.ToArray(); }
private static CompletionDetails[] GetCompletionsArray( CommandCompletion commandCompletion) { IEnumerable <CompletionDetails> completionList = commandCompletion.CompletionMatches.Select( CompletionDetails.Create); return(completionList.ToArray()); }
/// <summary> /// Gets completions for a statement contained in the given /// script file at the specified line and column position. /// </summary> /// <param name="scriptFile"> /// The script file in which completions will be gathered. /// </param> /// <param name="lineNumber"> /// The 1-based line number at which completions will be gathered. /// </param> /// <param name="columnNumber"> /// The 1-based column number at which completions will be gathered. /// </param> /// <returns> /// A CommandCompletion instance completions for the identified statement. /// </returns> public async Task <CompletionResults> GetCompletionsInFile( ScriptFile scriptFile, int lineNumber, int columnNumber) { Validate.IsNotNull("scriptFile", scriptFile); // Get the offset at the specified position. This method // will also validate the given position. int fileOffset = scriptFile.GetOffsetAtPosition( lineNumber, columnNumber); RunspaceHandle runspaceHandle = await this.powerShellContext.GetRunspaceHandle( new CancellationTokenSource(DefaultWaitTimeoutMilliseconds).Token); CommandCompletion commandCompletion = AstOperations.GetCompletions( scriptFile.ScriptAst, scriptFile.ScriptTokens, fileOffset, runspaceHandle.Runspace); runspaceHandle.Dispose(); if (commandCompletion != null) { try { CompletionResults completionResults = CompletionResults.Create( scriptFile, commandCompletion); // save state of most recent completion mostRecentCompletions = completionResults; mostRecentRequestFile = scriptFile.Id; mostRecentRequestLine = lineNumber; mostRecentRequestOffest = columnNumber; return(completionResults); } catch (ArgumentException e) { // Bad completion results could return an invalid // replacement range, catch that here Logger.Write( LogLevel.Error, $"Caught exception while trying to create CompletionResults:\n\n{e.ToString()}"); } } // If all else fails, return empty results return(new CompletionResults()); }
public void Completion_FromEmpty_to_NoMatch_Test() { var completion = new CommandCompletion(_TestCommands); completion.Completion("").Is("banner"); completion.Completion("banner").Is("clear"); completion.Completion("bar").Is("bar"); }
private void StartIntelliSense(int lineStartPosition, int caretPosition, string lineTextUpToCaret) { if (_intellisenseRunning) { return; } _intellisenseRunning = true; var statusBar = (IVsStatusbar)PowerShellToolsPackage.Instance.GetService(typeof(SVsStatusbar)); statusBar.SetText("Running IntelliSense..."); var sw = new Stopwatch(); sw.Start(); Ast ast; Token[] tokens; IScriptPosition cursorPosition; GetCommandCompletionParameters(caretPosition, out ast, out tokens, out cursorPosition); if (ast == null) { return; } var ps = PowerShell.Create(); ps.Runspace = PowerShellToolsPackage.Debugger.Runspace; var commandCompletion = CommandCompletion.CompleteInput(ast, tokens, cursorPosition, null, ps); var line = _textView.Caret.Position.BufferPosition.GetContainingLine(); var caretInLine = (caretPosition - line.Start); var text = line.GetText().Substring(0, caretInLine); IList <CompletionResult> list = commandCompletion.CompletionMatches; if (string.Equals(lineTextUpToCaret, text, StringComparison.Ordinal) && list.Count != 0) { if (list.Count != 0) { try { IntellisenseDone(commandCompletion.CompletionMatches, lineStartPosition, commandCompletion.ReplacementIndex + 0, commandCompletion.ReplacementLength, caretPosition); } catch (Exception ex) { Log.Debug("Failed to start IntelliSense.", ex); } } } statusBar.SetText(String.Format("IntelliSense complete in {0:0.00} seconds...", sw.Elapsed.TotalSeconds)); _intellisenseRunning = false; }
public string[] GetTabCompletion(string commandLine) { string[] strArrays; if (commandLine != null) { lock (this.clientRequestLock) { if (this.State == PowwaSession.SessionState.Available) { this.State = PowwaSession.SessionState.ExecutingCommand; System.Management.Automation.PowerShell powerShell = null; try { try { powerShell = System.Management.Automation.PowerShell.Create(); powerShell.Runspace = this.Runspace; CommandCompletion commandCompletion = CommandCompletion.CompleteInput(commandLine, commandLine.Length, null, powerShell); string str = commandLine.Substring(0, commandCompletion.ReplacementIndex); string[] strArrays1 = new string[commandCompletion.CompletionMatches.Count]; for (int i = 0; i < commandCompletion.CompletionMatches.Count; i++) { strArrays1[i] = string.Concat(str, commandCompletion.CompletionMatches[i].CompletionText); } strArrays = strArrays1; } catch { strArrays = new string[0]; } } finally { if (powerShell != null) { powerShell.Dispose(); } this.State = PowwaSession.SessionState.Available; } } else { PowwaEvents.PowwaEVENT_DEBUG_LOG1("GetTabCompletion(): Invalid Session State", "SessionState", this.State.ToString()); throw new InvalidOperationException("The session is not available"); } } return(strArrays); } else { throw new ArgumentNullException("commandLine"); } }
/// <summary> /// Gets completions for the symbol found in the Ast at /// the given file offset. /// </summary> /// <param name="scriptAst"> /// The Ast which will be traversed to find a completable symbol. /// </param> /// <param name="currentTokens"> /// The array of tokens corresponding to the scriptAst parameter. /// </param> /// <param name="fileOffset"> /// The 1-based file offset at which a symbol will be located. /// </param> /// <param name="runspace"> /// The Runspace to use for gathering completions. /// </param> /// <returns> /// A CommandCompletion instance that contains completions for the /// symbol at the given offset. /// </returns> static public CommandCompletion GetCompletions( Ast scriptAst, Token[] currentTokens, int fileOffset, Runspace runspace) { var type = scriptAst.Extent.StartScriptPosition.GetType(); var method = #if NanoServer type.GetMethod( "CloneWithNewOffset", BindingFlags.Instance | BindingFlags.NonPublic); #else type.GetMethod( "CloneWithNewOffset", BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(int) }, null); #endif IScriptPosition cursorPosition = (IScriptPosition)method.Invoke( scriptAst.Extent.StartScriptPosition, new object[] { fileOffset }); Logger.Write( LogLevel.Verbose, string.Format( "Getting completions at offset {0} (line: {1}, column: {2})", fileOffset, cursorPosition.LineNumber, cursorPosition.ColumnNumber)); CommandCompletion commandCompletion = null; if (runspace.RunspaceAvailability == RunspaceAvailability.Available) { using (System.Management.Automation.PowerShell powerShell = System.Management.Automation.PowerShell.Create()) { powerShell.Runspace = runspace; commandCompletion = CommandCompletion.CompleteInput( scriptAst, currentTokens, cursorPosition, null, powerShell); } } return(commandCompletion); }
internal static CompletionResults Create( ScriptFile scriptFile, CommandCompletion commandCompletion) { return new CompletionResults { Completions = GetCompletionsArray(commandCompletion), ReplacedRange = scriptFile.GetRangeBetweenOffsets( commandCompletion.ReplacementIndex, commandCompletion.ReplacementIndex + commandCompletion.ReplacementLength) }; }
public void Completion_FromEmpty_Test() { var completion = new CommandCompletion(_TestCommands); completion.Completion("").Is("banner"); completion.Completion("banner").Is("clear"); completion.Completion("clear").Is("cls"); completion.Completion("cls").Is("figgle"); completion.Completion("figgle").Is("figlet"); completion.Completion("figlet").Is("help"); completion.Completion("help").Is("banner"); completion.Completion("banner").Is("clear"); }
internal static CompletionResults Create( ScriptFile scriptFile, CommandCompletion commandCompletion) { return(new CompletionResults { Completions = GetCompletionsArray(commandCompletion), ReplacedRange = scriptFile.GetRangeBetweenOffsets( commandCompletion.ReplacementIndex, commandCompletion.ReplacementIndex + commandCompletion.ReplacementLength) }); }
public CommandCompletion CompleteInput(string input, int cursorIndex) { System.Management.Automation.PowerShell ps; if (!IsRemote) { ps = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace); } else { ps = System.Management.Automation.PowerShell.Create(); ps.Runspace = _runSpace; } return(CommandCompletion.CompleteInput(input, cursorIndex, null, ps)); }
public void Completion_Match_to_AnotherMatch_Test() { var completion = new CommandCompletion(_TestCommands); completion.Completion("c").Is("clear"); completion.Completion("clear").Is("cls"); completion.Completion("cls").Is("clear"); completion.Completion("he").Is("help"); completion.Completion("help").Is("help"); completion.Completion("").Is("banner"); completion.Completion("banner").Is("clear"); }
public static PwshCommandCompletion ToPwshCompletion(this CommandCompletion completion) { return(new PwshCommandCompletion() { CurrentMatchIndex = completion.CurrentMatchIndex, ReplacementIndex = completion.ReplacementIndex, ReplacementLength = completion.ReplacementLength, CompletionMatches = completion.CompletionMatches .Select(x => new PwshCompletionResult(x.CompletionText, x.ListItemText, EnumMapper.ToEnum <PwshCompletionResultType, CompletionResultType>(x.ResultType), x.ToolTip)) .ToList() }); }
public CommandCompletion GetCompletions(string inputText, int currentIndex, bool?forward) { if (_lastCompletion is null || inputText != _lastInputText) { _lastInputText = inputText; _lastCompletion = CommandCompletion.CompleteInput(inputText, currentIndex, new(), _powershell); } if (forward.HasValue) { _lastCompletion.GetNextResult(forward.Value); } return(_lastCompletion); }
private void DoReplacementForCompletion(CompletionResult completionResult, CommandCompletion completions) { var replacementText = completionResult.CompletionText; int cursorAdjustment = 0; if (completionResult.ResultType == CompletionResultType.ProviderContainer) { replacementText = GetReplacementTextForDirectory(replacementText, ref cursorAdjustment); } Replace(completions.ReplacementIndex, completions.ReplacementLength, replacementText); if (cursorAdjustment != 0) { MoveCursor(_current + cursorAdjustment); } completions.ReplacementLength = replacementText.Length; }
private void ProcessCompletion(string script, int caretPosition, int requestWindowId, long triggerTag) { lock (_syncLock) { _requestTrigger = triggerTag; } if (_callback == null) { _callback = OperationContext.Current.GetCallbackChannel <IIntelliSenseServiceCallback>(); } // Start process the existing waiting request, should only be one Task.Run(() => { try { CommandCompletion commandCompletion = null; lock (ServiceCommon.RunspaceLock) { if (_runspace.RunspaceAvailability == RunspaceAvailability.Available) { commandCompletion = CommandCompletionHelper.GetCommandCompletionList(script, caretPosition, _runspace); } else { // we'll handle it when we work on giving intellisense for debugging command // for now we just simply return with null for this request to complete. } } ServiceCommon.LogCallbackEvent("Callback intellisense at position {0}", caretPosition); _callback.PushCompletionResult(CompletionResultList.FromCommandCompletion(commandCompletion), requestWindowId); // Reset trigger lock (_syncLock) { _requestTrigger = 0; } } catch (Exception ex) { ServiceCommon.Log("Failed to retrieve the completion list per request due to exception: {0}", ex.Message); } }); }
/// <summary> /// Gets completions for a statement contained in the given /// script file at the specified line and column position. /// </summary> /// <param name="scriptFile"> /// The script file in which completions will be gathered. /// </param> /// <param name="lineNumber"> /// The 1-based line number at which completions will be gathered. /// </param> /// <param name="columnNumber"> /// The 1-based column number at which completions will be gathered. /// </param> /// <returns> /// A CommandCompletion instance completions for the identified statement. /// </returns> public async Task <CompletionResults> GetCompletionsInFile( ScriptFile scriptFile, int lineNumber, int columnNumber) { Validate.IsNotNull("scriptFile", scriptFile); // Get the offset at the specified position. This method // will also validate the given position. int fileOffset = scriptFile.GetOffsetAtPosition( lineNumber, columnNumber); RunspaceHandle runspaceHandle = await this.powerShellContext.GetRunspaceHandle( new CancellationTokenSource(DefaultWaitTimeoutMilliseconds).Token); CommandCompletion commandCompletion = AstOperations.GetCompletions( scriptFile.ScriptAst, scriptFile.ScriptTokens, fileOffset, runspaceHandle.Runspace); runspaceHandle.Dispose(); if (commandCompletion != null) { CompletionResults completionResults = CompletionResults.Create( scriptFile, commandCompletion); // save state of most recent completion mostRecentCompletions = completionResults; mostRecentRequestFile = scriptFile.Id; mostRecentRequestLine = lineNumber; mostRecentRequestOffest = columnNumber; return(completionResults); } else { return(new CompletionResults()); } }
private static string[] GetTabCompletionOutputs(string guid, string command, bool lastTokenOnly) { var session = GetScriptSession(guid); try { var result = CommandCompletion.FindMatches(session, command, lastTokenOnly); return(result.ToArray()); } finally { if (string.IsNullOrEmpty(guid)) { ScriptSessionManager.RemoveSession(session); } } }
/// <summary> /// Shows the tab-expansion popup. /// </summary> /// <param name="placementRectangle">The position to show the popup in.</param> /// <param name="list">The list of options</param> /// <param name="currentCommand">The current command</param> internal void ShowTabPopup(Rect placementRectangle, CommandCompletion list, string currentCommand) { // TODO: Minor: Sort this intelligently, by type... // list.Sort(); var matches = list.CompletionMatches; var listText = matches.Select(m => m.ListItemText).ToList(); var outputText = matches.Select(m => m.CompletionText).ToList(); var tooltips = matches.Select(m => m.ToolTip).ToList(); // And filter it too _tabbing = currentCommand.TrimEnd('\r', '\n'); _lastWord = _tabbing.GetLastWord(); // the sweet typeahead auto-filter _intellisense.Items.Filter = TypeAheadFilter; ShowPopup(placementRectangle, listText, outputText, tooltips, false, false); }
public Option <CommandCompletion <TSpec> > Complete <TSpec>(CommandResult <TSpec> result) where TSpec : CommandSpec <TSpec>, new() { if (Dispatches.TryGetValue(result.SubmissionId, out ICommandDispatch dispatched)) { var completion = CommandCompletion.Create((CommandDispatch <TSpec>)dispatched, result, now()); if (!Completions.TryAdd(result.SubmissionId, completion)) { throw new Exception("Can't add task to the memory completion index"); } else { return(completion); } } return(none <CommandCompletion <TSpec> >()); }
public void Completion_FromEmpty_to_AnotherMatch_Test() { var completion = new CommandCompletion(this._TestCommands); completion.Completion("").Is("banner"); completion.Completion("banner").Is("clear"); completion.Completion("fig").Is("figgle"); completion.Completion("figgle").Is("figlet"); completion.Completion("figlet").Is("figgle"); completion.Completion("figgle").Is("figlet"); completion.Completion("he").Is("help"); completion.Completion("help").Is("help"); completion.Completion("").Is("banner"); completion.Completion("banner").Is("clear"); }
public Option <ReadOnlyList <ICommandCompletion> > Complete(IEnumerable <ICommandResult> results) { var completions = MutableList.Create <ICommandCompletion>(); foreach (var result in results) { if (Dispatches.TryGetValue(result.SubmissionId, out ICommandDispatch dispatched)) { var completion = new CommandCompletion(dispatched, result, now()); if (!Completions.TryAdd(result.SubmissionId, completion)) { throw new Exception("Can't add task to the memory completion index"); } completions.Add(completion); } } return(ReadOnlyList.Create(completions)); }
private void PossibleCompletionsImpl(CommandCompletion completions, bool menuSelect) { if (completions == null || completions.CompletionMatches.Count == 0) { Ding(); return; } if (completions.CompletionMatches.Count >= _options.CompletionQueryItems) { if (!PromptYesOrNo(string.Format(CultureInfo.CurrentCulture, PSReadLineResources.DisplayAllPossibilities, completions.CompletionMatches.Count))) { return; } } var menu = CreateCompletionMenu(completions.CompletionMatches); if (menuSelect) { // Make sure the menu and line can appear on the screen at the same time, // if not, we'll skip the menu. var endBufferPoint = ConvertOffsetToPoint(_buffer.Length); menu.BufferLines = endBufferPoint.Y - _initialY + 1 + _options.ExtraPromptLineCount; if (menu.BufferLines + menu.Rows > _console.WindowHeight) { menuSelect = false; } } if (menuSelect) { MenuCompleteImpl(menu, completions); } else { menu.DrawMenu(null, menuSelect: false); InvokePrompt(key: null, arg: _console.CursorTop); } }
public bool GetCompletion(ref string input, ref int index, bool forward) { // Suggest a file if the input is blank. if (string.IsNullOrWhiteSpace(input)) { input = PATH_BEGIN; index = PATH_BEGIN.Length; } if (index == 0) return false; // Check the user has altered the input and we need to update our // completion list. if (completionListNeedsUpdate(input, index)) { completions = CommandCompletion.CompleteInput( input, index, null, powerShell); } // Determine the length of the text to replace with the new // completion. var replacementLength = getCurrentReplacementLength(completions); // Get the completion data. var result = completions.GetNextResult(forward); if (result == null) return false; // Set input and index of the new completion. var replacementIndex = completions.ReplacementIndex; var completionText = result.CompletionText; expectedInput = input .Remove(replacementIndex, replacementLength) .Insert(replacementIndex, completionText); expectedIndex = replacementIndex + completionText.Length; input = expectedInput; index = expectedIndex; return true; }
// [rgn] Public Methods (4) //private IPoshConsoleService _service; //public void SetService(IPoshConsoleService service) //{ // _service = service; //} public CommandCompletion GetChoices(string currentCommand, int cursorIndex) { ConsoleControl.TabExpansionTrace.TraceEvent(TraceEventType.Information, 1, "GetChoices for '{0}'", currentCommand); if (_command != currentCommand || (_choices == null || _choices.CompletionMatches.Count == 0) && (_command == null || _command != currentCommand)) { if (TabComplete == null) return null; _command = currentCommand; _choices = TabComplete(currentCommand, cursorIndex); } if (ConsoleControl.TabExpansionTrace.Switch.Level >= SourceLevels.Information) { ConsoleControl.TabExpansionTrace.TraceEvent(TraceEventType.Information, 2, "Choice List:"); foreach (var ch in _choices.CompletionMatches.Select(m => m.ListItemText)) { ConsoleControl.TabExpansionTrace.TraceEvent(TraceEventType.Information, 2, ch); } } return _choices; }
public void Reset() { _index = 0; _command = null; _choices = null; }
private CommandCompletion GetCompletions() { if (_tabCommandCount == 0) { try { _tabCompletions = null; // Could use the overload that takes an AST as it's faster (we've already parsed the // input for coloring) but that overload is a little more complicated in passing in the // cursor position. System.Management.Automation.PowerShell ps; if (!_mockableMethods.RunspaceIsRemote(_runspace)) { ps = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace); } else { ps = System.Management.Automation.PowerShell.Create(); ps.Runspace = _runspace; } String tmpBufferStringForCompleteInput = Options.UseTraditionalCompleteInput ? _buffer.ToString().Substring(0, _current) : _buffer.ToString(); _tabCompletions = _mockableMethods.CompleteInput(tmpBufferStringForCompleteInput, _current, null, ps); if (_tabCompletions.CompletionMatches.Count == 0) return null; } catch (Exception) { } } return _tabCompletions; }
private CommandCompletion GetCompletions() { if (_tabCommandCount == 0) { try { _tabCompletions = null; // Could use the overload that takes an AST as it's faster (we've already parsed the // input for coloring) but that overload is a little more complicated in passing in the // cursor position. PowerShell ps; if (_remoteRunspace == null) { ps = PowerShell.Create(RunspaceMode.CurrentRunspace); } else { ps = PowerShell.Create(); ps.Runspace = _remoteRunspace; } _tabCompletions = _mockableMethods.CompleteInput(_buffer.ToString(), _current, null, ps); if (_tabCompletions.CompletionMatches.Count == 0) return null; } catch (Exception) { } } return _tabCompletions; }
/// <summary> /// Shows the tab-expansion popup. /// </summary> /// <param name="placementRectangle">The position to show the popup in.</param> /// <param name="list">The list of options</param> /// <param name="currentCommand">The current command</param> internal void ShowTabPopup(Rect placementRectangle, CommandCompletion list, string currentCommand) { // TODO: Minor: Sort this intelligently, by type... // list.Sort(); var matches = list.CompletionMatches; var listText = matches.Select(m => m.ListItemText).ToList(); var outputText = matches.Select(m => m.CompletionText).ToList(); var tooltips = matches.Select(m => m.ToolTip).ToList(); // And filter it too _tabbing = currentCommand.TrimEnd('\r', '\n'); _lastWord = _tabbing.GetLastWord(); // the sweet typeahead auto-filter _intellisense.Items.Filter = TypeAheadFilter; ShowPopup(placementRectangle, listText, outputText, tooltips, false, false); }
internal static CompletionResults Create( CommandCompletion commandCompletion) { return new CompletionResults { Completions = GetCompletionsArray(commandCompletion), }; }
private void PossibleCompletionsImpl(CommandCompletion completions, bool menuSelect) { if (completions == null || completions.CompletionMatches.Count == 0) { Ding(); return; } if (completions.CompletionMatches.Count >= _options.CompletionQueryItems) { if (!PromptYesOrNo(string.Format(CultureInfo.CurrentCulture, PSReadLineResources.DisplayAllPossibilities, completions.CompletionMatches.Count))) { return; } } var matches = completions.CompletionMatches; var minColWidth = matches.Max(c => c.ListItemText.Length); minColWidth += 2; var menuColumnWidth = minColWidth; int displayRows; var bufferWidth = Console.BufferWidth; ConsoleBufferBuilder cb; if (Options.ShowToolTips) { const string seperator = "- "; var maxTooltipWidth = bufferWidth - minColWidth - seperator.Length; displayRows = matches.Count; cb = new ConsoleBufferBuilder(displayRows * bufferWidth); for (int index = 0; index < matches.Count; index++) { var match = matches[index]; var listItemText = HandleNewlinesForPossibleCompletions(match.ListItemText); cb.Append(listItemText); var spacesNeeded = minColWidth - listItemText.Length; if (spacesNeeded > 0) { cb.Append(' ', spacesNeeded); } cb.Append(seperator); var toolTip = HandleNewlinesForPossibleCompletions(match.ToolTip); toolTip = toolTip.Length <= maxTooltipWidth ? toolTip : toolTip.Substring(0, maxTooltipWidth); cb.Append(toolTip); // Make sure we always write out exactly 1 buffer width spacesNeeded = (bufferWidth * (index + 1)) - cb.Length; if (spacesNeeded > 0) { cb.Append(' ', spacesNeeded); } } menuColumnWidth = bufferWidth; } else { var screenColumns = bufferWidth; var displayColumns = Math.Max(1, screenColumns / minColWidth); displayRows = (completions.CompletionMatches.Count + displayColumns - 1) / displayColumns; cb = new ConsoleBufferBuilder(displayRows * bufferWidth); for (var row = 0; row < displayRows; row++) { for (var col = 0; col < displayColumns; col++) { var index = row + (displayRows * col); if (index >= matches.Count) break; var match = matches[index]; var item = HandleNewlinesForPossibleCompletions(match.ListItemText); cb.Append(item); cb.Append(' ', minColWidth - item.Length); } // Make sure we always write out exactly 1 buffer width var spacesNeeded = (bufferWidth * (row + 1)) - cb.Length; if (spacesNeeded > 0) { cb.Append(' ', spacesNeeded); } } } var menuBuffer = cb.ToArray(); if (menuSelect) { // Make sure the menu and line can appear on the screen at the same time, // if not, we'll skip the menu. var endBufferCoords = ConvertOffsetToCoordinates(_buffer.Length); var bufferLines = endBufferCoords.Y - _initialY + 1; if ((bufferLines + displayRows) > Console.WindowHeight) { menuSelect = false; } } if (menuSelect) { RemoveEditsAfterUndo(); var undoPoint = _edits.Count; int selectedItem = 0; bool undo = false; DoReplacementForCompletion(matches[0], completions); // Recompute end of buffer coordinates as the replacement could have // added a line. var endBufferCoords = ConvertOffsetToCoordinates(_buffer.Length); var menuAreaTop = endBufferCoords.Y + 1; var previousMenuTop = menuAreaTop; InvertSelectedCompletion(menuBuffer, selectedItem, menuColumnWidth, displayRows); WriteBufferLines(menuBuffer, ref menuAreaTop); // Showing the menu may have scrolled the screen or moved the cursor, update initialY to reflect that. _initialY -= (previousMenuTop - menuAreaTop); PlaceCursor(); previousMenuTop = menuAreaTop; int previousItem = selectedItem; bool processingKeys = true; while (processingKeys) { var nextKey = ReadKey(); if (nextKey == Keys.RightArrow) { selectedItem = Math.Min(selectedItem + displayRows, matches.Count - 1); } else if (nextKey == Keys.LeftArrow) { selectedItem = Math.Max(selectedItem - displayRows, 0); } else if (nextKey == Keys.DownArrow) { selectedItem = Math.Min(selectedItem + 1, matches.Count - 1); } else if (nextKey == Keys.UpArrow) { selectedItem = Math.Max(selectedItem - 1, 0); } else if (nextKey == Keys.Tab) { selectedItem = (selectedItem + 1) % matches.Count; } else if (nextKey == Keys.ShiftTab) { selectedItem = (selectedItem - 1) % matches.Count; if (selectedItem < 0) { selectedItem += matches.Count; } } else if (nextKey == Keys.CtrlG || nextKey == Keys.Escape) { undo = true; processingKeys = false; } else { PrependQueuedKeys(nextKey); processingKeys = false; } if (selectedItem != previousItem) { DoReplacementForCompletion(matches[selectedItem], completions); endBufferCoords = ConvertOffsetToCoordinates(_buffer.Length); menuAreaTop = endBufferCoords.Y + 1; InvertSelectedCompletion(menuBuffer, previousItem, menuColumnWidth, displayRows); InvertSelectedCompletion(menuBuffer, selectedItem, menuColumnWidth, displayRows); WriteBufferLines(menuBuffer, ref menuAreaTop); previousItem = selectedItem; if (previousMenuTop > menuAreaTop) { WriteBlankLines(previousMenuTop - menuAreaTop, menuAreaTop + displayRows); } } } WriteBlankLines(displayRows, menuAreaTop); var lastInsert = ((GroupedEdit)_edits[_edits.Count - 1])._groupedEditItems[1]; Debug.Assert(lastInsert is EditItemInsertString, "The only edits possible here are pairs of Delete/Insert"); var firstDelete = ((GroupedEdit)_edits[undoPoint])._groupedEditItems[0]; Debug.Assert(firstDelete is EditItemDelete, "The only edits possible here are pairs of Delete/Insert"); var groupEditCount = _edits.Count - undoPoint; _edits.RemoveRange(undoPoint, groupEditCount); _undoEditIndex = undoPoint; if (undo) { // Pretend it never happened. lastInsert.Undo(); firstDelete.Undo(); Render(); } else { // Leave one edit instead of possibly many to undo SaveEditItem(GroupedEdit.Create(new List<EditItem> { firstDelete, lastInsert })); } } else { var endBufferCoords = ConvertOffsetToCoordinates(_buffer.Length); var menuAreaTop = endBufferCoords.Y + 1; WriteBufferLines(menuBuffer, ref menuAreaTop); _initialY = menuAreaTop + displayRows; Render(); } }
private void DoReplacementForCompletion(CompletionResult completionResult, CommandCompletion completions) { var replacementText = completionResult.CompletionText; int cursorAdjustment = 0; if (completionResult.ResultType == CompletionResultType.ProviderContainer) { replacementText = GetReplacementTextForDirectory(replacementText, ref cursorAdjustment); } Replace(completions.ReplacementIndex, completions.ReplacementLength, replacementText); if (cursorAdjustment != 0) { _current += cursorAdjustment; PlaceCursor(); } completions.ReplacementLength = replacementText.Length; }