public int FormatSpan(IVsTextLines vsTextLines, TextSpan[] ts) { if (ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out var startPos)) && ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out var endPos))) { var textBuffer = vsTextLines.ToITextBuffer(_services); var range = TextRange.FromBounds(startPos, endPos); var snapshot = textBuffer.CurrentSnapshot; var point = snapshot.CreateTrackingPoint(range.End, PointTrackingMode.Positive); var text = snapshot.GetText(range.ToSpan()); var line = snapshot.GetLineFromPosition(range.Start); var lineTail = snapshot.GetText(Span.FromBounds(range.End, line.End)); var formatter = new RangeFormatter(_services); formatter.FormatRange(TextView.ToEditorView(), textBuffer.ToEditorBuffer(), range); // Do not trim whitespace after standalone operators if (IsStandaloneOperator(text) && string.IsNullOrEmpty(lineTail)) { textBuffer.Insert(point.GetPosition(textBuffer.CurrentSnapshot), " "); } } return(VSConstants.S_OK); }
public int FormatSpan(IVsTextLines vsTextLines, TextSpan[] ts) { int hr = VSConstants.S_OK; int startPos = -1; int endPos = -1; if (ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos)) && ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos))) { var textBuffer = vsTextLines.ToITextBuffer(); RangeFormatter.FormatRange(TextView, textBuffer, TextRange.FromBounds(startPos, endPos), REditorSettings.FormatOptions); } return(hr); }
public static int GetPositionOfLineIndex(this IVsTextLines buffer, int iLine, int iIndex) { int piPosition; buffer.GetPositionOfLineIndex(iLine, iIndex, out piPosition); return(piPosition); }
public int FormatSpan(IVsTextLines vsTextLines, TextSpan[] ts) { int hr = VSConstants.S_OK; int startPos = -1; int endPos = -1; if (ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos)) && ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos))) { var textBuffer = vsTextLines.ToITextBuffer(); var range = TextRange.FromBounds(startPos, endPos); // Do not format standalone operators var text = textBuffer.CurrentSnapshot.GetText(range.ToSpan()); if (CanFormat(text)) { RangeFormatter.FormatRange(TextView, textBuffer, range, VsAppShell.Current.GetService <IREditorSettings>().FormatOptions, VsAppShell.Current); } } return(hr); }
public int FormatSpan(IVsTextLines vsTextLines, TextSpan[] ts) { var startPos = -1; var endPos = -1; if (ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos)) && ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos))) { var textBuffer = vsTextLines.ToITextBuffer(_services); var range = TextRange.FromBounds(startPos, endPos); // Do not format standalone operators var text = textBuffer.CurrentSnapshot.GetText(range.ToSpan()); if (CanFormat(text)) { var formatter = new RangeFormatter(_services); formatter.FormatRange(TextView.ToEditorView(), textBuffer.ToEditorBuffer(), range); } } return(VSConstants.S_OK); }
public static List<EditSpan> ReformatCode(IVsTextLines pBuffer, TextSpan span, int tabSize) { string filePath = FilePathUtilities.GetFilePath(pBuffer); // Return dynamic scanner based on file extension List<EditSpan> changeList = new List<EditSpan>(); int nbLines; pBuffer.GetLineCount(out nbLines); string codeToFormat; int lastLine; int lastLineIndex; pBuffer.GetLastLineIndex(out lastLine, out lastLineIndex); pBuffer.GetLineText(0, 0, lastLine, lastLineIndex, out codeToFormat); NShaderScanner shaderScanner = NShaderScannerFactory.GetShaderScanner(filePath); Scanner lexer = shaderScanner.Lexer; lexer.SetSource(codeToFormat, 0); int spanStart; int spanEnd; pBuffer.GetPositionOfLineIndex(span.iStartLine, span.iStartIndex, out spanStart); pBuffer.GetPositionOfLineIndex(span.iEndLine, span.iEndIndex, out spanEnd); int state = 0; int start, end; ShaderToken token = (ShaderToken) lexer.GetNext(ref state, out start, out end); List<int> brackets = new List<int>(); List<int> delimiters = new List<int>(); // !EOL and !EOF int level = 0; int startCopy = 0; int levelParenthesis = 0; while (token != ShaderToken.EOF) { switch (token) { case ShaderToken.LEFT_PARENTHESIS: levelParenthesis++; break; case ShaderToken.RIGHT_PARENTHESIS: levelParenthesis--; if ( levelParenthesis < 0 ) { levelParenthesis = 0; } break; case ShaderToken.LEFT_BRACKET: level++; if (codeToFormat[start] == '{' && start >= spanStart && end <= spanEnd) { Match match = matchBraceStart.Match(codeToFormat, start); StringBuilder codeFormatted = new StringBuilder(); codeFormatted.Append("{\r\n"); int levelToIndentNext = level; if (match.Groups.Count == 2) { string matchStr = match.Groups[1].Value; levelToIndentNext--; } for (int i = 0; i < levelToIndentNext; i++) { for (int j = 0; j < tabSize; j++) { codeFormatted.Append(' '); } } if (match.Groups.Count == 2) { codeFormatted.Append("}\r\n"); } TextSpan editTextSpan = new TextSpan(); pBuffer.GetLineIndexOfPosition(start, out editTextSpan.iStartLine, out editTextSpan.iStartIndex); pBuffer.GetLineIndexOfPosition(startCopy + match.Index + match.Length, out editTextSpan.iEndLine, out editTextSpan.iEndIndex); changeList.Add(new EditSpan(editTextSpan, codeFormatted.ToString())); } break; case ShaderToken.RIGHT_BRACKET: level--; if (level < 0) { level = 0; } brackets.Add(start); break; case ShaderToken.DELIMITER: if (codeToFormat[start] == ';' && start >= spanStart && end <= spanEnd && levelParenthesis == 0) { Match match = matchEndOfStatement.Match(codeToFormat, start); StringBuilder codeFormatted = new StringBuilder(); codeFormatted.Append(";\r\n"); int levelToIndentNext = level; bool isBracketFound = (match.Groups.Count == 2 && match.Groups[1].Value == "}"); if (isBracketFound) { string matchStr = match.Groups[1].Value; levelToIndentNext--; } for (int i = 0; i < levelToIndentNext; i++) { for (int j = 0; j < tabSize; j++) { codeFormatted.Append(' '); } } if (isBracketFound) { codeFormatted.Append("}\r\n"); } TextSpan editTextSpan = new TextSpan(); pBuffer.GetLineIndexOfPosition(start, out editTextSpan.iStartLine, out editTextSpan.iStartIndex); pBuffer.GetLineIndexOfPosition(startCopy + match.Index + match.Length, out editTextSpan.iEndLine, out editTextSpan.iEndIndex); changeList.Add(new EditSpan(editTextSpan, codeFormatted.ToString())); } break; } token = (ShaderToken) lexer.GetNext(ref state, out start, out end); } return changeList; }
public int FormatSpan(IVsTextLines pBuffer, TextSpan[] ts) { MSXML.IXMLDOMNode codeNode, snippetTypes, declarations, imports; int hr; if (ErrorHandler.Failed(hr = _session.GetSnippetNode("CodeSnippet:Code", out codeNode))) { return(hr); } if (ErrorHandler.Failed(hr = _session.GetHeaderNode("CodeSnippet:SnippetTypes", out snippetTypes))) { return(hr); } List <string> declList = new List <string>(); if (ErrorHandler.Succeeded(hr = _session.GetSnippetNode("CodeSnippet:Declarations", out declarations)) && declarations != null) { foreach (MSXML.IXMLDOMNode declType in declarations.childNodes) { var id = declType.selectSingleNode("./CodeSnippet:ID"); if (id != null) { declList.Add(id.text); } } } List <string> importList = new List <string>(); if (ErrorHandler.Succeeded(hr = _session.GetSnippetNode("CodeSnippet:Imports", out imports)) && imports != null) { foreach (MSXML.IXMLDOMNode import in imports.childNodes) { var id = import.selectSingleNode("./CodeSnippet:Namespace"); if (id != null) { importList.Add(id.text); } } } bool surroundsWith = false, surroundsWithStatement = false; foreach (MSXML.IXMLDOMNode snippetType in snippetTypes.childNodes) { if (snippetType.nodeName == "SnippetType") { if (snippetType.text == SurroundsWith) { surroundsWith = true; } else if (snippetType.text == SurroundsWithStatement) { surroundsWithStatement = true; } } } // get the indentation of where we're inserting the code... string baseIndentation = GetBaseIndentation(ts); int startPosition; pBuffer.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPosition); var insertTrackingPoint = _textView.TextBuffer.CurrentSnapshot.CreateTrackingPoint(startPosition, PointTrackingMode.Positive); TextSpan?endSpan = null; using (var edit = _textView.TextBuffer.CreateEdit()) { if (surroundsWith || surroundsWithStatement) { // this is super annoyning... Most languages can do a surround with and $selected$ can be // an empty string and everything's the same. But in Python we can't just have something like // "while True: " without a pass statement. So if we start off with an empty selection we // need to insert a pass statement. This is the purpose of the "SurroundsWithStatement" // snippet type. // // But, to make things even more complicated, we don't have a good indication of what's the // template text vs. what's the selected text. We do have access to the original template, // but all of the values have been replaced with their default values when we get called // here. So we need to go back and re-apply the template, except for the $selected$ part. // // Also, the text has \n, but the inserted text has been replaced with the appropriate newline // character for the buffer. var templateText = codeNode.text.Replace("\n", _textView.Options.GetNewLineCharacter()); foreach (var decl in declList) { string defaultValue; if (ErrorHandler.Succeeded(_session.GetFieldValue(decl, out defaultValue))) { templateText = templateText.Replace("$" + decl + "$", defaultValue); } } templateText = templateText.Replace("$end$", ""); // we can finally figure out where the selected text began witin the original template... int selectedIndex = templateText.IndexOf("$selected$"); if (selectedIndex != -1) { var selection = _textView.Selection; // now we need to get the indentation of the $selected$ element within the template, // as we'll need to indent the selected code to that level. string indentation = GetTemplateSelectionIndentation(templateText, selectedIndex); var start = _selectionStart.GetPosition(_textView.TextBuffer.CurrentSnapshot); var end = _selectionEnd.GetPosition(_textView.TextBuffer.CurrentSnapshot); if (end < start) { // we didn't actually have a selction, and our negative tracking pushed us // back to the start of the buffer... end = start; } var selectedSpan = Span.FromBounds(start, end); if (surroundsWithStatement && String.IsNullOrWhiteSpace(_textView.TextBuffer.CurrentSnapshot.GetText(selectedSpan))) { // we require a statement here and the user hasn't selected any code to surround, // so we insert a pass statement (and we'll select it after the completion is done) edit.Replace(new Span(startPosition + selectedIndex, end - start), "pass"); // Surround With can be invoked with no selection, but on a line with some text. // In that case we need to inject an extra new line. var endLine = _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(end); var endText = endLine.GetText().Substring(end - endLine.Start); if (!String.IsNullOrWhiteSpace(endText)) { edit.Insert(end, _textView.Options.GetNewLineCharacter()); } // we want to leave the pass statement selected so the user can just // continue typing over it... var startLine = _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(startPosition + selectedIndex); _selectEndSpan = true; endSpan = new TextSpan() { iStartLine = startLine.LineNumber, iEndLine = startLine.LineNumber, iStartIndex = baseIndentation.Length + indentation.Length, iEndIndex = baseIndentation.Length + indentation.Length + 4, }; } IndentSpan( edit, indentation, _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(start).LineNumber + 1, // 1st line is already indented _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(end).LineNumber ); } } // we now need to update any code which was not selected that we just inserted. IndentSpan(edit, baseIndentation, ts[0].iStartLine + 1, ts[0].iEndLine); edit.Apply(); } if (endSpan != null) { _session.SetEndSpan(endSpan.Value); } // add any missing imports... AddMissingImports( importList, insertTrackingPoint.GetPoint(_textView.TextBuffer.CurrentSnapshot) ).Wait(); return(hr); }
public int FormatSpan(IVsTextLines pBuffer, TextSpan[] ts) { MSXML.IXMLDOMNode codeNode, snippetTypes, declarations, imports; int hr; if (ErrorHandler.Failed(hr = _session.GetSnippetNode("CodeSnippet:Code", out codeNode))) { return hr; } if (ErrorHandler.Failed(hr = _session.GetHeaderNode("CodeSnippet:SnippetTypes", out snippetTypes))) { return hr; } List<string> declList = new List<string>(); if (ErrorHandler.Succeeded(hr = _session.GetSnippetNode("CodeSnippet:Declarations", out declarations)) && declarations != null) { foreach (MSXML.IXMLDOMNode declType in declarations.childNodes) { var id = declType.selectSingleNode("./CodeSnippet:ID"); if (id != null) { declList.Add(id.text); } } } List<string> importList = new List<string>(); if (ErrorHandler.Succeeded(hr = _session.GetSnippetNode("CodeSnippet:Imports", out imports)) && imports != null) { foreach (MSXML.IXMLDOMNode import in imports.childNodes) { var id = import.selectSingleNode("./CodeSnippet:Namespace"); if (id != null) { importList.Add(id.text); } } } bool surroundsWith = false, surroundsWithStatement = false; foreach (MSXML.IXMLDOMNode snippetType in snippetTypes.childNodes) { if (snippetType.nodeName == "SnippetType") { if (snippetType.text == SurroundsWith) { surroundsWith = true; } else if (snippetType.text == SurroundsWithStatement) { surroundsWithStatement = true; } } } // get the indentation of where we're inserting the code... string baseIndentation = GetBaseIndentation(ts); int startPosition; pBuffer.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPosition); var insertTrackingPoint = _textView.TextBuffer.CurrentSnapshot.CreateTrackingPoint(startPosition, PointTrackingMode.Positive); TextSpan? endSpan = null; using (var edit = _textView.TextBuffer.CreateEdit()) { if (surroundsWith || surroundsWithStatement) { // this is super annoyning... Most languages can do a surround with and $selected$ can be // an empty string and everything's the same. But in Python we can't just have something like // "while True: " without a pass statement. So if we start off with an empty selection we // need to insert a pass statement. This is the purpose of the "SurroundsWithStatement" // snippet type. // // But, to make things even more complicated, we don't have a good indication of what's the // template text vs. what's the selected text. We do have access to the original template, // but all of the values have been replaced with their default values when we get called // here. So we need to go back and re-apply the template, except for the $selected$ part. // // Also, the text has \n, but the inserted text has been replaced with the appropriate newline // character for the buffer. var templateText = codeNode.text.Replace("\n", _textView.Options.GetNewLineCharacter()); foreach (var decl in declList) { string defaultValue; if (ErrorHandler.Succeeded(_session.GetFieldValue(decl, out defaultValue))) { templateText = templateText.Replace("$" + decl + "$", defaultValue); } } templateText = templateText.Replace("$end$", ""); // we can finally figure out where the selected text began witin the original template... int selectedIndex = templateText.IndexOf("$selected$"); if (selectedIndex != -1) { var selection = _textView.Selection; // now we need to get the indentation of the $selected$ element within the template, // as we'll need to indent the selected code to that level. string indentation = GetTemplateSelectionIndentation(templateText, selectedIndex); var start = _selectionStart.GetPosition(_textView.TextBuffer.CurrentSnapshot); var end = _selectionEnd.GetPosition(_textView.TextBuffer.CurrentSnapshot); if (end < start) { // we didn't actually have a selction, and our negative tracking pushed us // back to the start of the buffer... end = start; } var selectedSpan = Span.FromBounds(start, end); if (surroundsWithStatement && String.IsNullOrWhiteSpace(_textView.TextBuffer.CurrentSnapshot.GetText(selectedSpan))) { // we require a statement here and the user hasn't selected any code to surround, // so we insert a pass statement (and we'll select it after the completion is done) edit.Replace(new Span(startPosition + selectedIndex, end - start), "pass"); // Surround With can be invoked with no selection, but on a line with some text. // In that case we need to inject an extra new line. var endLine = _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(end); var endText = endLine.GetText().Substring(end - endLine.Start); if (!String.IsNullOrWhiteSpace(endText)) { edit.Insert(end, _textView.Options.GetNewLineCharacter()); } // we want to leave the pass statement selected so the user can just // continue typing over it... var startLine = _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(startPosition + selectedIndex); _selectEndSpan = true; endSpan = new TextSpan() { iStartLine = startLine.LineNumber, iEndLine = startLine.LineNumber, iStartIndex = baseIndentation.Length + indentation.Length, iEndIndex = baseIndentation.Length + indentation.Length + 4, }; } IndentSpan( edit, indentation, _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(start).LineNumber + 1, // 1st line is already indented _textView.TextBuffer.CurrentSnapshot.GetLineFromPosition(end).LineNumber ); } } // we now need to update any code which was not selected that we just inserted. IndentSpan(edit, baseIndentation, ts[0].iStartLine + 1, ts[0].iEndLine); edit.Apply(); } if (endSpan != null) { _session.SetEndSpan(endSpan.Value); } // add any missing imports... AddMissingImports( importList, insertTrackingPoint.GetPoint(_textView.TextBuffer.CurrentSnapshot) ).Wait(); return hr; }
public int GetPositionOfLineIndex(int iLine, int iIndex, out int piPosition) { return(_textBuffer.GetPositionOfLineIndex(iLine, iIndex, out piPosition)); }
/// <summary> /// Format the content inserted by a code snippet /// </summary> public int FormatSpan(IVsTextLines pBuffer, TextSpan[] ts) { // Example of a snippet template (taken from forprops.snippet and use ... to represent // indent spaces): // // for (var $property$ in $object$) { // ....if ($object$.hasOwnProperty($property$)) { // ........$selected$$end$ // ....} // }; // // Example of code in pBuffer (the for loop is inserted by a forprops snippet): // // var object = { one: 1, two: 2 }; // for (var property in object) { // ....if (object.hasOwnProperty(property)) { // ........ // ....} // }; // // Result examples: // // (1) If indent size = 2: // // var object = { one: 1, two: 2 }; // for (var property in object) { // ..if (object.hasOwnProperty(property)) { // .... // ..} // }; // // (2) If indent size = 2 and OpenBracesOnNewLineForControl = true: // // var object = { one: 1, two: 2 }; // for (var property in object) // { // ..if (object.hasOwnProperty(property)) // ..{ // .... // ..} // }; // Algorithm: The idea is to use Formatting.Formatter to format the inserted content. // However, Formatting.Formatter does not format lines that only contain spaces. For // example, here is how Formatting.Formatter formats the code above: // // var object = { one: 1, two: 2 }; // for (var property in object) { // ..if (object.hasOwnProperty(property)) { // ........ // ..} // }; // // An additional step will be included to ensure such lines are formatted correctly. int baseIndentationLevel = GetViewIndentationLevelAtLine(ts[0].iStartLine); for (int lineNumber = ts[0].iStartLine; lineNumber <= ts[0].iEndLine; ++lineNumber) { string lineContent = _textView.TextBuffer.CurrentSnapshot.GetLineFromLineNumber(lineNumber).GetText(); string indentationString = GetTemplateIndentationString(lineContent); if (indentationString != lineContent) // This means line contains some characters other than spaces { continue; } int newIndentationLevel = baseIndentationLevel + GetTemplateIndentationLevel(indentationString); string newIndentation = _textView.Options.IsConvertTabsToSpacesEnabled() ? new string(' ', newIndentationLevel *_textView.Options.GetIndentSize()) : new string('\t', newIndentationLevel); using (var edit = _textView.TextBuffer.CreateEdit()) { int indendationPos; pBuffer.GetPositionOfLineIndex(lineNumber, 0, out indendationPos); Span bufferIndentationSpan = new Span(indendationPos, indentationString.Length); edit.Replace(bufferIndentationSpan, newIndentation); edit.Apply(); } } // Now that we have handled empty lines, use Formatter to format the inserted content. int startPos = 0, endPos = 0; pBuffer.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos); pBuffer.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos); Formatting.FormattingOptions options = EditFilter.CreateFormattingOptions(_textView.Options, _textView.TextBuffer.CurrentSnapshot); string text = _textView.TextBuffer.CurrentSnapshot.GetText(); EditFilter.ApplyEdits(_textView.TextBuffer, Formatting.Formatter.GetEditsForRange(text, startPos, endPos, options)); return(VSConstants.S_OK); }
public static List <EditSpan> ReformatCode(IVsTextLines pBuffer, TextSpan span, int tabSize) { string filePath = FilePathUtilities.GetFilePath(pBuffer); // Return dynamic scanner based on file extension List <EditSpan> changeList = new List <EditSpan>(); int nbLines; pBuffer.GetLineCount(out nbLines); string codeToFormat; int lastLine; int lastLineIndex; pBuffer.GetLastLineIndex(out lastLine, out lastLineIndex); pBuffer.GetLineText(0, 0, lastLine, lastLineIndex, out codeToFormat); NShaderScanner shaderScanner = NShaderScannerFactory.GetShaderScanner(filePath); Scanner lexer = shaderScanner.Lexer; lexer.SetSource(codeToFormat, 0); int spanStart; int spanEnd; pBuffer.GetPositionOfLineIndex(span.iStartLine, span.iStartIndex, out spanStart); pBuffer.GetPositionOfLineIndex(span.iEndLine, span.iEndIndex, out spanEnd); int state = 0; int start, end; ShaderToken token = (ShaderToken)lexer.GetNext(ref state, out start, out end); List <int> brackets = new List <int>(); List <int> delimiters = new List <int>(); // !EOL and !EOF int level = 0; int startCopy = 0; int levelParenthesis = 0; while (token != ShaderToken.EOF) { switch (token) { case ShaderToken.LEFT_PARENTHESIS: levelParenthesis++; break; case ShaderToken.RIGHT_PARENTHESIS: levelParenthesis--; if (levelParenthesis < 0) { levelParenthesis = 0; } break; case ShaderToken.LEFT_BRACKET: level++; if (codeToFormat[start] == '{' && start >= spanStart && end <= spanEnd) { Match match = matchBraceStart.Match(codeToFormat, start); StringBuilder codeFormatted = new StringBuilder(); codeFormatted.Append("{\r\n"); int levelToIndentNext = level; if (match.Groups.Count == 2) { string matchStr = match.Groups[1].Value; levelToIndentNext--; } for (int i = 0; i < levelToIndentNext; i++) { for (int j = 0; j < tabSize; j++) { codeFormatted.Append(' '); } } if (match.Groups.Count == 2) { codeFormatted.Append("}\r\n"); } TextSpan editTextSpan = new TextSpan(); pBuffer.GetLineIndexOfPosition(start, out editTextSpan.iStartLine, out editTextSpan.iStartIndex); pBuffer.GetLineIndexOfPosition(startCopy + match.Index + match.Length, out editTextSpan.iEndLine, out editTextSpan.iEndIndex); changeList.Add(new EditSpan(editTextSpan, codeFormatted.ToString())); } break; case ShaderToken.RIGHT_BRACKET: level--; if (level < 0) { level = 0; } brackets.Add(start); break; case ShaderToken.DELIMITER: if (codeToFormat[start] == ';' && start >= spanStart && end <= spanEnd && levelParenthesis == 0) { Match match = matchEndOfStatement.Match(codeToFormat, start); StringBuilder codeFormatted = new StringBuilder(); codeFormatted.Append(";\r\n"); int levelToIndentNext = level; bool isBracketFound = (match.Groups.Count == 2 && match.Groups[1].Value == "}"); if (isBracketFound) { string matchStr = match.Groups[1].Value; levelToIndentNext--; } for (int i = 0; i < levelToIndentNext; i++) { for (int j = 0; j < tabSize; j++) { codeFormatted.Append(' '); } } if (isBracketFound) { codeFormatted.Append("}\r\n"); } TextSpan editTextSpan = new TextSpan(); pBuffer.GetLineIndexOfPosition(start, out editTextSpan.iStartLine, out editTextSpan.iStartIndex); pBuffer.GetLineIndexOfPosition(startCopy + match.Index + match.Length, out editTextSpan.iEndLine, out editTextSpan.iEndIndex); changeList.Add(new EditSpan(editTextSpan, codeFormatted.ToString())); } break; } token = (ShaderToken)lexer.GetNext(ref state, out start, out end); } return(changeList); }
public int FormatSpan(IVsTextLines vsTextLines, TextSpan[] ts) { int hr = VSConstants.S_OK; int startPos = -1; int endPos = -1; if (ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos)) && ErrorHandler.Succeeded(vsTextLines.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos))) { var textBuffer = vsTextLines.ToITextBuffer(); RangeFormatter.FormatRange(TextView, textBuffer, TextRange.FromBounds(startPos, endPos), REditorSettings.FormatOptions, VsAppShell.Current); } return hr; }
/// <summary> /// Format the content inserted by a code snippet /// </summary> public int FormatSpan(IVsTextLines pBuffer, TextSpan[] ts) { // Example of a snippet template (taken from forprops.snippet and use ... to represent // indent spaces): // // for (var $property$ in $object$) { // ....if ($object$.hasOwnProperty($property$)) { // ........$selected$$end$ // ....} // }; // // Example of code in pBuffer (the for loop is inserted by a forprops snippet): // // var object = { one: 1, two: 2 }; // for (var property in object) { // ....if (object.hasOwnProperty(property)) { // ........ // ....} // }; // // Result examples: // // (1) If indent size = 2: // // var object = { one: 1, two: 2 }; // for (var property in object) { // ..if (object.hasOwnProperty(property)) { // .... // ..} // }; // // (2) If indent size = 2 and OpenBracesOnNewLineForControl = true: // // var object = { one: 1, two: 2 }; // for (var property in object) // { // ..if (object.hasOwnProperty(property)) // ..{ // .... // ..} // }; // Algorithm: The idea is to use Formatting.Formatter to format the inserted content. // However, Formatting.Formatter does not format lines that only contain spaces. For // example, here is how Formatting.Formatter formats the code above: // // var object = { one: 1, two: 2 }; // for (var property in object) { // ..if (object.hasOwnProperty(property)) { // ........ // ..} // }; // // An additional step will be included to ensure such lines are formatted correctly. int baseIndentationLevel = GetViewIndentationLevelAtLine(ts[0].iStartLine); for (int lineNumber = ts[0].iStartLine; lineNumber <= ts[0].iEndLine; ++lineNumber) { string lineContent = _textView.TextBuffer.CurrentSnapshot.GetLineFromLineNumber(lineNumber).GetText(); string indentationString = GetTemplateIndentationString(lineContent); if (indentationString != lineContent) { // This means line contains some characters other than spaces continue; } int newIndentationLevel = baseIndentationLevel + GetTemplateIndentationLevel(indentationString); string newIndentation = _textView.Options.IsConvertTabsToSpacesEnabled() ? new string(' ', newIndentationLevel * _textView.Options.GetIndentSize()) : new string('\t', newIndentationLevel); using (var edit = _textView.TextBuffer.CreateEdit()) { int indendationPos; pBuffer.GetPositionOfLineIndex(lineNumber, 0, out indendationPos); Span bufferIndentationSpan = new Span(indendationPos, indentationString.Length); edit.Replace(bufferIndentationSpan, newIndentation); edit.Apply(); } } // Now that we have handled empty lines, use Formatter to format the inserted content. int startPos = 0, endPos = 0; pBuffer.GetPositionOfLineIndex(ts[0].iStartLine, ts[0].iStartIndex, out startPos); pBuffer.GetPositionOfLineIndex(ts[0].iEndLine, ts[0].iEndIndex, out endPos); Formatting.FormattingOptions options = EditFilter.CreateFormattingOptions(_textView.Options, _textView.TextBuffer.CurrentSnapshot); string text = _textView.TextBuffer.CurrentSnapshot.GetText(); EditFilter.ApplyEdits(_textView.TextBuffer, Formatting.Formatter.GetEditsForRange(text, startPos, endPos, options)); return VSConstants.S_OK; }