public static CompletionResult processCompletion(@NotNull String typed,
                                                   @NotNull Finder finder,
                                                   @NotNull FileLookup.LookupFilter filter,
                                                   @NotNull Map<String, String> macroMap,
                                                   @Nullable FileLookup.LookupFile preselected) {
    List<FileLookup.LookupFile> macros = new ArrayList<>();
    List<FileLookup.LookupFile> variants = new ArrayList<>();

    MinusculeMatcher matcher = createMatcher(typed);
    for (String eachMacro : macroMap.keySet()) {
      if (matcher.matches(eachMacro)) {
        String eachPath = macroMap.get(eachMacro);
        if (eachPath != null) {
          FileLookup.LookupFile macroFile = finder.find(eachPath);
          if (macroFile != null && macroFile.exists()) {
            macros.add(macroFile);
            variants.add(macroFile);
            macroFile.setMacro(eachMacro);
          }
        }
      }
    }

    String typedText = finder.normalize(typed);

    FileLookup.LookupFile current = getClosestParent(typed, finder);
    boolean currentParentMatch;
    boolean closedPath;
    String effectivePrefix;
    FileLookup.LookupFile currentGrandparent;
    String grandparentPrefix;

    if (current != null) {
      currentParentMatch = SystemInfo.isFileSystemCaseSensitive
                           ? typedText.equals(current.getAbsolutePath())
                           : typedText.equalsIgnoreCase(current.getAbsolutePath());

      closedPath = typed.endsWith(finder.getSeparator()) && typedText.length() > finder.getSeparator().length();
      String currentParentText = current.getAbsolutePath();

      if (!StringUtil.startsWithIgnoreCase(typedText, currentParentText)) {
        return new CompletionResult(variants, macros, List.of(), List.of(), null);
      }

      String prefix = typedText.substring(currentParentText.length());
      if (prefix.startsWith(finder.getSeparator())) {
        prefix = prefix.substring(finder.getSeparator().length());
      }
      else if (typed.endsWith(finder.getSeparator())) {
        prefix = "";
      }

      effectivePrefix = prefix;

      currentGrandparent = current.getParent();

      String gpPrefix = null;
      if (currentGrandparent != null && currentParentMatch && !closedPath) {
        String currentGrandparentText = currentGrandparent.getAbsolutePath();
        if (StringUtil.startsWithConcatenation(typedText, currentGrandparentText, finder.getSeparator())) {
          gpPrefix = currentParentText.substring(currentGrandparentText.length() + finder.getSeparator().length());
        }
      }
      grandparentPrefix = gpPrefix;
    }
    else {
      currentParentMatch = false;
      closedPath = false;
      effectivePrefix = typedText;
      currentGrandparent = null;
      grandparentPrefix = null;
    }

    return ReadAction.compute(new ThrowableComputable<>() {
      @Override
      public CompletionResult compute() throws RuntimeException {
        List<FileLookup.LookupFile> siblings = new ArrayList<>();
        List<FileLookup.LookupFile> kidsAfterSeparator = new ArrayList<>();

        if (current != null) {
          variants.addAll(getMatchingChildren(effectivePrefix, current));

          if (currentParentMatch && !closedPath && !typed.isEmpty()) {
            kidsAfterSeparator.addAll(variants);
          }

          if (grandparentPrefix != null) {
            List<FileLookup.LookupFile> children = getMatchingChildren(grandparentPrefix, currentGrandparent);
            variants.addAll(0, children);
            siblings.addAll(children);
          }
        }

        FileLookup.LookupFile toPreselect = preselected;

        if (toPreselect == null || !variants.contains(toPreselect)) {
          boolean toPreselectFixed = false;
          if (!effectivePrefix.isEmpty()) {
            for (FileLookup.LookupFile each : variants) {
              String eachName = StringUtil.toUpperCase(each.getName());
              if (!eachName.startsWith(effectivePrefix)) continue;
              toPreselect = each;
              toPreselectFixed = true;
              break;
            }

            if (!toPreselectFixed) {
              toPreselect = null;
            }
          }
          else {
            toPreselect = null;
          }

          if (toPreselect == null) {
            if (variants.size() == 1) {
              toPreselect = variants.get(0);
            }
            else if (effectivePrefix.isEmpty()) {
              if (!siblings.isEmpty()) {
                toPreselect = siblings.get(0);
              }
            }

            if (toPreselect == null && !variants.contains(null) && !variants.isEmpty()) {
              toPreselect = variants.get(0);
            }
          }
        }

        if (currentParentMatch && !siblings.isEmpty()) {
          toPreselect = null;
        }

        return new CompletionResult(variants, macros, siblings, kidsAfterSeparator, toPreselect);
      }

      private List<FileLookup.LookupFile> getMatchingChildren(String prefix, FileLookup.LookupFile parent) {
        MinusculeMatcher matcher = createMatcher(prefix);
        return parent.getChildren(file -> !file.equals(current) && filter.isAccepted(file) && matcher.matches(file.getName()));
      }
    });
  }
public static CompletionResult processCompletion(@NotNull String typed,
                                                   @NotNull Finder finder,
                                                   @NotNull FileLookup.LookupFilter filter,
                                                   @NotNull Map<String, String> macroMap,
                                                   @Nullable FileLookup.LookupFile preselected)