private void init(@NotNull Predicate<? super Macro> filter, @Nullable Map<String, String> userMacros) {
    super.init();

    setTitle(IdeCoreBundle.message("title.macros"));
    setOKButtonText(IdeCoreBundle.message("button.insert"));

    List<Macro> macros = ContainerUtil.sorted(ContainerUtil.filter(MacroManager.getInstance().getMacros(),
                                              macro -> MacroFilter.GLOBAL.accept(macro) && filter.test(macro)),
    new Comparator<>() {
      @Override
      public int compare(Macro macro1, Macro macro2) {
        String name1 = macro1.getName();
        String name2 = macro2.getName();
        if (!StringUtil.startsWithChar(name1, '/')) {
          name1 = ZERO + name1;
        }
        if (!StringUtil.startsWithChar(name2, '/')) {
          name2 = ZERO + name2;
        }
        return name1.compareToIgnoreCase(name2);
      }

      private static final String ZERO = new String(new char[]{0});
    });

    if (userMacros != null && !userMacros.isEmpty()) {
      for (Map.Entry<String, String> macro : userMacros.entrySet()) {
        myMacrosModel.addElement(new EntryWrapper(macro));
      }
    }
    Item firstMacro = null;
    for (Macro macro : macros) {
      final Item element = new MacroWrapper(macro);
      if (firstMacro == null) {
        firstMacro = element;
      }
      myMacrosModel.addElement(element);
    }

    final Item finalFirstMacro = firstMacro;
    myMacrosList.setCellRenderer(new GroupedItemsListRenderer<>(new ListItemDescriptorAdapter<>() {
      @Override
      public String getTextFor(Item value) {
        return value.toString(); //NON-NLS
      }

      @Override
      public boolean hasSeparatorAboveOf(Item value) {
        return value == finalFirstMacro;
      }
    }));

    addListeners();
    if (!myMacrosModel.isEmpty()) {
      myMacrosList.setSelectedIndex(0);
    }
    else {
      setOKActionEnabled(false);
    }
  }
private void init(@NotNull Predicate<? super Macro> filter, @Nullable Map<String, String> userMacros)