/// <summary> /// Creates a new comment line based on the position of the caret and Doxygen configuration. /// </summary> /// <param name="currentLine">Current line for reference.</param> private void NewCommentLine() { ThreadHelper.ThrowIfNotOnUIThread(); int lineNumber = m_textView.Caret.Position.BufferPosition.GetContainingLine().LineNumber; string currentLine = m_textView.TextSnapshot.GetLineFromLineNumber(lineNumber).GetText(); string startSpaces = currentLine.Replace(currentLine.TrimStart(), ""); string endSpaces = currentLine.Replace(currentLine.TrimEnd(), ""); // Try to also guess proper indentation level based on the current line. int extraIndent = 0; int i = lineNumber; string loopLine = currentLine; while (!loopLine.StartsWith("/*!") || !loopLine.StartsWith("/**")) { if (m_regexTagSection.IsMatch(loopLine)) { extraIndent = m_config.TagIndentation; break; } --i; if (i < 0 || i > m_textView.TextSnapshot.LineCount - 1) { break; } loopLine = m_textView.TextSnapshot.GetLineFromLineNumber(i).GetText().TrimStart(); } TextSelection ts = m_dte.ActiveDocument.Selection as TextSelection; ts.DeleteLeft(endSpaces.Length); if (currentLine.EndsWith("*/")) { ts.MoveToLineAndOffset(ts.CurrentLine, currentLine.Length - 1); } else { ts.MoveToLineAndOffset(ts.CurrentLine, currentLine.Length + 1); } // TODO: This adds trailing space. Get rid of it similarly to SmartIndent(). ts.Insert(m_generator.GenerateTagStartLine(startSpaces) + new string(' ', extraIndent)); }
internal void Restore() { if (topWasActivePoint) { selection.MoveToLineAndOffset(bottomLine, bottomLineOffset); selection.MoveToLineAndOffset(topLine, topLineOffset, true); } else { selection.MoveToLineAndOffset(topLine, topLineOffset); selection.MoveToLineAndOffset(bottomLine, bottomLineOffset, true); } }
private void UpdateCallback(object sender, EventArgs e) { ThreadHelper.ThrowIfNotOnUIThread(); DTE dte = ServiceProvider.GetServiceAsync(typeof(DTE)).Result as DTE; if (dte == null) { return; } TextSelection section = dte.ActiveDocument.Selection as TextSelection; // 光标移动至第一行第一列 section.MoveToLineAndOffset(1, 1); bool result = section.FindText("database", (int)vsFindOptions.vsFindOptionsRegularExpression); if (!result) { section.SelectAll(); section.Delete(); } else { //需要添加此操作,否则不会替换成功 section.SelectAll(); section.Text = ""; } }
/// <summary> /// This function is the callback used to execute the command when the menu item is clicked. /// See the constructor to see how the menu item is associated with this function using /// OleMenuCommandService service and MenuCommand class. /// </summary> /// <param name="sender">Event sender.</param> /// <param name="e">Event args.</param> private void Execute(object sender, EventArgs e) { // Verify the current thread is the UI thread. ThreadHelper.ThrowIfNotOnUIThread(); string name = FormatXmlCommand.environment.ActiveDocument.FullName; string extension = Path.GetExtension(FormatXmlCommand.environment.ActiveDocument.FullName).ToUpperInvariant(); if (FormatXmlCommand.XmlExtensions.Contains(extension)) { // Get the selected text from the environment and make a note of where we are in the document. TextSelection selection = FormatXmlCommand.environment.ActiveDocument.Selection as TextSelection; int line = selection.ActivePoint.Line; int offset = selection.ActivePoint.LineCharOffset; // Get the start end points (round down and up to the start of a line). EditPoint startPoint = selection.AnchorPoint.CreateEditPoint(); startPoint.StartOfDocument(); // The initial endpoint is one line below the start. EditPoint endPoint = selection.ActivePoint.CreateEditPoint(); endPoint.EndOfDocument(); // This will replace the XML in the current module with the scrubbed and beautified XML. startPoint.ReplaceText( endPoint, FormatXmlCommand.ScrubDocument(startPoint.GetText(endPoint), extension), (int)(vsEPReplaceTextOptions.vsEPReplaceTextNormalizeNewlines | vsEPReplaceTextOptions.vsEPReplaceTextTabsSpaces)); // There will likely be some dramatic changes to the format of the document. This will restore the cursor to where it was in the // document before we beautified it. selection.MoveToLineAndOffset(line, offset); } }
/// <summary> /// Tries to do smart indentation based on the current position of the caret. /// </summary> /// <returns>If smart indentation was performed. Otherwise false.</returns> private bool TrySmartIndent() { ThreadHelper.ThrowIfNotOnUIThread(); // Try to indent intelligently to correct location based on the previous line. TextSelection ts = m_dte.ActiveDocument.Selection as TextSelection; string prevLine = ts.ActivePoint.CreateEditPoint().GetLines(ts.ActivePoint.Line - 1, ts.ActivePoint.Line); bool success = m_generator.GenerateIndentation(ts.ActivePoint.LineCharOffset, prevLine, out int newOffset); if (success) { // If we're at the end of the line, we should just move the caret. This ensures that the editor doesn't // commit any trailing spaces unless user writes something after the indentation. if (ts.ActivePoint.LineCharOffset > ts.ActivePoint.LineLength) { ts.MoveToLineAndOffset(ts.ActivePoint.Line, newOffset); } else { // Otherwise add indentation in the middle of the line. ts.Insert(new string(' ', newOffset - ts.ActivePoint.LineCharOffset)); } } return(success); }
/// <summary> /// Navigates to defect occurence in code editor /// </summary> /// <param name="sender">Sender</param> /// <param name="arguments">Event arguments</param> public void Navigate(object sender, EventArgs arguments) { Task task = sender as Task; if (task == null) { throw new ArgumentException("sender parm cannot be null"); } if (string.IsNullOrEmpty(task.Document)) { return; } var dte = (DTE)serviceProvider.GetService(typeof(DTE)); var activeDocument = dte.ActiveDocument; if (activeDocument == null || !PathUtils.AreEquals(activeDocument.FullName, task.Document)) { VsShellUtilities.OpenDocument(serviceProvider, task.Document); activeDocument = dte.ActiveDocument; } TextSelection textSelection = activeDocument.Selection as TextSelection; textSelection.MoveToLineAndOffset(task.Line + 1, 1); }
void MoveTo(string fileName,int line,int column) { if (File.Exists(fileName)) { try { OpenFile(fileName); TextSelection ts = m_dte.ActiveDocument.Selection as TextSelection; TextDocument textDoc = ts.Parent; if (line > textDoc.EndPoint.Line) { line = textDoc.EndPoint.Line; column = 1; } if (ts != null && line > 0 && textDoc != null) { ts.MoveToLineAndOffset(line,column); } } catch (Exception) { Logger.Debug("Go to page fail."); } } }
/// <summary> /// Invokes the editor for the specified Gallio test. /// </summary> /// <param name="uiBlob">Identifies the Project/Item blob to be displayed.</param> /// <param name="test">The test that the editor is being invoked for.</param> public void InvokeEditor(UIBlob uiBlob, ITestElement test) { if (!TipShellExtension.IsInitialized) { return; } GallioTestElement gallioTest = test as GallioTestElement; if (gallioTest != null) { if (gallioTest.Path == null) { ErrorDialog.Show(NativeWindow.FromHandle((IntPtr)dte.MainWindow.HWnd), Properties.Resources.UnknownTestCodeLocationCaption, Properties.Resources.UnknownTestCodeLocation, ""); } else { Window window = dte.OpenFile(EnvDTE.Constants.vsViewKindCode, gallioTest.Path); TextSelection selection = window.Selection as TextSelection; if (gallioTest.Line != 0) { if (selection != null) { selection.MoveToLineAndOffset(gallioTest.Line, Math.Max(1, gallioTest.Column), false); } } window.Activate(); } } }
internal bool markType(Lookup lookup, Projects projects) { foreach (Project p in projects) { try { if (p.CodeModel != null) { CodeClass2 codeClass = (CodeClass2)p.CodeModel.CodeTypeFromFullName(lookup.typeName); if (codeClass != null) { try { object test = codeClass.ProjectItem; dte.Documents.Open(codeClass.ProjectItem.get_FileNames(0), "Auto", false); TextSelection textSelection = (TextSelection)dte.ActiveDocument.Selection; textSelection.MoveToLineAndOffset(codeClass.StartPoint.Line, codeClass.StartPoint.LineCharOffset, false); dte.MainWindow.Activate(); log(String.Format(Context.LOG_INFO + "Method {0} not found but type {1} -> marking type", lookup.methodName, lookup.typeName)); return(true); } catch (System.Runtime.InteropServices.COMException) { } } } } catch (NotImplementedException) { } catch (Exception e) { log(Context.LOG_ERROR + e.ToString()); } } log(Context.LOG_WARN + "Could not find the Type \"" + lookup.typeName + "\"!"); return(false); }
private void Activate(Window editorWindow, TextSelection editorSelection, IList <CodeFunction> methods, int line, int lineCharOffset) { if (methods != null && methods.Count > 0) { foreach (CodeFunction m in methods) { if (string.Compare(m.Name, methodName, true) == 0) { line = m.StartPoint.Line; lineCharOffset = m.StartPoint.LineCharOffset; break; } } } // execute default action or create location description: if (autoExecute) { editorSelection.MoveToLineAndOffset(line, lineCharOffset, false); editorWindow.Visible = true; } else { activationData = new ActivationDataEventArgs(editorWindow, editorSelection, line, lineCharOffset); } }
/// <summary> /// Creates a new comment line based on the position of the caret and Doxygen configuration. /// </summary> /// <param name="currentLine">Current line for reference.</param> private void NewCommentLine(string currentLine) { ThreadHelper.ThrowIfNotOnUIThread(); string startSpaces = currentLine.Replace(currentLine.TrimStart(), ""); string endSpaces = currentLine.Replace(currentLine.TrimEnd(), ""); TextSelection ts = m_dte.ActiveDocument.Selection as TextSelection; // Try to also guess proper indentation level based on the current line. int oldLine = ts.ActivePoint.Line; int oldOffset = ts.ActivePoint.LineCharOffset; int extraIndent = 0; while (!currentLine.StartsWith("/*!")) { if (m_regexTagSection.IsMatch(currentLine)) { extraIndent = m_configService.Config.TagIndentation; break; } ts.LineUp(); currentLine = ts.ActivePoint.CreateEditPoint().GetLines(ts.ActivePoint.Line, ts.ActivePoint.Line + 1); currentLine = currentLine.TrimStart(); } // Remove extra spaces from the previous line and add tag start line. ts.MoveToLineAndOffset(oldLine, oldOffset); ts.DeleteLeft(endSpaces.Length); // TODO: This adds trailing space. Get rid of it similarly to SmartIndent(). ts.Insert(m_generator.GenerateTagStartLine(startSpaces) + new string(' ', extraIndent)); }
public void MoveActivePoint(int Line, int Offset, bool Extend = false) { var activeDocument = dte.ActiveDocument; TextSelection textSelection = activeDocument.Selection as TextSelection; textSelection.MoveToLineAndOffset(Line + 1, Offset, Extend); }
/// <summary> /// Opens file and moves caret to specific line and offset /// </summary> /// <param name="filePath">File Path</param> /// <param name="lineNumber">Line Number</param> /// <param name="offset">Offset</param> public void OpenDocumentAndMoveCaret(string filePath, int lineNumber, int offset) { Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread(); if (OpenDocument(filePath)) { TextSelection sel = (TextSelection)_dte.ActiveDocument.Selection; sel.MoveToLineAndOffset(lineNumber, offset); } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Moves the up before comment. /// </summary> /// <param name="sel">The sel.</param> /// ------------------------------------------------------------------------------------ private void MoveUpBeforeComment(TextSelection sel) { TextRanges textRanges = null; for (; true;) { if (sel.FindPattern("\\<summary\\>|/// ---", (int)(vsFindOptions.vsFindOptionsBackwards | vsFindOptions.vsFindOptionsRegularExpression), ref textRanges)) { // GhostDoc messes up dashed lines from inherited comments from base class, // so delete those if (sel.Text.StartsWith("/// ---")) { sel.EndOfLine(true); sel.WordRight(true, 1); sel.Delete(1); } else if (sel.Text.StartsWith("<summary>")) { while (true) { sel.MoveToLineAndOffset(sel.ActivePoint.Line - 1, 1, false); sel.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, false); sel.EndOfLine(true); if (!sel.Text.StartsWith("///")) { if (sel.Text.Length > 0) { // there is a non-empty comment line. We want to start at the end // of it sel.EndOfLine(false); } else { sel.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, false); } break; } // GhostDoc messes up dashed lines from inherited comments from base class, // so delete those if (sel.Text.StartsWith("/// -----")) { sel.WordRight(true, 1); sel.Delete(1); } } return; } } else { return; } } }
/// <summary>mark the method and bring the Visual Studio on front</summary> /// <param term='codeFunction'>is the right codeFunction element to the searched method</param> /// <param name="methodString">name of the method</param> internal void markMethod(CodeFunction codeFunction) { dte.Documents.Open(codeFunction.ProjectItem.get_FileNames(0), "Auto", false); TextSelection textSelection = (TextSelection)dte.ActiveDocument.Selection; textSelection.MoveToLineAndOffset(codeFunction.StartPoint.Line, codeFunction.StartPoint.LineCharOffset, false); TextRanges textRanges = null; string pattern = @"[:b]<{" + codeFunction.Name + @"}>[:b(\n]"; if (textSelection.FindPattern(pattern, (int)vsFindOptions.vsFindOptionsRegularExpression, ref textRanges)) { TextRange r = textRanges.Item(2); textSelection.MoveToLineAndOffset(r.StartPoint.Line, r.StartPoint.LineCharOffset, false); textSelection.MoveToLineAndOffset(r.EndPoint.Line, r.EndPoint.LineCharOffset, true); } dte.MainWindow.Activate(); }
public void Seek(long offset, SeekOrigin origin) { long lineNumber = offset; if (origin == SeekOrigin.Current) { lineNumber += _selection.CurrentLine; } _selection.MoveToLineAndOffset((int)lineNumber, 0, false); }
public CodeVariable GetVariable(FileLinePositionSpan location) { m_textSelection.MoveToLineAndOffset(location.StartLinePosition.Line + this.StartLineNumber - 1, 1); m_textSelection.SelectLine(); CodeVariable var = (CodeVariable)m_textSelection.ActivePoint.get_CodeElement( vsCMElement.vsCMElementVariable); return(var); }
private static void SelectInnerDefinition(TextSelection selection, TextDocument document) { EditPoint pt = document.CreateEditPoint(); int startPos = selection.ActivePoint.Line; int currentLine = startPos; bool IsCssRule(int lineNum) { string line = pt.GetLines(lineNum, lineNum + 1); // We reached the edge of element styles definition. if (line.Contains('}') || line.Contains('{')) { return(false); } // Current line does not contain any CSS rules, break to support invalid/incomplete files. if (!line.Contains(':')) { return(false); } return(true); } // Find the start of styles definition block. while (IsCssRule(currentLine) && currentLine-- > 0) { ; } selection.MoveToLineAndOffset(currentLine + 1, 1, false); currentLine = startPos; // Find the end of styles definition block. while (IsCssRule(currentLine) && ++currentLine < document.EndPoint.Line) { ; } selection.MoveToLineAndOffset(currentLine, 1, true); }
void onShowInAtlas(object[] param) { Document doc = m_applicationObject.ActiveDocument; TextSelection ts = doc.Selection as TextSelection; int lineOffset = ts.AnchorPoint.LineCharOffset; int lineNum = ts.AnchorPoint.Line; ts.SelectLine(); string lineText = ts.Text; ts.MoveToLineAndOffset(lineNum, lineOffset); Regex rx = new Regex(@"\b(?<word>\w+)\b", RegexOptions.Compiled | RegexOptions.IgnoreCase); MatchCollection matches = rx.Matches(lineText); // Report on each match. string token = null; foreach (Match match in matches) { string word = match.Groups["word"].Value; int startIndex = match.Index; int endIndex = startIndex + word.Length - 1; int lineIndex = lineOffset - 1; if (startIndex <= lineIndex && endIndex + 1 >= lineIndex) { token = word; break; } } if (token != null) { string docPath = doc.FullName; m_socket.remoteCall("showInAtlas", new object[] { token, "*", docPath, lineNum }); } // TextDocument txtDoc = doc.Object("TextDocument") as TextDocument; // ProjectItem projectItem = doc.ProjectItem; // FileCodeModel fileCodeModel = projectItem.FileCodeModel; // // if (true || fileCodeModel.Language == CodeModelLanguageConstants.vsCMLanguageCSharp) // { // EnvDTE.TextSelection txtSelection = m_applicationObject.ActiveDocument.Selection as EnvDTE.TextSelection; // CodeElement codeEmelemt = null; // try // { // codeEmelemt = fileCodeModel.CodeElementFromPoint(txtSelection.TopPoint, vsCMElement.vsCMElementFunction); // string codeName = codeEmelemt.Name; // } // catch { } // } }
/*************************************************************************** * exec */ /** * Retrieves the selected block of text and replaces it with the result of a * call to <c>convertBlock</c>. * * @param sender Command object. ***************************************************************************/ public override void exec(object sender, EventArgs e) { /*----------------------------------------*/ /* Get the document and selection. Indent */ /* offset is current caret position. */ /*----------------------------------------*/ Document doc = app.ActiveDocument; TextSelection select = (TextSelection)doc.Selection; VirtualPoint top = select.TopPoint; VirtualPoint bottom = select.BottomPoint; int indent = select.CurrentColumn - 1; /*--------------------------------------------*/ /* Set edit points at the start and end of */ /* the lines where selection starts and ends. */ /*--------------------------------------------*/ EditPoint ep1 = top.CreateEditPoint(); EditPoint ep2 = bottom.CreateEditPoint(); ep1.MoveToLineAndOffset(top.Line, 1); ep2.MoveToLineAndOffset(bottom.Line, bottom.LineLength + 1); /*---------------------------------------*/ /* Convert the block from the content of */ /* the start and end line of selection. */ /*---------------------------------------*/ string block = convertBlock(ep1.GetText(ep2), indent); if (block != null) { /*------------------------------------*/ /* Open an undo context if none open. */ /*------------------------------------*/ UndoContext undo = app.UndoContext; if (!undo.IsOpen) { undo.Open(GetType().Name, false); } /*----------------------------------------------------------*/ /* Replace the selected block, move the caret to the indent */ /* position on the last line, and close the Undo Context. */ /*----------------------------------------------------------*/ ep1.Delete(ep2); ep1.Insert(block); select.MoveToLineAndOffset(ep1.Line, indent + 1, false); undo.Close(); } }
public static string GetTextBetweenCurPosToLine(this TextSelection selection, int to_lineNum, bool moveToEndOfDoc = true) { ThreadHelper.ThrowIfNotOnUIThread(); selection.MoveToLineAndOffset(to_lineNum, 1, Extend: true); string result = selection.Text; if (moveToEndOfDoc) { selection.EndOfDocument(); } return(result); }
public Bookmark GotoBookmark(int number) { var bookmark = _Bookmarks[number]; if(bookmark == null) return null; var row = _Bookmarks[number].GetRow(_Buffer); TextSelection selection = _DTE2.ActiveDocument.Selection; int column = selection.ActivePoint.DisplayColumn; selection.StartOfDocument(); selection.MoveToLineAndOffset(row, column); return _Bookmarks[number]; }
public static void ExtendToFullLine(this TextSelection selection) { var line1 = selection.TopLine; var line2 = selection.BottomLine; if (selection.IsEmpty || !selection.BottomPoint.AtStartOfLine) { line2 += 1; } if (line2 > selection.Parent.EndPoint.Line) { selection.Parent.EndPoint.CreateEditPoint().Insert("\r\n"); } selection.GotoLine(line1); selection.MoveToLineAndOffset(line2, 1, true); }
/// <summary> /// Show selected project file /// </summary> /// <param name="file"></param> /// <param name="row"></param> /// <param name="column"></param> /// <param name="length"></param> /// <returns></returns> private bool ShowProblemFile(string file, int row, int column, int length) { FileInfo fileInfo = new FileInfo(file); if (fileInfo.Exists) { try { _applicationObject.ItemOperations.OpenFile(file, EnvDTEConstants.vsViewKindCode); _applicationObject.ActiveDocument.Activate(); TextSelection selection = (TextSelection)_applicationObject.ActiveDocument.Selection; try { selection.MoveToLineAndOffset(row, column, false); selection.CharRight(true, length); } catch (ArgumentException ex) { if (IsJavaScriptFile(fileInfo)) { string errMsg = "“This plugin does not support showing results in a compressed min.js file. \n" + "To view the full results, please navigate to the Checkmarx results viewer."; TopMostMessageBox.Show(errMsg); return(true); } } return(true); } catch (Exception ex) { Logger.Create().Error(ex.ToString()); TopMostMessageBox.Show(ex.Message); } } return(false); }
private bool NavigateToFileInVisualStudio(string path, int lineNumber, int columnNumber) { path = Path.GetFullPath(path); var logger = NullLogger.Instance; IVisualStudio visualStudio = visualStudioManager.GetVisualStudio(VisualStudioVersion.Any, true, logger); if (visualStudio == null) { return(false); } visualStudio.Call(dte => { Window window = OpenFile(dte, path); if (window == null) { window = FindFileInSolution(dte, path); } TextSelection selection = window.Selection as TextSelection; if (lineNumber != 0) { if (selection != null) { selection.MoveToLineAndOffset(lineNumber, Math.Max(1, columnNumber), false); } } window.Activate(); window.Visible = true; }); visualStudio.BringToFront(); return(true); }
bool TryToMoveTo(string fileName,int line,string searchToken) { if (!File.Exists(fileName)) { return(false); } try { OpenFile(fileName); TextSelection ts = m_dte.ActiveDocument.Selection as TextSelection; TextDocument textDoc = ts.Parent; if (ts != null && textDoc != null && line >= textDoc.StartPoint.Line && line <= textDoc.EndPoint.Line) { ts.GotoLine(line,true); var lineStr = ts.Text; var formatStr = string.Format(@"\b{0}\b",searchToken); var matches = Regex.Matches(lineStr,formatStr,RegexOptions.ExplicitCapture); int column = -1; foreach (Match nextMatch in matches) { column = nextMatch.Index + 1; break; } if (column == -1) { return(false); } ts.MoveToLineAndOffset(line,column,false); } } catch (Exception e) { return(false); } return(true); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Moves the down after comment. /// </summary> /// <param name="sel">The sel.</param> /// ------------------------------------------------------------------------------------ private void MoveDownAfterComment(TextSelection sel) { // Go to the beginning of the line and move down until we find a line that doesn't // start with ///. while (true) { sel.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, false); sel.EndOfLine(true); if (!sel.Text.StartsWith("///")) { break; } // GhostDoc messes up dashed lines from inherited comments from base class, // so delete those if (sel.Text.StartsWith("/// -----")) { sel.WordRight(true, 1); sel.Delete(1); sel.LineUp(false, 1); } sel.MoveToLineAndOffset(sel.ActivePoint.Line + 1, 1, false); } }
public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) { try { if (VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider)) { return(m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut)); } // make a copy of this so we can look at it after forwarding some commands uint commandID = nCmdID; char typedChar = char.MinValue; // make sure the input is a char before getting it if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR) { typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn); } if (m_dte != null) { string currentLine = m_textView.TextSnapshot.GetLineFromPosition( m_textView.Caret.Position.BufferPosition.Position).GetText(); // check for the Javadoc slash and two asterisk pattern while compensating for visual studio's block comment closing generation if (typedChar == '*' && currentLine.Trim() == "/**/") { // Calculate how many spaces string spaces = currentLine.Replace(currentLine.TrimStart(), ""); TextSelection ts = m_dte.ActiveDocument.Selection as TextSelection; //Remember where the cursor was when command was triggered int oldLine = ts.ActivePoint.Line; int oldOffset = ts.ActivePoint.LineCharOffset; ts.LineDown(); ts.EndOfLine(); ts.SelectLine(); //Detect and skip over Unreal Engine Function Macros string trimmedFuncLine = ts.Text.Trim(); if (trimmedFuncLine != "" && trimmedFuncLine.StartsWith("UFUNCTION(")) { ts.EndOfLine(); } else { ts.MoveToLineAndOffset(oldLine, oldOffset); ts.LineDown(); ts.EndOfLine(); } CodeElement codeElement = null; FileCodeModel fcm = m_dte.ActiveDocument.ProjectItem.FileCodeModel; if (fcm != null) { codeElement = fcm.CodeElementFromPoint(ts.ActivePoint, vsCMElement.vsCMElementFunction); } if (codeElement != null && codeElement is CodeFunction) { CodeFunction function = codeElement as CodeFunction; StringBuilder sb = new StringBuilder("*"); bool isNoArgsNoReturn = true; foreach (CodeElement child in codeElement.Children) { CodeParameter parameter = child as CodeParameter; if (parameter != null) { sb.AppendFormat("\r\n" + spaces + " * @param {0} ", parameter.Name); isNoArgsNoReturn = false; } } if (function.Type.AsString != "void") { isNoArgsNoReturn = false; if (function.Type.AsString == "bool") { sb.AppendFormat("\r\n" + spaces + " * @return true \r\n" + spaces + " * @return false "); } else { sb.AppendFormat("\r\n" + spaces + " * @return "); } } //If function has a return type or parameters then we generate them and return, otherwise we skip to generate a single line comment if (!isNoArgsNoReturn) { sb.Insert(1, "\r\n" + spaces + " * "); sb.AppendFormat("\r\n" + spaces + " "); ts.MoveToLineAndOffset(oldLine, oldOffset); ts.Insert(sb.ToString()); ts.MoveToLineAndOffset(oldLine, oldOffset); ts.LineDown(); ts.EndOfLine(); return(VSConstants.S_OK); } } //For variables and void functions with no parameters we can do a single line comment ts.MoveToLineAndOffset(oldLine, oldOffset); ts.Insert("* "); ts.MoveToLineAndOffset(oldLine, oldOffset + 2); return(VSConstants.S_OK); } else if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN) { //Get text on current line before and after cursor TextSelection ts = m_dte.ActiveDocument.Selection as TextSelection; int oldLine = ts.ActivePoint.Line; int oldOffset = ts.ActivePoint.LineCharOffset; ts.EndOfLine(true); string afterCursor = ts.Text; ts.MoveToLineAndOffset(oldLine, oldOffset); ts.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn, true); string beforeCursor = ts.Text; string beforeCursorTrimmed = beforeCursor.TrimStart(); ts.MoveToLineAndOffset(oldLine, oldOffset); // Calculate how many spaces string spaces = beforeCursorTrimmed == "" ? beforeCursor : beforeCursor.Replace(beforeCursorTrimmed, ""); bool hasAsteriskBeforeCursor = beforeCursorTrimmed == "" ? false : beforeCursorTrimmed.StartsWith("* "); bool hasBlockTerminatorAfterCursor = afterCursor == "" ? false : afterCursor.EndsWith("*/"); bool hasBlockTerminatorDirectlyAfterCursor = hasBlockTerminatorAfterCursor && afterCursor.Trim() == "*/"; //Add a space to maintain correct asterisk alignment if needed if (beforeCursorTrimmed != "" && beforeCursorTrimmed.StartsWith("/*")) { hasAsteriskBeforeCursor = true; spaces += " "; } if (hasAsteriskBeforeCursor) { ts.Insert("\r\n" + spaces); if (!hasBlockTerminatorAfterCursor) { ts.Insert("* "); } else if (hasBlockTerminatorDirectlyAfterCursor) { ts.Delete(afterCursor.Length); ts.Insert("*/"); ts.MoveToLineAndOffset(ts.ActivePoint.Line, ts.ActivePoint.LineCharOffset - 2); } return(VSConstants.S_OK); } else if (hasBlockTerminatorAfterCursor) { ts.Insert("* \r\n" + spaces); if (hasBlockTerminatorDirectlyAfterCursor) { ts.Delete(afterCursor.Length); ts.Insert("*/"); ts.MoveToLineAndOffset(ts.ActivePoint.Line, ts.ActivePoint.LineCharOffset - 2); } return(VSConstants.S_OK); } } } // pass along the command so the char is added to the buffer return(m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut)); } catch { } return(VSConstants.E_FAIL); }
public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) { try { if (VsShellUtilities.IsInAutomationFunction(m_provider.ServiceProvider)) { return(m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut)); } // make a copy of this so we can look at it after forwarding some commands uint commandID = nCmdID; char typedChar = char.MinValue; // make sure the input is a char before getting it if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.TYPECHAR) { typedChar = (char)(ushort)Marshal.GetObjectForNativeVariant(pvaIn); } // check for the triple slash if (typedChar == '/' && m_dte != null) { string currentLine = m_textView.TextSnapshot.GetLineFromPosition( m_textView.Caret.Position.BufferPosition.Position).GetText(); if ((currentLine + "/").Trim() == "///") { // Calculate how many spaces string spaces = currentLine.Replace(currentLine.TrimStart(), ""); TextSelection ts = m_dte.ActiveDocument.Selection as TextSelection; int oldLine = ts.ActivePoint.Line; int oldOffset = ts.ActivePoint.LineCharOffset; ts.LineDown(); ts.EndOfLine(); CodeElement codeElement = null; FileCodeModel fcm = m_dte.ActiveDocument.ProjectItem.FileCodeModel; if (fcm != null) { codeElement = fcm.CodeElementFromPoint(ts.ActivePoint, vsCMElement.vsCMElementFunction); } if (codeElement != null && codeElement is CodeFunction) { CodeFunction function = codeElement as CodeFunction; StringBuilder sb = new StringBuilder("/ <summary>\r\n" + spaces + "/// \r\n" + spaces + "/// </summary>"); foreach (CodeElement child in codeElement.Children) { CodeParameter parameter = child as CodeParameter; if (parameter != null) { sb.AppendFormat("\r\n" + spaces + "/// <param name=\"{0}\"></param>", parameter.Name); } } if (function.Type.AsString != "void") { sb.AppendFormat("\r\n" + spaces + "/// <returns></returns>"); } ts.MoveToLineAndOffset(oldLine, oldOffset); ts.Insert(sb.ToString()); ts.MoveToLineAndOffset(oldLine, oldOffset); ts.LineDown(); ts.EndOfLine(); return(VSConstants.S_OK); } else { ts.MoveToLineAndOffset(oldLine, oldOffset); ts.Insert("/ <summary>\r\n" + spaces + "/// \r\n" + spaces + "/// </summary>"); ts.MoveToLineAndOffset(oldLine, oldOffset); ts.LineDown(); ts.EndOfLine(); return(VSConstants.S_OK); } } } if (m_session != null && !m_session.IsDismissed) { // check for a commit character if (nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN || nCmdID == (uint)VSConstants.VSStd2KCmdID.TAB || typedChar == '>') { // check for a selection // if the selection is fully selected, commit the current session if (m_session.SelectedCompletionSet.SelectionStatus.IsSelected) { string selectedCompletion = m_session.SelectedCompletionSet.SelectionStatus.Completion.DisplayText; m_session.Commit(); TextSelection ts = m_dte.ActiveDocument.Selection as TextSelection; switch (selectedCompletion) { case "<!-->": ts.CharLeft(false, 3); break; case "<![CDATA[>": ts.CharLeft(false, 3); break; case "<c>": ts.CharLeft(false, 4); break; case "<code>": ts.CharLeft(false, 7); break; case "<example>": ts.CharLeft(false, 10); break; case "<exception>": ts.CharLeft(false, 14); break; case "<include>": ts.CharLeft(false, 21); break; case "<list>": ts.CharLeft(false, 7); break; case "<para>": ts.CharLeft(false, 7); break; case "<param>": ts.CharLeft(false, 10); break; case "<paramref>": ts.CharLeft(false, 13); break; case "<permission>": ts.CharLeft(false, 15); break; case "<remarks>": ts.CharLeft(false, 10); break; case "<returns>": ts.CharLeft(false, 10); break; case "<see>": ts.CharLeft(false, 3); break; case "<seealso>": ts.CharLeft(false, 3); break; case "<typeparam>": ts.CharLeft(false, 14); break; case "<typeparamref>": ts.CharLeft(false, 3); break; case "<value>": ts.CharLeft(false, 8); break; default: break; } // also, don't add the character to the buffer return(VSConstants.S_OK); } else { // if there is no selection, dismiss the session m_session.Dismiss(); } } } else { if (pguidCmdGroup == VSConstants.VSStd2K && nCmdID == (uint)VSConstants.VSStd2KCmdID.RETURN) { string currentLine = m_textView.TextSnapshot.GetLineFromPosition( m_textView.Caret.Position.BufferPosition.Position).GetText(); if (currentLine.TrimStart().StartsWith("///")) { TextSelection ts = m_dte.ActiveDocument.Selection as TextSelection; string spaces = currentLine.Replace(currentLine.TrimStart(), ""); ts.Insert("\r\n" + spaces + "/// "); return(VSConstants.S_OK); } } } // pass along the command so the char is added to the buffer int retVal = m_nextCommandHandler.Exec(ref pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); if (typedChar == '<') { string currentLine = m_textView.TextSnapshot.GetLineFromPosition( m_textView.Caret.Position.BufferPosition.Position).GetText(); if (currentLine.TrimStart().StartsWith("///")) { if (m_session == null || m_session.IsDismissed) // If there is no active session, bring up completion { if (this.TriggerCompletion()) { m_session.SelectedCompletionSet.SelectBestMatch(); m_session.SelectedCompletionSet.Recalculate(); return(VSConstants.S_OK); } } } } else if ( commandID == (uint)VSConstants.VSStd2KCmdID.BACKSPACE || commandID == (uint)VSConstants.VSStd2KCmdID.DELETE || char.IsLetter(typedChar)) { if (m_session != null && !m_session.IsDismissed) // the completion session is already active, so just filter { m_session.SelectedCompletionSet.SelectBestMatch(); m_session.SelectedCompletionSet.Recalculate(); return(VSConstants.S_OK); } } return(retVal); } catch { } return(VSConstants.E_FAIL); }
/// ------------------------------------------------------------------------------------ /// <summary> /// Moves the down after comment. /// </summary> /// <param name="sel">The sel.</param> /// ------------------------------------------------------------------------------------ private void MoveDownAfterComment(TextSelection sel) { // Go to the beginning of the line and move down until we find a line that doesn't // start with ///. while (true) { sel.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, false); sel.EndOfLine(true); if (!sel.Text.StartsWith("///")) break; // GhostDoc messes up dashed lines from inherited comments from base class, // so delete those if (sel.Text.StartsWith("/// -----")) { sel.WordRight(true, 1); sel.Delete(1); sel.LineUp(false, 1); } sel.MoveToLineAndOffset(sel.ActivePoint.Line + 1, 1, false); } }
private void DoFormat(bool selected) { if (_dte == null || _dte.ActiveDocument == null) { return; } string text = ""; string initIndent = ""; EditPoint sp; EditPoint sd; if (selected) { TextSelection sel = (TextSelection)_dte.ActiveDocument.Selection; sp = sel.TopPoint.CreateEditPoint(); sd = sel.BottomPoint.CreateEditPoint(); sel.MoveToLineAndOffset(sp.Line, 1); sel.MoveToLineAndOffset(sd.Line, 1, true); sel.EndOfLine(true); sp = sel.TopPoint.CreateEditPoint(); sd = sel.BottomPoint.CreateEditPoint(); text = sel.Text; foreach (var ch in text) { if (ch != ' ' && ch != '\t') { break; } initIndent += ch; } } else { TextDocument doc = (TextDocument)_dte.ActiveDocument.Object("TextDocument"); sp = doc.StartPoint.CreateEditPoint(); sd = doc.EndPoint.CreateEditPoint(); text = sp.GetText(sd); } if (String.IsNullOrEmpty(text)) { return; } string eol = GetEol(text); int lang = GetLanguage(); int sizeOut = 0; int sizeMsg = 0; if (NativeMethods.DoFormatter(lang, text, null, ref sizeOut, null, ref sizeMsg, 0, eol, initIndent)) { StringBuilder textOut = new StringBuilder(sizeOut); StringBuilder textMsg = new StringBuilder(sizeMsg); if (NativeMethods.DoFormatter(lang, text, textOut, ref sizeOut, textMsg, ref sizeMsg, 0, eol, initIndent)) { ShowOutput(textMsg.ToString()); sp.ReplaceText(sd, textOut.ToString(), (int)vsEPReplaceTextOptions.vsEPReplaceTextKeepMarkers); } } }
/// ------------------------------------------------------------------------------------ /// <summary> /// Moves the up before comment. /// </summary> /// <param name="sel">The sel.</param> /// ------------------------------------------------------------------------------------ private void MoveUpBeforeComment(TextSelection sel) { TextRanges textRanges = null; for (; true; ) { if (sel.FindPattern("\\<summary\\>|/// ---", (int)(vsFindOptions.vsFindOptionsBackwards | vsFindOptions.vsFindOptionsRegularExpression), ref textRanges)) { // GhostDoc messes up dashed lines from inherited comments from base class, // so delete those if (sel.Text.StartsWith("/// ---")) { sel.EndOfLine(true); sel.WordRight(true, 1); sel.Delete(1); } else if (sel.Text.StartsWith("<summary>")) { while (true) { sel.MoveToLineAndOffset(sel.ActivePoint.Line - 1, 1, false); sel.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, false); sel.EndOfLine(true); if (!sel.Text.StartsWith("///")) { if (sel.Text.Length > 0) { // there is a non-empty comment line. We want to start at the end // of it sel.EndOfLine(false); } else sel.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText, false); break; } // GhostDoc messes up dashed lines from inherited comments from base class, // so delete those if (sel.Text.StartsWith("/// -----")) { sel.WordRight(true, 1); sel.Delete(1); } } return; } } else return; } }