diff --git a/platform/platform-impl/src/com/intellij/help/impl/KeymapGenerator.kt b/platform/platform-impl/src/com/intellij/help/impl/KeymapGenerator.kt index 930cfe78197e..962f7185a293 100644 --- a/platform/platform-impl/src/com/intellij/help/impl/KeymapGenerator.kt +++ b/platform/platform-impl/src/com/intellij/help/impl/KeymapGenerator.kt @@ -1,114 +1,104 @@ -// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -package com.intellij.help.impl; +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.help.impl -import com.google.common.collect.Sets; -import com.intellij.openapi.actionSystem.ActionManager; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.Shortcut; -import com.intellij.openapi.actionSystem.ex.ActionManagerEx; -import com.intellij.openapi.application.ApplicationStarter; -import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.application.ex.ApplicationInfoEx; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.keymap.Keymap; -import com.intellij.openapi.keymap.KeymapUtil; -import com.intellij.openapi.keymap.ex.KeymapManagerEx; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import com.intellij.openapi.actionSystem.Shortcut +import com.intellij.openapi.actionSystem.ex.ActionManagerEx +import com.intellij.openapi.application.ApplicationStarter +import com.intellij.openapi.application.PathManager +import com.intellij.openapi.application.ex.ApplicationInfoEx +import com.intellij.openapi.diagnostic.logger +import com.intellij.openapi.keymap.KeymapUtil +import com.intellij.openapi.keymap.ex.KeymapManagerEx +import com.intellij.openapi.util.text.StringUtil +import java.io.IOException +import java.nio.file.Files +import java.nio.file.Path +import kotlin.system.exitProcess -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; -import java.util.Set; -import java.util.stream.IntStream; +private val LOG = logger() -/** - * @author Konstantin Bulenkov - */ -final class KeymapGenerator implements ApplicationStarter { - @Override - public String getCommandName() { - return "keymap"; - } +private val LEVELS = sequenceOf(1, 4).map { i -> + " ".repeat(i * 2) +}.toList() - private static final Logger LOG = Logger.getInstance(KeymapGenerator.class); - private static final String[] LEVELS = IntStream.range(1, 4).mapToObj(i -> " ".repeat(i * 2)).toArray(String[]::new); +private class KeymapGenerator : ApplicationStarter { + @Suppress("OVERRIDE_DEPRECATION") + override val commandName: String + get() = "keymap" - private static void renderAction(@NotNull String id, - @Nullable String asId, - Shortcut @NotNull [] shortcuts, - @NotNull StringBuilder dest) { - if (shortcuts.length == 0) { - return; - } + override fun main(args: List) { + val xml = StringBuilder() + xml.append("\n").append("\n") - dest.append(LEVELS[1]).append("\n"); + val keyManager = KeymapManagerEx.getInstanceEx() + val actionManager = ActionManagerEx.getInstanceEx() + val boundActions = actionManager.getBoundActions() - // Different shortcuts may have equal display strings (e.g., shift+minus and shift+subtract) - // We don't want them do be duplicated for users - Arrays.stream(shortcuts) - .map(shortcut -> KeymapUtil.getShortcutText(shortcut)) - .distinct() - .forEach(shortcut -> dest.append(LEVELS[2]).append("").append(shortcut).append("\n")); + for (keymap in keyManager.allKeymaps) { + xml.append(LEVELS[0]).append("\n") - final AnAction action = ActionManager.getInstance().getAction(id); - - if (action != null) { - final String text = action.getTemplatePresentation().getText(); - if (text != null) { - dest.append(LEVELS[2]).append("").append(StringUtil.escapeXmlEntities(text)).append("\n"); + val alreadyMapped = HashSet(keymap.actionIdList) + for (id in alreadyMapped) { + renderAction(id = id, asId = null, shortcuts = keymap.getShortcuts(id), dest = xml, actionManager = actionManager) } - } - dest.append(LEVELS[1]).append("\n"); - } - - @Override - public void main(@NotNull List args) { - StringBuilder xml = new StringBuilder(); - xml.append("\n").append("\n"); - - KeymapManagerEx keyManager = KeymapManagerEx.getInstanceEx(); - ActionManagerEx actionManager = ActionManagerEx.getInstanceEx(); - Set boundActions = actionManager.getBoundActions(); - - for (Keymap keymap : keyManager.getAllKeymaps()) { - xml.append(LEVELS[0]).append("\n"); - - Set alreadyMapped = Sets.newHashSet(keymap.getActionIdList()); - - alreadyMapped.forEach(id -> { - renderAction(id, null, keymap.getShortcuts(id), xml); - }); //We need to inject bound actions under their real names in every keymap that doesn't already have them. - boundActions.forEach(id -> { - final String binding = actionManager.getActionBinding(id); + for (id in boundActions) { + val binding = actionManager.getActionBinding(id) if (binding != null && !alreadyMapped.contains(id)) { - renderAction(binding, id, keymap.getShortcuts(binding), xml); + renderAction(id = binding, asId = id, shortcuts = keymap.getShortcuts(binding), dest = xml, actionManager = actionManager) } - }); + } - xml.append(LEVELS[0]).append("\n"); + xml.append(LEVELS[0]).append("\n") } - xml.append(""); + xml.append("") - Path targetFilePath = Paths.get(args.size() > 1 ? args.get(1) : PathManager.getHomePath()) - .resolve( - "keymap-%s.xml".formatted(ApplicationInfoEx.getInstanceEx().getApiVersionAsNumber().getProductCode().toLowerCase(Locale.ROOT))); + val targetFilePath = Path.of(if (args.size > 1) args[1] else PathManager.getHomePath()) + .resolve("keymap-%s.xml".format(ApplicationInfoEx.getInstanceEx().apiVersionAsNumber.productCode.lowercase())) try { - FileUtil.writeToFile(targetFilePath.toFile(), xml.toString()); - LOG.info("Keymaps saved to: " + targetFilePath.toAbsolutePath()); + Files.createDirectories(targetFilePath.parent) + Files.writeString(targetFilePath, xml.toString()) + LOG.info("Keymaps saved to: $targetFilePath") } - catch (IOException e) { - LOG.error("Cannot save keymaps", e); - System.exit(1); + catch (e: IOException) { + LOG.error("Cannot save keymaps", e) + exitProcess(1) } - System.exit(0); + exitProcess(0) } } + +private fun renderAction( + id: String, + asId: String?, + shortcuts: Array, + dest: StringBuilder, + actionManager: ActionManagerEx, +) { + if (shortcuts.isEmpty()) { + return + } + + dest.append(LEVELS[1]).append("\n") + + // Different shortcuts may have equal display strings (e.g., shift+minus and shift+subtract) + // We don't want them do be duplicated for users + shortcuts + .asSequence() + .map { KeymapUtil.getShortcutText(it) } + .distinct() + .forEach { shortcut -> + dest.append(LEVELS[2]).append("").append(shortcut).append("\n") + } + + val action = actionManager.getAction(id) + if (action != null) { + val text = action.templatePresentation.text + if (text != null) { + dest.append(LEVELS[2]).append("").append(StringUtil.escapeXmlEntities(text)).append("\n") + } + } + dest.append(LEVELS[1]).append("\n") +}