IEnumerable <Range> SelectSplit(Range range, SelectSplitDialog.Result result)
        {
            var stack = new Stack <SelectSplitEnum>();

            stack.Push(SelectSplitEnum.None);

            var charValue = new Dictionary <char, SelectSplitEnum>
            {
                ['('] = SelectSplitEnum.Parentheses,
                [')'] = SelectSplitEnum.Parentheses,
                ['['] = SelectSplitEnum.Brackets,
                [']'] = SelectSplitEnum.Brackets,
                ['{'] = SelectSplitEnum.Braces,
                ['}'] = SelectSplitEnum.Braces,
                ['<'] = SelectSplitEnum.LTGT,
                ['>'] = SelectSplitEnum.LTGT,
            };

            var start    = range.Start;
            var pos      = start;
            var matchPos = -1;
            var matchLen = 0;

            while (true)
            {
                var stackTop = stack.Peek();
                if (stackTop.HasFlag(SelectSplitEnum.String))
                {
                    if (pos >= range.End)
                    {
                        throw new Exception("Incomplete string");
                    }
                    else if ((pos + 1 < range.End) && (Data.Data[pos] == '\\') && (!stackTop.HasFlag(SelectSplitEnum.VerbatimString)))
                    {
                        pos += 2;
                    }
                    else if ((pos + 1 < range.End) && (Data.Data[pos] == '"') && (Data.Data[pos + 1] == '"') && (stackTop.HasFlag(SelectSplitEnum.VerbatimString)))
                    {
                        pos += 2;
                    }
                    else if ((pos + 1 < range.End) && (Data.Data[pos] == '{') && (Data.Data[pos + 1] == '{') && (stackTop.HasFlag(SelectSplitEnum.InterpolatedString)))
                    {
                        pos += 2;
                    }
                    else if ((Data.Data[pos] == '{') && (stackTop.HasFlag(SelectSplitEnum.InterpolatedString)))
                    {
                        stack.Push(SelectSplitEnum.Braces);
                        ++pos;
                    }
                    else if (Data.Data[pos] == '"')
                    {
                        stack.Pop();
                        ++pos;
                    }
                    else
                    {
                        ++pos;
                    }
                }
                else
                {
                    if ((stackTop == SelectSplitEnum.None) && (pos > matchPos))
                    {
                        var match = result.Regex.Match(GetString(new Range(pos, range.End)));
                        if (match.Success)
                        {
                            if (match.Length == 0)
                            {
                                throw new Exception("Cannot split on empty selection");
                            }
                            matchPos = match.Index + pos;
                            matchLen = match.Length;
                        }
                        else
                        {
                            matchPos = range.End;
                            matchLen = 0;
                        }
                    }

                    if ((pos >= range.End) || ((pos == matchPos) && (stackTop == SelectSplitEnum.None)))
                    {
                        if (stack.Count != 1)
                        {
                            throw new Exception($"Didn't find close for {stackTop}");
                        }
                        var useStart = start;
                        var useEnd   = pos;
                        if (result.TrimWhitespace)
                        {
                            while ((useStart < pos) && (char.IsWhiteSpace(Data.Data[useStart])))
                            {
                                ++useStart;
                            }
                            while ((useEnd > useStart) && (char.IsWhiteSpace(Data.Data[useEnd - 1])))
                            {
                                --useEnd;
                            }
                        }
                        if ((result.IncludeEmpty) || (useStart != useEnd))
                        {
                            yield return(new Range(useEnd, useStart));
                        }
                        if (pos >= range.End)
                        {
                            break;
                        }
                        if (result.IncludeResults)
                        {
                            yield return(Range.FromIndex(pos, matchLen));
                        }
                        pos  += matchLen;
                        start = pos;
                    }
                    else if (((result.BalanceParens) && (Data.Data[pos] == '(')) || ((result.BalanceBrackets) && (Data.Data[pos] == '[')) || ((result.BalanceBraces) && (Data.Data[pos] == '{')) || ((result.BalanceLTGT) && (Data.Data[pos] == '<')))
                    {
                        stack.Push(charValue[Data.Data[pos++]]);
                    }
                    else if (((result.BalanceParens) && (Data.Data[pos] == ')')) || ((result.BalanceBrackets) && (Data.Data[pos] == ']')) || ((result.BalanceBraces) && (Data.Data[pos] == '}')) || ((result.BalanceLTGT) && (Data.Data[pos] == '>')))
                    {
                        if (charValue[Data.Data[pos]] != stackTop)
                        {
                            throw new Exception($"Didn't find open for {Data.Data[pos]}");
                        }
                        stack.Pop();
                        ++pos;
                    }
                    else if ((result.BalanceStrings) && (Data.Data[pos] == '\"'))
                    {
                        stack.Push(SelectSplitEnum.String);
                        ++pos;
                    }
                    else if ((result.BalanceStrings) && (pos + 1 < range.End) && (Data.Data[pos] == '@') && (Data.Data[pos + 1] == '\"'))
                    {
                        stack.Push(SelectSplitEnum.VerbatimString);
                        pos += 2;
                    }
                    else if ((result.BalanceStrings) && (pos + 1 < range.End) && (Data.Data[pos] == '$') && (Data.Data[pos + 1] == '\"'))
                    {
                        stack.Push(SelectSplitEnum.InterpolatedString);
                        pos += 2;
                    }
                    else if ((result.BalanceStrings) && (pos + 2 < range.End) && (Data.Data[pos] == '$') && (Data.Data[pos + 1] == '@') && (Data.Data[pos + 2] == '\"'))
                    {
                        stack.Push(SelectSplitEnum.InterpolatedVerbatimString);
                        pos += 3;
                    }
                    else
                    {
                        ++pos;
                    }
                }
            }
        }
        void Command_Select_Split(SelectSplitDialog.Result result)
        {
            var indexes = GetFixedExpressionResults <int>(result.Index);

            SetSelections(Selections.AsParallel().AsOrdered().SelectMany((range, index) => SelectSplit(range, result).Skip(indexes[index] == 0 ? 0 : indexes[index] - 1).Take(indexes[index] == 0 ? int.MaxValue : 1)).ToList());
        }