Quantcast
Channel: Visual Studio Integrate forum
Viewing all articles
Browse latest Browse all 4410

Replacing text in Visual Studio while preserving the caret.

$
0
0

So,


I am writing right now an auto-format functionality for my custom language in Visual Studio. 
It is very similiar to what C# does:

1) If you type "}" or ";" character in editor, it will format the underlying block, eg: each '{', and ';' are on separate lines. 

This is very simple example, but say, this is the source:

if(1){
}
	if(3)
	{
	}

return 4<caret>

Say, your caret is after '4', as soon as you type ';', it will format the code, like so:

if(1)
{ } if(3) { } return 4;<caret>

notice that the first brace went down & the indent level of second IF went to normal. Also notice that the caret is in correct place.


I've implemented the whole functionality, except there is one slight problem:

1) I can not KEEP the caret position on the same token. How exactly do I maintain the caret position on specific token, when usingITextEdit.CreateEdit()

What I have tried:

[1] If I use ITextEdit.Replace and replace everything, caret will be put at the end of the file, which is wrong. I've also tried to set caret directly, usingIWpfTextView.Caret.MoveTo(new place). It works, but it's not part of the "edit". As soon as I use ctrl+z functionality, the caret is all messed up.I don't want to implement some custom caret "history", I want to do it the way it is meant to be.

Now the good thing is, I actually managed to do it, writing kind of "extreme" code to accomplish this, but there's slight problem: my scroll bar resets to zero always, eg vertical scrollOffset=0. No ideas how to get rid of this.


Do you have any suggestions?

using (var edit = _wpfTextView.TextBuffer.CreateEdit())
{
	// if there is no caret,
	// we might as well replace it entirely,
	// as we don't really care?!
	if (_codeFormatterOutput.CurrentCaretLine == null || _codeFormatterOutput.OldCaretLine == null)
	{
		edit.Replace(Span.FromBounds(0, edit.Snapshot.Length), 
				string.Join(Environment.NewLine, _newLines));
		edit.Apply();
		return;
	}

	// step0: delete everything after CARET line
	if (_codeFormatterOutput.OldCaretLine + 1 < _oldLines.Length)
	{
		edit.Delete(
			Span.FromBounds(
				edit.Snapshot.GetLineFromLineNumber(_codeFormatterOutput.OldCaretLine.Value + 1)
					.Start, edit.Snapshot.Length));
	}

	// step1: delete everything BEFORE caret line
	if (_codeFormatterOutput.OldCaretLine > 0)
	{
		edit.Delete(
			Span.FromBounds(0,
				edit.Snapshot.GetLineFromLineNumber(_codeFormatterOutput.OldCaretLine.Value - 1)
					.EndIncludingLineBreak.Position));
	}

	// replace the caret line with correct one.
	edit.Replace(edit.Snapshot.GetLineFromLineNumber(_codeFormatterOutput.OldCaretLine.Value).Extent,
		_newLines[_codeFormatterOutput.CurrentCaretLine.Value]);

	
	// add new lines before caret
	edit.Insert(0,
		string.Join(Environment.NewLine, _newLines.Take(_codeFormatterOutput.CurrentCaretLine.Value)) + Environment.NewLine);

	// add lines after caret.
	edit.Insert(edit.Snapshot.GetLineFromLineNumber(_codeFormatterOutput.OldCaretLine.Value + 1).Start,
		string.Join(Environment.NewLine, _newLines.Skip(_codeFormatterOutput.CurrentCaretLine.Value + 1)));



	edit.Apply();
}





C#/C++ | WPF/DirectShow/OpenGL/Winapi/




Viewing all articles
Browse latest Browse all 4410

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>