//TODO: Copied from VsVimHost public FSharpOption <int> GetNewLineIndent(ITextView textView, ITextSnapshotLine contextLine, ITextSnapshotLine newLine, IVimLocalSettings localSettings) { //if (_vimApplicationSettings.UseEditorIndent) //{ var indent = _smartIndentationService.GetDesiredIndentation(textView, newLine); if (indent.HasValue) { return(FSharpOption.Create(indent.Value)); } else { // If the user wanted editor indentation but the editor doesn't support indentation // even though it proffers an indentation service then fall back to what auto // indent would do if it were enabled (don't care if it actually is) // // Several editors like XAML offer the indentation service but don't actually // provide information. User clearly wants indent there since the editor indent // is enabled. Do a best effort and use Vim style indenting return(FSharpOption.Create(EditUtil.GetAutoIndent(contextLine, localSettings.TabStop))); } //} //return FSharpOption<int>.None; }
public override string GetIndentationString(int lineNumber) { if (lineNumber < 1 || lineNumber > editor.LineCount) { return(""); } var doc = context.AnalysisDocument; if (doc == null) { return(editor.GetLineIndent(lineNumber)); } var snapshot = editor.TextView.TextBuffer.CurrentSnapshot; var caretLine = snapshot.GetLineFromLineNumber(lineNumber - 1); int?indentation = smartIndentationService.GetDesiredIndentation(editor.TextView, caretLine); if (indentation.HasValue && indentation.Value > 0) { return(CalculateIndentationString(indentation.Value)); } var line = editor.GetLine(lineNumber); if (line == null) { return(editor.GetLineIndent(lineNumber)); } try { if (line.Contains(editor.CaretOffset)) { var syntaxRoot = doc.GetSyntaxRootSynchronously(default);
/// <summary> /// Remaps a given x-coordinate to a valid point. If the provided x-coordinate is past the right end of the line, it will /// be clipped to the correct position depending on the virtual space settings. If the ISmartIndent is providing indentation /// settings, the x-coordinate will be changed based on that. /// </summary> private double MapXCoordinate(ITextViewLine textLine, double xCoordinate, bool userSpecifiedXCoordinate) { // if the clicked point is to the right of the text and virtual space is disabled, the coordinate // needs to be fixed if ((xCoordinate > textLine.TextRight) && !this.IsVirtualSpaceOrBoxSelectionEnabled) { double indentationWidth = 0.0; // ask the ISmartIndent to see if any indentation is necessary for empty lines if (textLine.End == textLine.Start) { int?indentation = _smartIndentationService.GetDesiredIndentation(_wpfTextView, textLine.Start.GetContainingLine()); if (indentation.HasValue) { //The indentation specified by the smart indent service is desired column position of the caret. Find out how much virtual space //need to be at the end of the line to satisfy that. //TOOD: _wpfTextView.FormattedLineSource.ColumnWidth instead of 16 indentationWidth = Math.Max(0.0, (((double)indentation.Value) * 16 - textLine.TextWidth)); // if the coordinate is specified by the user and the user has selected a coordinate to the left // of the indentation suggested by ISmartIndent, overrule the ISmartIndent provided value and // do not use any indentation. if (userSpecifiedXCoordinate && (xCoordinate < (textLine.TextRight + indentationWidth))) { indentationWidth = 0.0; } } } xCoordinate = textLine.TextRight + indentationWidth; } return(xCoordinate); }
/// <summary> /// Gets the desired indentation /// </summary> /// <param name="textView">Text view</param> /// <param name="smartIndentationService">Smart indentation service</param> /// <param name="line">Line</param> /// <returns></returns> public static int?GetDesiredIndentation(ITextView textView, ISmartIndentationService smartIndentationService, ITextSnapshotLine line) { if (textView == null) { throw new ArgumentNullException(nameof(textView)); } if (smartIndentationService == null) { throw new ArgumentNullException(nameof(smartIndentationService)); } if (line == null) { throw new ArgumentNullException(nameof(line)); } var indentStyle = textView.Options.GetIndentStyle(); switch (indentStyle) { case IndentStyle.None: return(0); case IndentStyle.Block: return(GetDesiredBlockIndentation(textView, line)); case IndentStyle.Smart: var indentSize = smartIndentationService.GetDesiredIndentation(textView, line); Debug.Assert(indentSize == null || indentSize.Value >= 0); return(indentSize); default: Debug.Fail($"Invalid {nameof(IndentStyle)}: {indentStyle}"); return(null); } }
/// <summary> /// Gets the desired indentation /// </summary> /// <param name="textView">Text view</param> /// <param name="smartIndentationService">Smart indentation service</param> /// <param name="line">Line</param> /// <returns></returns> public static int? GetDesiredIndentation(ITextView textView, ISmartIndentationService smartIndentationService, ITextSnapshotLine line) { if (textView == null) throw new ArgumentNullException(nameof(textView)); if (smartIndentationService == null) throw new ArgumentNullException(nameof(smartIndentationService)); if (line == null) throw new ArgumentNullException(nameof(line)); var indentStyle = textView.Options.GetIndentStyle(); switch (indentStyle) { case IndentStyle.None: return 0; case IndentStyle.Block: return GetDesiredBlockIndentation(textView, line); case IndentStyle.Smart: var indentSize = smartIndentationService.GetDesiredIndentation(textView, line); Debug.Assert(indentSize == null || indentSize.Value >= 0); return indentSize; default: Debug.Fail($"Invalid {nameof(IndentStyle)}: {indentStyle}"); return null; } }
// From https://github.com/dotnet/roslyn/blob/e39a3aeb1185ef0b349cad96a105969423065eac/src/EditorFeatures/Core/Shared/Extensions/ITextViewExtensions.cs#L278 public static int? GetDesiredIndentation(this ITextView textView, ISmartIndentationService smartIndentService, ITextSnapshotLine line) { var pointInView = textView.BufferGraph.MapUpToSnapshot(line.Start, PointTrackingMode.Positive, PositionAffinity.Successor, textView.TextSnapshot); if (!pointInView.HasValue) return null; var lineInView = textView.TextSnapshot.GetLineFromPosition(pointInView.Value.Position); return smartIndentService.GetDesiredIndentation(textView, lineInView); }
// From https://github.com/dotnet/roslyn/blob/e39a3aeb1185ef0b349cad96a105969423065eac/src/EditorFeatures/Core/Shared/Extensions/ITextViewExtensions.cs#L278 public static int?GetDesiredIndentation(this ITextView textView, ISmartIndentationService smartIndentService, ITextSnapshotLine line) { var pointInView = textView.BufferGraph.MapUpToSnapshot(line.Start, PointTrackingMode.Positive, PositionAffinity.Successor, textView.TextSnapshot); if (!pointInView.HasValue) { return(null); } var lineInView = textView.TextSnapshot.GetLineFromPosition(pointInView.Value.Position); return(smartIndentService.GetDesiredIndentation(textView, lineInView)); }
/// <summary> /// Remaps a given x-coordinate to a valid point. If the provided x-coordinate is past the right end of the line, it will /// be clipped to the correct position depending on the virtual space settings. If the ISmartIndent is providing indentation /// settings, the x-coordinate will be changed based on that. /// </summary> public static double MapXCoordinate(this ITextViewLine textLine, ITextView textView, double xCoordinate, ISmartIndentationService smartIndentationService, bool userSpecifiedXCoordinate) { if (textLine == null) { throw new ArgumentNullException(nameof(textLine)); } if (textView == null) { throw new ArgumentNullException(nameof(textView)); } // if the clicked point is to the right of the text and virtual space is disabled, the coordinate // needs to be fixed if ((xCoordinate > textLine.TextRight) && !textView.IsVirtualSpaceOrBoxSelectionEnabled()) { double indentationWidth = 0.0; // ask the ISmartIndent to see if any indentation is necessary for empty lines if (textLine.End == textLine.Start) { int?indentation = smartIndentationService?.GetDesiredIndentation(textView, textLine.Start.GetContainingLine()); if (indentation.HasValue) { //The indentation specified by the smart indent service is desired column position of the caret. Find out how much virtual space //need to be at the end of the line to satisfy that. // TODO: need a way to determine column width in xplat scenarios, bug https://devdiv.visualstudio.com/DevDiv/_workitems/edit/637741 double columnWidth = (textView is ITextView3 textView3) ? textView3.FormattedLineSource.ColumnWidth : throw new NotSupportedException(); indentationWidth = Math.Max(0.0, (((double)indentation.Value) * columnWidth - textLine.TextWidth)); // if the coordinate is specified by the user and the user has selected a coordinate to the left // of the indentation suggested by ISmartIndent, overrule the ISmartIndent provided value and // do not use any indentation. if (userSpecifiedXCoordinate && (xCoordinate < (textLine.TextRight + indentationWidth))) { indentationWidth = 0.0; } } } xCoordinate = textLine.TextRight + indentationWidth; } return(xCoordinate); }
/// <summary> /// Remaps a given x-coordinate to a valid point. If the provided x-coordinate is past the right end of the line, it will /// be clipped to the correct position depending on the virtual space settings. If the ISmartIndent is providing indentation /// settings, the x-coordinate will be changed based on that. /// </summary> public static double MapXCoordinate(this ITextViewLine textLine, ITextView textView, double xCoordinate, ISmartIndentationService smartIndentationService, bool userSpecifiedXCoordinate) { if (textLine == null) { throw new ArgumentNullException(nameof(textLine)); } if (textView == null) { throw new ArgumentNullException(nameof(textView)); } // if the clicked point is to the right of the text and virtual space is disabled, the coordinate // needs to be fixed if ((xCoordinate > textLine.TextRight) && !textView.IsVirtualSpaceOrBoxSelectionEnabled()) { double indentationWidth = 0.0; // ask the ISmartIndent to see if any indentation is necessary for empty lines if (textLine.End == textLine.Start) { int?indentation = smartIndentationService?.GetDesiredIndentation(textView, textLine.Start.GetContainingLine()); if (indentation.HasValue) { //The indentation specified by the smart indent service is desired column position of the caret. Find out how much virtual space //need to be at the end of the line to satisfy that. double columnWidth = (textView.ViewScroller is IViewScroller2 viewScroller) ? viewScroller.ColumnWidth : 7; indentationWidth = Math.Max(0.0, (((double)indentation.Value) * columnWidth - textLine.TextWidth)); // if the coordinate is specified by the user and the user has selected a coordinate to the left // of the indentation suggested by ISmartIndent, overrule the ISmartIndent provided value and // do not use any indentation. if (userSpecifiedXCoordinate && (xCoordinate < (textLine.TextRight + indentationWidth))) { indentationWidth = 0.0; } } } xCoordinate = textLine.TextRight + indentationWidth; } return(xCoordinate); }
/// <summary> /// Indents the line where the caret is currently located. /// </summary> /// <remarks> /// We don't send this command to the editor since smart indentation doesn't work along with /// BufferChanged event. Instead, we need to implement indentation ourselves. We still use /// ISmartIndentProvider provided by the language. /// </remarks> private void IndentCurrentLine(SnapshotPoint caretPosition) { Debug.Assert(_currentLanguageBuffer != null); var caretLine = caretPosition.GetContainingLine(); var indentation = _smartIndenterService.GetDesiredIndentation(_textView, caretLine); // When the user submits via ctrl-enter, the indenter service sometimes // gets confused and maps the subject position after the last newline in // a language buffer to the location *before* the next prompt in the // surface buffer. When this happens, indentation will be 0. Fortunately, // no indentation is required in such cases, so we can just do nothing. if (indentation != null && indentation != 0) { var sourceSpans = GetSourceSpans(caretPosition.Snapshot); var promptIndex = GetPromptIndexForPoint(sourceSpans, caretPosition); var promptSpan = sourceSpans[promptIndex]; Debug.Assert(IsPrompt(promptSpan)); int promptLength = promptSpan.Length; Debug.Assert(promptLength == 2 || promptLength == 0); // Not required, just expected. var adjustedIndentationValue = indentation.GetValueOrDefault() - promptLength; if (caretPosition == caretLine.End) { // create virtual space: _textView.Caret.MoveTo(new VirtualSnapshotPoint(caretPosition, adjustedIndentationValue)); } else { var langCaret = GetPositionInLanguageBuffer(caretPosition); if (langCaret == null) { return; } // insert whitespace indentation: var options = _textView.Options; string whitespace = GetWhiteSpaceForVirtualSpace(adjustedIndentationValue, options.IsConvertTabsToSpacesEnabled() ? default(int?) : options.GetTabSize()); _currentLanguageBuffer.Insert(langCaret.Value, whitespace); } } }
public override string GetIndentationString(int lineNumber) { if (lineNumber < 1 || lineNumber > editor.LineCount) { return(""); } var doc = context.AnalysisDocument; if (doc == null) { return(editor.GetLineIndent(lineNumber)); } var snapshot = editor.TextView.TextBuffer.CurrentSnapshot; var caretLine = snapshot.GetLineFromLineNumber(lineNumber - 1); int?indentation = smartIndentationService.GetDesiredIndentation(editor.TextView, caretLine); if (indentation.HasValue && indentation.Value > 0) { return(CalculateIndentationString(indentation.Value)); } return(editor.GetLineIndent(lineNumber) + CalculateIndentationString(editor.Options.IndentationSize)); }