protected override int InternalExec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) { int hr = OLECMDERR_E_NOTSUPPORTED; if (!WpfConsole.Host.IsCommandEnabled) { return(hr); } // if the console has not been successfully started, do not accept any key inputs if (!WpfConsole.Dispatcher.IsStartCompleted) { return(hr); } // if the console is in the middle of executing a command, do not accept any key inputs if (WpfConsole.Dispatcher.IsExecutingCommand) { return(hr); } if (pguidCmdGroup == VSConstants.GUID_VSStandardCommandSet97) { //Debug.Print("Exec: GUID_VSStandardCommandSet97: {0}", (VSConstants.VSStd97CmdID)nCmdID); switch ((VSConstants.VSStd97CmdID)nCmdID) { case VSConstants.VSStd97CmdID.Paste: if (IsCaretInReadOnlyRegion || IsSelectionReadonly) { hr = VSConstants.S_OK; // eat it } else { PasteText(ref hr); } break; } } else if (pguidCmdGroup == VSConstants.VSStd2K) { //Debug.Print("Exec: VSStd2K: {0}", (VSConstants.VSStd2KCmdID)nCmdID); switch ((VSConstants.VSStd2KCmdID)nCmdID) { case VSConstants.VSStd2KCmdID.TYPECHAR: if (IsCompletionSessionActive) { char ch = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn); if (IsCommitChar(ch)) { if (_completionSession.SelectedCompletionSet.SelectionStatus.IsSelected) { _completionSession.Commit(); } else { _completionSession.Dismiss(); } } } else { if (IsSelectionReadonly) { WpfTextView.Selection.Clear(); } if (IsCaretInReadOnlyRegion) { WpfTextView.Caret.MoveTo(WpfConsole.InputLineExtent.End); } } break; case VSConstants.VSStd2KCmdID.LEFT: case VSConstants.VSStd2KCmdID.LEFT_EXT: case VSConstants.VSStd2KCmdID.LEFT_EXT_COL: case VSConstants.VSStd2KCmdID.WORDPREV: case VSConstants.VSStd2KCmdID.WORDPREV_EXT: case VSConstants.VSStd2KCmdID.WORDPREV_EXT_COL: if (IsCaretAtInputLineStart) { // // Note: This simple implementation depends on Prompt containing a trailing space. // When caret is on the right of InputLineStart, editor will handle it correctly, // and caret won't move left to InputLineStart because of the trailing space. // hr = VSConstants.S_OK; // eat it } break; case VSConstants.VSStd2KCmdID.BOL: case VSConstants.VSStd2KCmdID.BOL_EXT: case VSConstants.VSStd2KCmdID.BOL_EXT_COL: if (IsCaretOnInputLine) { VirtualSnapshotPoint oldCaretPoint = WpfTextView.Caret.Position.VirtualBufferPosition; WpfTextView.Caret.MoveTo(WpfConsole.InputLineStart.Value); WpfTextView.Caret.EnsureVisible(); if ((VSConstants.VSStd2KCmdID)nCmdID == VSConstants.VSStd2KCmdID.BOL) { WpfTextView.Selection.Clear(); } else if ((VSConstants.VSStd2KCmdID)nCmdID != VSConstants.VSStd2KCmdID.BOL) // extend selection { VirtualSnapshotPoint anchorPoint = WpfTextView.Selection.IsEmpty ? oldCaretPoint.TranslateTo(WpfTextView.TextSnapshot) : WpfTextView.Selection.AnchorPoint; WpfTextView.Selection.Select(anchorPoint, WpfTextView.Caret.Position.VirtualBufferPosition); } hr = VSConstants.S_OK; } break; case VSConstants.VSStd2KCmdID.UP: if (!IsCompletionSessionActive) { if (IsCaretInReadOnlyRegion) { ExecuteCommand(VSConstants.VSStd2KCmdID.END); } WpfConsole.NavigateHistory(-1); hr = VSConstants.S_OK; } break; case VSConstants.VSStd2KCmdID.DOWN: if (!IsCompletionSessionActive) { if (IsCaretInReadOnlyRegion) { ExecuteCommand(VSConstants.VSStd2KCmdID.END); } WpfConsole.NavigateHistory(+1); hr = VSConstants.S_OK; } break; case VSConstants.VSStd2KCmdID.RETURN: if (IsCompletionSessionActive) { if (_completionSession.SelectedCompletionSet.SelectionStatus.IsSelected) { _completionSession.Commit(); } else { _completionSession.Dismiss(); } } else if (IsCaretOnInputLine || !IsCaretInReadOnlyRegion) { ExecuteCommand(VSConstants.VSStd2KCmdID.END); ExecuteCommand(VSConstants.VSStd2KCmdID.RETURN); WpfConsole.EndInputLine(); } hr = VSConstants.S_OK; break; case VSConstants.VSStd2KCmdID.TAB: if (!IsCaretInReadOnlyRegion) { if (IsCompletionSessionActive) { _completionSession.Commit(); } else { TriggerCompletion(); } } hr = VSConstants.S_OK; break; case VSConstants.VSStd2KCmdID.CANCEL: if (IsCompletionSessionActive) { _completionSession.Dismiss(); hr = VSConstants.S_OK; } else if (!IsCaretInReadOnlyRegion) { // Delete all text after InputLineStart WpfTextView.TextBuffer.Delete(WpfConsole.AllInputExtent); hr = VSConstants.S_OK; } break; case VSConstants.VSStd2KCmdID.CUTLINE: // clears the console when CutLine shortcut key is pressed, // usually it is Ctrl + L WpfConsole.ClearConsole(); hr = VSConstants.S_OK; break; } } return(hr); }
protected override int InternalExec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) { ThreadHelper.ThrowIfNotOnUIThread(); int hr = OLECMDERR_E_NOTSUPPORTED; if (WpfConsole == null || WpfConsole.Host == null || WpfConsole.Dispatcher == null) { return(hr); } if (!WpfConsole.Host.IsCommandEnabled) { return(hr); } if (!WpfConsole.Dispatcher.IsExecutingReadKey) { // if the console has not been successfully started, do not accept any key inputs, unless // we are in the middle of a ReadKey call. This happens when the execution group policy setting // is set to AllSigned, and PS is asking user to trust the certificate. if (!WpfConsole.Dispatcher.IsStartCompleted) { return(hr); } // if the console is in the middle of executing a command, do not accept any key inputs unless // we are in the middle of a ReadKey call. if (WpfConsole.Dispatcher.IsExecutingCommand) { return(hr); } } if (pguidCmdGroup == VSConstants.GUID_VSStandardCommandSet97) { //Debug.Print("Exec: GUID_VSStandardCommandSet97: {0}", (VSConstants.VSStd97CmdID)nCmdID); switch ((VSConstants.VSStd97CmdID)nCmdID) { case VSConstants.VSStd97CmdID.Paste: if (IsCaretInReadOnlyRegion || IsSelectionReadonly) { hr = VSConstants.S_OK; // eat it } else { PasteText(ref hr); } break; } } else if (pguidCmdGroup == VSConstants.VSStd2K) { //Debug.Print("Exec: VSStd2K: {0}", (VSConstants.VSStd2KCmdID)nCmdID); var commandID = (VSConstants.VSStd2KCmdID)nCmdID; if (WpfConsole.Dispatcher.IsExecutingReadKey) { switch (commandID) { case VSConstants.VSStd2KCmdID.TYPECHAR: case VSConstants.VSStd2KCmdID.BACKSPACE: case VSConstants.VSStd2KCmdID.RETURN: var keyInfo = GetVsKeyInfo(pvaIn, commandID); WpfConsole.Dispatcher.PostKey(keyInfo); break; case VSConstants.VSStd2KCmdID.CANCEL: // Handle ESC WpfConsole.Dispatcher.CancelWaitKey(); break; } hr = VSConstants.S_OK; // eat everything } else { switch (commandID) { case VSConstants.VSStd2KCmdID.TYPECHAR: if (IsCompletionSessionActive) { char ch = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn); if (IsCommitChar(ch)) { if (_completionSession.SelectedCompletionSet.SelectionStatus.IsSelected) { _completionSession.Commit(); } else { _completionSession.Dismiss(); } } } else { if (IsSelectionReadonly) { WpfTextView.Selection.Clear(); } if (IsCaretInReadOnlyRegion) { WpfTextView.Caret.MoveTo(WpfConsole.InputLineExtent.End); } } break; case VSConstants.VSStd2KCmdID.LEFT: case VSConstants.VSStd2KCmdID.LEFT_EXT: case VSConstants.VSStd2KCmdID.LEFT_EXT_COL: case VSConstants.VSStd2KCmdID.WORDPREV: case VSConstants.VSStd2KCmdID.WORDPREV_EXT: case VSConstants.VSStd2KCmdID.WORDPREV_EXT_COL: if (IsCaretAtInputLineStart) { // // Note: This simple implementation depends on Prompt containing a trailing space. // When caret is on the right of InputLineStart, editor will handle it correctly, // and caret won't move left to InputLineStart because of the trailing space. // hr = VSConstants.S_OK; // eat it } break; case VSConstants.VSStd2KCmdID.BOL: case VSConstants.VSStd2KCmdID.BOL_EXT: case VSConstants.VSStd2KCmdID.BOL_EXT_COL: if (IsCaretOnInputLine) { VirtualSnapshotPoint oldCaretPoint = WpfTextView.Caret.Position.VirtualBufferPosition; WpfTextView.Caret.MoveTo(WpfConsole.InputLineStart.Value); WpfTextView.Caret.EnsureVisible(); if ((VSConstants.VSStd2KCmdID)nCmdID == VSConstants.VSStd2KCmdID.BOL) { WpfTextView.Selection.Clear(); } else if ((VSConstants.VSStd2KCmdID)nCmdID != VSConstants.VSStd2KCmdID.BOL) // extend selection { VirtualSnapshotPoint anchorPoint = WpfTextView.Selection.IsEmpty ? oldCaretPoint.TranslateTo( WpfTextView.TextSnapshot) : WpfTextView.Selection.AnchorPoint; WpfTextView.Selection.Select(anchorPoint, WpfTextView.Caret.Position.VirtualBufferPosition); } hr = VSConstants.S_OK; } break; case VSConstants.VSStd2KCmdID.UP: if (!IsCompletionSessionActive) { if (IsCaretInReadOnlyRegion) { ExecuteCommand(VSConstants.VSStd2KCmdID.END); } WpfConsole.NavigateHistory(-1); hr = VSConstants.S_OK; } break; case VSConstants.VSStd2KCmdID.DOWN: if (!IsCompletionSessionActive) { if (IsCaretInReadOnlyRegion) { ExecuteCommand(VSConstants.VSStd2KCmdID.END); } WpfConsole.NavigateHistory(+1); hr = VSConstants.S_OK; } break; case VSConstants.VSStd2KCmdID.RETURN: if (IsCompletionSessionActive) { if (_completionSession.SelectedCompletionSet.SelectionStatus.IsSelected) { _completionSession.Commit(); } else { _completionSession.Dismiss(); } } else if (IsCaretOnInputLine || !IsCaretInReadOnlyRegion) { ExecuteCommand(VSConstants.VSStd2KCmdID.END); ExecuteCommand(VSConstants.VSStd2KCmdID.RETURN); NuGetUIThreadHelper.JoinableTaskFactory .RunAsync(() => EndInputLineAsync(WpfConsole)) .PostOnFailure(nameof(WpfConsoleKeyProcessor)); } hr = VSConstants.S_OK; break; case VSConstants.VSStd2KCmdID.TAB: if (!IsCaretInReadOnlyRegion) { if (IsCompletionSessionActive) { _completionSession.Commit(); } else { NuGetUIThreadHelper.JoinableTaskFactory.RunAsync(async delegate { await TriggerCompletionAsync(); }) .PostOnFailure(nameof(WpfConsoleKeyProcessor)); } } hr = VSConstants.S_OK; break; case VSConstants.VSStd2KCmdID.CANCEL: if (IsCompletionSessionActive) { _completionSession.Dismiss(); hr = VSConstants.S_OK; } else if (!IsCaretInReadOnlyRegion) { // Delete all text after InputLineStart WpfTextView.TextBuffer.Delete(WpfConsole.AllInputExtent); hr = VSConstants.S_OK; } break; case VSConstants.VSStd2KCmdID.CUTLINE: // clears the console when CutLine shortcut key is pressed, // usually it is Ctrl + L WpfConsole.ClearConsole(); hr = VSConstants.S_OK; break; } } } return(hr); }