Can I prevent my indent logic from breaking intelliprompt?

SyntaxEditor Web Languages Add-on for WPF Forum

Posted 8 years ago by Craig - Varigence, Inc.
Version: 11.1.0544
Avatar
I'm using the SyntaxEditor with the Web languages add-on and I'm hitting a conflict between a custom behavior I've written and intelliprompt.

The behavior is for indenting. Specifically, let's say I type the element <Toys. When I type > to close the element, I want:

1. The end tag to appear automatically (already works).
2. The end tag to be two lines beneath the start tag so there's an empty line in between.
3. The cursor to be within the empty line in between, and be indented.

So, in the end, it should look like:

<Toys>

</Toys>

with the cursor beneath the 's' in <Toys>.

However, when the indent occurs and then the user presses < (at the new cursor position), a completion list doesn't appear as it should. I've narrowed the problem down to my behavior's use of InsertText to insert the newline. I suspect the intelliprompt logic treats the newline as user input, doesn't find a match, and thus doesn't pop-up on the following keypress of <.

What I'd like to know is:

1. Does the XML add-on have a built in way to provide this style of indenting so I don't need custom logic.
2. If it doesn't, is there a way to insert the new line without interferring with intelliprompt?
3. Do you have any recommendations on how can I improve my behavior's indenting logic?

Thanks,

-Craig

The behavior:

if (e.TextChange.Type == TextChangeTypes.Enter)
{
    var editor = sender as SyntaxEditor;
    if (editor == null)
    {
        return;
    }

    // Notice that the reader is processing the old snapshot.
    // That way, we can see if the cursor is surrounded by matching xml tags on the same line.
    // We can't use e.NewSnapshot since that will include the newline due to pressing Enter.
    var snapshotOffset = new TextSnapshotOffset(e.ChangedSnapshotRange.Snapshot, e.ChangedSnapshotRange.StartOffset);
    var reader = e.OldSnapshot.GetReader(snapshotOffset.Offset);

    if (!reader.GoToPreviousToken())
    {
        return;
    }

    // Ensure the previous token is '>'.
    if (reader.Token.Key != "StartTagEndDelimiter")
    {
        return;
    }

    // Search backward for a start element name
    var elementName = string.Empty;
    var lineIndex = 0;

    var exitLoop = false;
    while (reader.GoToPreviousToken() && !exitLoop)
    {
        switch (reader.Token.Key)
        {
            case "StartTagName":
                elementName = reader.TokenText.Trim();
                lineIndex = reader.Token.StartPosition.Line;
                exitLoop = true;
                break;
            case "StartTagStartDelimiter":
            case "EndTagEndDelimiter":
                return;
        }
    }

    // Ensure that the previous tag has a non empty element name.
    if (string.IsNullOrWhiteSpace(elementName))
    {
        return;
    }

    // Ensure that the previous tag name token is on the same line as the changed snapshot.
    if (lineIndex != e.ChangedSnapshotRange.StartLine.Index)
    {
        return;
    }

    reader.Offset = snapshotOffset.Offset;
    var performSmartIndent = false;

    if (!reader.GoToPreviousToken())
    {
        return;
    }

    // Ensure the next token is '<'.
    if (reader.Token.Key != "StartTagEndDelimiter")
    {
        return;
    }

    exitLoop = false;
    while (reader.GoToNextToken() && !exitLoop)
    {
        switch (reader.Token.Key)
        {
            case "EndTagText":
                if (elementName == reader.TokenText.Trim() && 
                    reader.Token.StartPosition.Line == e.ChangedSnapshotRange.StartLine.Index)
                {
                    // If the elementName matches the token's text
                    // and the token is on the same line as the changed snapshot,
                    // then the tags are <abc></abc> so we can perform a smart indent.
                    performSmartIndent = true;
                    exitLoop = true;
                }
                else
                {
                    return;
                }

                break;
            case "EndTagEndDelimiter":
            case "StartTagStartDelimiter":
                exitLoop = true;
                break;
        }
    }

    if (performSmartIndent)
    {
        var startTagLine = e.ChangedSnapshotRange.StartLine;
        var startLineIndentAmount = startTagLine.Snapshot.Lines[startTagLine.Index].IndentAmount;

        // Insert a new line after the current line.
        editor.Document.InsertText(TextChangeTypes.Indent, startTagLine.EndOffset + 1, "\r\n");

        // Move the caret to the inserted line and indent it.
        var caretPosition = new TextPosition(startTagLine.Index + 1, startLineIndentAmount + editor.Document.TabSize);
        editor.Caret.Position = caretPosition;

        // On the end tag's line, indent so the end tag's indent matches the start tag's indent.
        var endTagLine = editor.Document.CurrentSnapshot.Lines[startTagLine.Index + 2];
        endTagLine.IndentAmount = startLineIndentAmount;
    }
}
[Modified at 07/13/2011 03:26 PM]

Comments (4)

Posted 8 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Craig,

It's hard to say what the problem is without having something to debug. However pressing Enter shouldn't really affect the IntelliPrompt display when next typing a '<'.

Would you like to put together a new simple sample project that shows what you are doing (keep it as minimal as possible) and email that to us? Rename the .zip file extension so it doesn't get spam blocked.

1) We don't have that style of indenting yet, but a smart indent provider is on the TODO list.
2) Per above, hard to say without the sample.
3) Need to try it in a sample.


Actipro Software Support

Posted 8 years ago by Craig - Varigence, Inc.
Avatar
A sample is on its way.

Thanks,

-Craig

[Modified at 07/14/2011 01:31 PM]
Posted 8 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi Craig,

Thanks for the sample. The problem here is that you put the caret in virtual space at the end of your behavior. So when you type '<' it's actually inserting " <" as typed text (with padding spaces beforehand).

If you make this change it works ok:
editor.Document.InsertText(TextChangeTypes.Indent, startTagLine.EndOffset + 1, new string(' ', startLineIndentAmount + editor.Document.TabSize) + "\r\n");


Actipro Software Support

Answer - Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Craig,

Just wanted to follow up and let you know this is in for the next build per this blog post.


Actipro Software Support

The latest build of this product (v2018.1 build 0675) was released 2 months ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.