public static List <GotoRange> GetPositionsData(IEnumerable <string> strs, GotoType gotoType)
            {
                void setFile(GotoRange pd, string value) => pd.File                    = value;
                void setStartLine(GotoRange pd, string value) => pd.Start.Line         = int.Parse(value) - 1;
                void setEndLine(GotoRange pd, string value) => pd.End.Line             = int.Parse(value) - 1;
                void setStartIndex(GotoRange pd, string value) => pd.Start.Index       = int.Parse(value) - 1;
                void setEndIndex(GotoRange pd, string value) => pd.End.Index           = int.Parse(value) - 1;
                void setStartColumn(GotoRange pd, string value) => pd.Start.Column     = int.Parse(value) - 1;
                void setEndColumn(GotoRange pd, string value) => pd.End.Column         = int.Parse(value) - 1;
                void setStartPosition(GotoRange pd, string value) => pd.Start.Position = int.Parse(value);
                void setEndPosition(GotoRange pd, string value) => pd.End.Position     = int.Parse(value);

                string regexPattern;
                List <Action <GotoRange, string> > actions;

                switch (gotoType)
                {
                case GotoType.Line:
                    regexPattern = @"^(?:((?:[a-z]:)?[\w\s,\\.-]+):)?(\d+)(?:-(\d+))?|((?:[a-z]:)?[\w\s,\\.-]+)\((\d+)\)$";
                    actions      = new List <Action <GotoRange, string> > {
                        setFile, setStartLine, setEndLine, setFile, setStartLine
                    };
                    break;

                case GotoType.Column:
                    regexPattern = @"^(?:(?:((?:[a-z]:)?[\w\s,\\.-]+):)?(\d+):)?(\d+)(?:-(?:(\d+):)?(\d+))?$";
                    actions      = new List <Action <GotoRange, string> > {
                        setFile, setStartLine, setStartColumn, setEndLine, setEndColumn
                    };
                    break;

                case GotoType.Index:
                    regexPattern = @"^(?:(?:((?:[a-z]:)?[\w\s,\\.-]+):)?(\d+):)?(\d+)(?:-(?:(\d+):)?(\d+))?|((?:[a-z]:)?[\w\s,\\.-]+)\((\d+),(\d+),(\d+),(\d+)\)$";
                    actions      = new List <Action <GotoRange, string> > {
                        setFile, setStartLine, setStartIndex, setEndLine, setEndIndex, setFile, setStartLine, setStartIndex, setEndLine, setEndIndex
                    };
                    break;

                case GotoType.Position:
                    regexPattern = @"^(?:((?:[a-z]:)?[\w\s,\\.-]+):)?(\d+)(?:-(\d+))?$";
                    actions      = new List <Action <GotoRange, string> > {
                        setFile, setStartPosition, setEndPosition
                    };
                    break;

                default: throw new Exception("Invalid gototype");
                }
                var regex = new Regex(regexPattern, RegexOptions.IgnoreCase);

                var result = new List <GotoRange>();

                foreach (var str in strs)
                {
                    var pd    = new GotoRange();
                    var match = regex.Match(str);
                    if (!match.Success)
                    {
                        throw new Exception($"Invalid location: {str} ({gotoType})");
                    }
                    for (var ctr = 0; ctr < actions.Count; ++ctr)
                    {
                        if (match.Groups[ctr + 1].Success)
                        {
                            actions[ctr](pd, match.Groups[ctr + 1].Value);
                        }
                    }
                    result.Add(pd);
                }

                return(result);
            }
        void Command_Position_Goto(GotoType gotoType, bool selecting, PositionGotoDialog.Result result)
        {
            var values = GotoRange.GetPositionsData(GetVariableExpressionResults <string>(result.Expression), gotoType);

            if (!values.Any())
            {
                return;
            }

            var hasFiles = values.First().File != null;

            if (values.Any(x => (x.File != null) != hasFiles))
            {
                throw new Exception("Either all locations must have files or none");
            }

            var valuesByFile = new List <List <GotoRange> >();
            var fileMap      = new Dictionary <string, List <GotoRange> >(StringComparer.OrdinalIgnoreCase);

            foreach (var value in values)
            {
                List <GotoRange> list;
                if (result.OpenFilesOnce)
                {
                    var key = value.File ?? "";
                    if (!fileMap.ContainsKey(key))
                    {
                        fileMap[key] = list = new List <GotoRange>();
                        valuesByFile.Add(list);
                    }
                    else
                    {
                        list = fileMap[key];
                    }
                }
                else
                {
                    list = new List <GotoRange>();
                    valuesByFile.Add(list);
                }
                list.Add(value);
            }

            if (hasFiles)
            {
                var invalidFiles = valuesByFile.Select(list => list.First().File).NonNull().Where(file => !File.Exists(file)).ToList();
                if (invalidFiles.Any())
                {
                    throw new Exception($"The following files could not be found: {string.Join("\n", invalidFiles)}");
                }
            }

            var active = new HashSet <TextEditor>();

            foreach (var list in valuesByFile)
            {
                var useTE = list.First().File == null ? this : TabsParent.Add(list.First().File);
                active.Add(useTE);

                var sels      = useTE.Selections.ToList();
                var positions = list;

                if ((sels.Count == 0) && ((gotoType == GotoType.Line) || (gotoType == GotoType.Position)))
                {
                    sels.Add(useTE.BeginRange);
                }
                if (sels.Count == 1)
                {
                    sels = sels.Resize(positions.Count, sels[0]).ToList();
                }
                if (positions.Count == 1)
                {
                    positions = positions.Expand(sels.Count, positions[0]).ToList();
                }
                if (positions.Count != sels.Count)
                {
                    throw new Exception("Expression count doesn't match selection count");
                }

                useTE.SetSelections(sels.AsParallel().AsOrdered().Select((range, ctr) => positions[ctr].GetRange(useTE, range, selecting)).ToList());
            }

            if (hasFiles)
            {
                foreach (var item in TabsParent.Items)
                {
                    item.Active = active.Contains(item);
                }
                TabsParent.TopMost = active.First();
            }
        }