private static Func <String, int, bool, bool, String> GetPathSuggester(bool EnableFile, bool EnableDirectory, PathString DefaultValue) { return((v, ConfirmedLength, Cycle, CyclePrevious) => { var vConfirmed = v.Substring(0, ConfirmedLength); if (!Cycle && (vConfirmed == "")) { return vConfirmed; } if (vConfirmed == "") { return DefaultValue ?? ""; } PathString ConfirmedPath; PathString ConfirmedParts; try { ConfirmedPath = vConfirmed.AsPath(); if (vConfirmed.EndsWith("\\") || vConfirmed.EndsWith("/")) { ConfirmedParts = ConfirmedPath; } else { var Parts = ConfirmedPath.Parts; if (Parts.Count <= 1) { ConfirmedParts = ""; } else { ConfirmedParts = PathString.Join(Parts.AsEnumerable().Reverse().Skip(1).Reverse()); } } } catch (ArgumentException) { return vConfirmed; } if ((ConfirmedParts != "") && !Directory.Exists(ConfirmedParts)) { return vConfirmed; } if (EnableFile && File.Exists(ConfirmedPath) && !Cycle) { return vConfirmed; } if (EnableDirectory && Directory.Exists(ConfirmedPath) && !Cycle) { return vConfirmed; } var FileSelections = new List <string> { }; if (EnableFile) { try { FileSelections = FileSystemUtils.GetFiles(ConfirmedParts, "*", SearchOption.TopDirectoryOnly).Select(f => f.FileName).ToList(); } catch (UnauthorizedAccessException) { } } var DirectorySelections = new List <string> { }; if (EnableDirectory) { try { DirectorySelections = FileSystemUtils.GetDirectories(ConfirmedParts, "*", SearchOption.TopDirectoryOnly).Select(d => d.FileName).ToList(); } catch (UnauthorizedAccessException) { } } var Selections = FileSelections.Concat(DirectorySelections).Select(s => ConfirmedParts / s).ToList(); String FirstMatched = null; String PreviousMatched = null; bool HasExactMatch = false; //if there is an exact match and in cycle mode, the next or previous match is returned //if there is an exact match and not in cycle mode, the exact match is returned //otherwise, the first match is returned //if there is no match and in cycle mode, the original suggestion is returned //if there is no match and not in cycle mode, the original input is returned foreach (var s in Selections.Where(s => s.ToString().StartsWith(vConfirmed, StringComparison.OrdinalIgnoreCase))) { if (v.Equals(s, StringComparison.OrdinalIgnoreCase)) { if (!Cycle) { return s; } if (CyclePrevious) { return PreviousMatched ?? s; } HasExactMatch = true; continue; } if (FirstMatched == null) { FirstMatched = s; } PreviousMatched = s; if (HasExactMatch) { return s; } } return FirstMatched ?? (Cycle ? v : vConfirmed); }); }