private bool FindMatchingPair(BraceKind brace, SnapshotPoint position, int direction, out SnapshotSpan leftSpan, out SnapshotSpan rightSpan) { leftSpan = new SnapshotSpan(position, position); rightSpan = leftSpan; var buffer = PythonTextBufferInfo.ForBuffer(_site, position.Snapshot.TextBuffer); if (buffer == null) { return(false); } if (!(buffer.GetTokenAtPoint(position)?.Trigger ?? TokenTriggers.None).HasFlag(TokenTriggers.MatchBraces)) { return(false); } var snapshot = position.Snapshot; int depth = 0; foreach (var token in (direction > 0 ? buffer.GetTokensForwardFromPoint(position) : buffer.GetTokensInReverseFromPoint(position - 1))) { if (!token.Trigger.HasFlag(TokenTriggers.MatchBraces)) { continue; } var tokenSpan = token.ToSnapshotSpan(snapshot); var txt = tokenSpan.GetText(); var kind = GetBraceKind(txt); if (kind == BraceKind.None) { return(false); } if (kind == brace) { if (txt.IsCloseGrouping()) { depth -= direction; } else { depth += direction; } } if (depth == 0) { leftSpan = tokenSpan; rightSpan = new SnapshotSpan(snapshot, position - 1, 1); return(true); } } return(false); }
public int?GetDesiredIndentation(ITextSnapshotLine line) { if (_pyService.LangPrefs.IndentMode == vsIndentStyle.vsIndentStyleSmart) { return(AutoIndent.GetLineIndentation(PythonTextBufferInfo.ForBuffer(_pyService.Site, line.Snapshot.TextBuffer), line, _textView)); } else { return(null); } }
public bool TryCreateContext(ITextView textView, SnapshotPoint openingPoint, char openingBrace, char closingBrace, out IBraceCompletionContext context) { var bi = PythonTextBufferInfo.ForBuffer(Site, openingPoint.Snapshot.TextBuffer); if (IsValidBraceCompletionContext(bi, openingPoint, openingBrace)) { context = new BraceCompletionContext(); return(true); } else { context = null; return(false); } }
public PythonTextBufferInfo GetBufferInfo(ITextBuffer textBuffer) { return(PythonTextBufferInfo.ForBuffer(this, textBuffer)); }
public bool TryTriggerExpansion(ITextView textView) { if (textView == null) { throw new ArgumentNullException(nameof(textView)); } if (_vsExpansionMgr == null) { return(false); } if (!textView.Selection.IsEmpty || textView.Caret.Position.BufferPosition <= 0) { return(false); } var snapshot = textView.TextBuffer.CurrentSnapshot; var caretSpan = new SnapshotSpan(snapshot, new Span(textView.Caret.Position.BufferPosition.Position - 1, 1)); var bufferInfo = PythonTextBufferInfo.ForBuffer(_site, textView.TextBuffer); var tokens = bufferInfo.GetTrackingTokens(caretSpan); if (!tokens.Any()) { return(false); } var token = tokens.First(); var tokenSpan = token.ToSnapshotSpan(snapshot); if (tokenSpan.End.Position != caretSpan.End.Position) { // Match C# behavior and only trigger snippet // if caret is at the end of an identifier. Otherwise, // a TAB should be inserted even if the token matches // a snippet shortcut. return(false); } var text = tokenSpan.GetText(); var textSpan = new TextSpan[1]; textSpan[0].iStartLine = tokenSpan.Start.GetContainingLine().LineNumber; textSpan[0].iStartIndex = tokenSpan.Start.Position - tokenSpan.Start.GetContainingLine().Start; textSpan[0].iEndLine = tokenSpan.End.GetContainingLine().LineNumber; textSpan[0].iEndIndex = tokenSpan.End.Position - tokenSpan.End.GetContainingLine().Start; var client = GetOrCreateExpansionClient(textView); int hr = _vsExpansionMgr.GetExpansionByShortcut( client, CommonGuidList.guidPythonLanguageServiceGuid, text, _editorAdaptersFactoryService.GetViewAdapter(textView), textSpan, 1, out string expansionPath, out string title ); if (ErrorHandler.Succeeded(hr)) { // hr may be S_FALSE if there are multiple expansions, // so we don't want to InsertNamedExpansion yet. VS will // pop up a selection dialog in this case. if (hr == VSConstants.S_OK) { return(ErrorHandler.Succeeded(client.InsertNamedExpansion(title, expansionPath, textSpan[0]))); } return(true); } return(false); }