mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-03-01 04:46:02 +01:00
Merge remote-tracking branch 'zolotov/master'
This commit is contained in:
commit
2186945729
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
*.iml
|
||||
/.idea/
|
||||
/idea/
|
||||
/out/
|
||||
|
@ -1,5 +1,8 @@
|
||||
package com.maddyhome.idea.vim;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.io.Resources;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
@ -24,22 +27,28 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.maddyhome.idea.vim.ui.VimKeymapDialog;
|
||||
import org.jdom.Document;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
|
||||
import static com.google.common.io.ByteStreams.toByteArray;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
public class VimKeyMapUtil {
|
||||
private static Logger LOG = Logger.getInstance(VimKeyMapUtil.class);
|
||||
private static final Joiner PATH_JOINER = Joiner.on(File.separatorChar);
|
||||
public static final String VIM_KEYMAP_NAME = "Vim";
|
||||
|
||||
private static final String VIM_XML = "Vim.xml";
|
||||
private static final String KEYMAPS_PATH = PATH_JOINER.join(PathManager.getConfigPath(), "keymaps");
|
||||
private static final String INSTALLED_VIM_KEYMAP_PATH = PATH_JOINER.join(KEYMAPS_PATH, VIM_XML);
|
||||
|
||||
private static Logger LOG = Logger.getInstance(VimKeyMapUtil.class);
|
||||
|
||||
public static boolean isVimKeymapInstalled() {
|
||||
return KeymapManager.getInstance().getKeymap("Vim") != null;
|
||||
return KeymapManager.getInstance().getKeymap(VIM_KEYMAP_NAME) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -47,83 +56,63 @@ public class VimKeyMapUtil {
|
||||
*/
|
||||
public static boolean installKeyBoardBindings() {
|
||||
LOG.debug("Check for keyboard bindings");
|
||||
|
||||
final KeymapManagerImpl manager = (KeymapManagerImpl)KeymapManager.getInstance();
|
||||
|
||||
final Keymap keymap = manager.getKeymap("Vim");
|
||||
if (keymap != null) {
|
||||
if (isVimKeymapInstalled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final String keyMapsPath = PathManager.getConfigPath() + File.separatorChar + "keymaps";
|
||||
final LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
|
||||
final VirtualFile keyMapsFolder = localFileSystem.refreshAndFindFileByPath(keyMapsPath);
|
||||
if (keyMapsFolder == null) {
|
||||
LOG.error("Failed to install vim keymap. Empty keymaps folder");
|
||||
if (localFileSystem.refreshAndFindFileByPath(KEYMAPS_PATH) == null) {
|
||||
reportError("Failed to install vim keymap. Empty keymaps folder");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG.debug("No vim keyboard installed found. Installing");
|
||||
String keymapPath = PathManager.getPluginsPath() + File.separatorChar + VimPlugin.IDEAVIM_NOTIFICATION_TITLE + File.separatorChar + VIM_XML;
|
||||
File vimKeyMapFile = new File(keymapPath);
|
||||
// Look in development path
|
||||
if ((!vimKeyMapFile.exists() || !vimKeyMapFile.isFile()) && ApplicationManagerEx.getApplicationEx().isInternal()) {
|
||||
final String resource = VimKeyMapUtil.class.getResource("").toString();
|
||||
keymapPath = resource.toString().substring("file:".length(), resource.indexOf("out")) + "community/plugins/ideavim/keymap/" + VIM_XML;
|
||||
vimKeyMapFile = new File(keymapPath);
|
||||
}
|
||||
if (!vimKeyMapFile.exists() || !vimKeyMapFile.isFile()) {
|
||||
final String error = "Installation of the Vim keymap failed because Vim keymap file not found: " + keymapPath;
|
||||
LOG.error(error);
|
||||
Notifications.Bus.notify(new Notification(VimPlugin.IDEAVIM_NOTIFICATION_ID, VimPlugin.IDEAVIM_NOTIFICATION_TITLE, error, NotificationType.ERROR));
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
final VirtualFile vimKeyMap2Copy = localFileSystem.refreshAndFindFileByIoFile(vimKeyMapFile);
|
||||
if (vimKeyMap2Copy == null){
|
||||
final String error = "Installation of the Vim keymap failed because Vim keymap file not found: " + keymapPath;
|
||||
LOG.error(error);
|
||||
Notifications.Bus.notify(new Notification(VimPlugin.IDEAVIM_NOTIFICATION_ID, VimPlugin.IDEAVIM_NOTIFICATION_TITLE, error, NotificationType.ERROR));
|
||||
return false;
|
||||
}
|
||||
final VirtualFile vimKeyMapVFile = localFileSystem.copyFile(VimPlugin.getInstance(), vimKeyMap2Copy, keyMapsFolder, VIM_XML);
|
||||
|
||||
final String path = vimKeyMapVFile.getPath();
|
||||
final Document document = StorageUtil.loadDocument(new FileInputStream(path));
|
||||
if (document == null) {
|
||||
LOG.error("Failed to install vim keymap. Vim.xml file is corrupted");
|
||||
Notifications.Bus.notify(new Notification(VimPlugin.IDEAVIM_NOTIFICATION_ID, VimPlugin.IDEAVIM_NOTIFICATION_TITLE,
|
||||
"Failed to install vim keymap. Vim.xml file is corrupted", NotificationType.ERROR));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prompt user to select the parent for the Vim keyboard
|
||||
final byte[] bytes = toByteArray(retrieveSourceKeymapStream());
|
||||
Files.write(bytes, new File(INSTALLED_VIM_KEYMAP_PATH));
|
||||
final Document document = StorageUtil.loadDocument(bytes);
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
configureVimParentKeymap(path, document, false);
|
||||
// Prompt user to select the parent for the Vim keyboard
|
||||
configureVimParentKeymap(INSTALLED_VIM_KEYMAP_PATH, document, false);
|
||||
}
|
||||
|
||||
final KeymapImpl vimKeyMap = new KeymapImpl();
|
||||
final Keymap[] allKeymaps = manager.getAllKeymaps();
|
||||
vimKeyMap.readExternal(document.getRootElement(), allKeymaps);
|
||||
manager.addKeymap(vimKeyMap);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
reportError(e);
|
||||
installKeymap(document);
|
||||
} catch (IOException e) {
|
||||
reportError("Source keymap not found", e);
|
||||
return false;
|
||||
} catch (InvalidDataException e) {
|
||||
reportError("Failed to install vim keymap. Vim.xml file is corrupted", e);
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
reportError("Failed to install vim keymap.\n", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void installKeymap(Document document) throws InvalidDataException {
|
||||
if (document == null) {
|
||||
throw new InvalidDataException();
|
||||
}
|
||||
final KeymapImpl vimKeyMap = new KeymapImpl();
|
||||
final KeymapManagerImpl keymapManager = (KeymapManagerImpl) KeymapManager.getInstance();
|
||||
final Keymap[] allKeymaps = keymapManager.getAllKeymaps();
|
||||
vimKeyMap.readExternal(document.getRootElement(), allKeymaps);
|
||||
keymapManager.addKeymap(vimKeyMap);
|
||||
}
|
||||
|
||||
private static void requestRestartOrShutdown(final Project project) {
|
||||
final ApplicationEx app = ApplicationManagerEx.getApplicationEx();
|
||||
if (app.isRestartCapable()) {
|
||||
if (Messages.showDialog(project, "Restart " + ApplicationNamesInfo.getInstance().getProductName() + " to activate changes?",
|
||||
VimPlugin.IDEAVIM_NOTIFICATION_TITLE, new String[]{"&Restart", "&Postpone"}, 0, Messages.getQuestionIcon()) == 0) {
|
||||
VimPlugin.IDEAVIM_NOTIFICATION_TITLE, new String[]{"&Restart", "&Postpone"}, 0,
|
||||
Messages.getQuestionIcon()) == 0) {
|
||||
app.restart();
|
||||
}
|
||||
} else {
|
||||
if (Messages.showDialog(project, "Shut down " + ApplicationNamesInfo.getInstance().getProductName() + " to activate changes?",
|
||||
VimPlugin.IDEAVIM_NOTIFICATION_TITLE, new String[]{"&Shut Down", "&Postpone"}, 0, Messages.getQuestionIcon()) == 0){
|
||||
VimPlugin.IDEAVIM_NOTIFICATION_TITLE, new String[]{"&Shut Down", "&Postpone"}, 0,
|
||||
Messages.getQuestionIcon()) == 0) {
|
||||
app.exit(true);
|
||||
}
|
||||
}
|
||||
@ -131,6 +120,7 @@ public class VimKeyMapUtil {
|
||||
|
||||
/**
|
||||
* Changes parent keymap for the Vim
|
||||
*
|
||||
* @return true if document was changed successfully
|
||||
*/
|
||||
private static boolean configureVimParentKeymap(final String path, final Document document, final boolean showNotification) throws IOException {
|
||||
@ -138,7 +128,7 @@ public class VimKeyMapUtil {
|
||||
final String parentKeymap = rootElement.getAttributeValue("parent");
|
||||
final VimKeymapDialog vimKeymapDialog = new VimKeymapDialog(parentKeymap);
|
||||
vimKeymapDialog.show();
|
||||
if (vimKeymapDialog.getExitCode() != DialogWrapper.OK_EXIT_CODE){
|
||||
if (vimKeymapDialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) {
|
||||
return false;
|
||||
}
|
||||
rootElement.removeAttribute("parent");
|
||||
@ -151,7 +141,7 @@ public class VimKeyMapUtil {
|
||||
if (showNotification) {
|
||||
Notifications.Bus.notify(new Notification(VimPlugin.IDEAVIM_NOTIFICATION_ID, VimPlugin.IDEAVIM_NOTIFICATION_TITLE,
|
||||
"Successfully configured vim keymap to be based on " +
|
||||
selectedKeymap.getPresentableName(),
|
||||
selectedKeymap.getPresentableName(),
|
||||
NotificationType.INFORMATION));
|
||||
}
|
||||
|
||||
@ -159,7 +149,7 @@ public class VimKeyMapUtil {
|
||||
}
|
||||
|
||||
public static boolean isVimKeymapUsed() {
|
||||
return KeymapManager.getInstance().getActiveKeymap().getName().equals("Vim");
|
||||
return KeymapManager.getInstance().getActiveKeymap().getName().equals(VIM_KEYMAP_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,13 +159,13 @@ public class VimKeyMapUtil {
|
||||
LOG.debug("Enabling keymap");
|
||||
|
||||
// In case if Vim keymap is already in use or we don't need it, we have nothing to do
|
||||
if (isVimKeymapUsed() == enableVimKeymap){
|
||||
if (isVimKeymapUsed() == enableVimKeymap) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final KeymapManagerImpl manager = (KeymapManagerImpl)KeymapManager.getInstance();
|
||||
final KeymapManagerImpl manager = (KeymapManagerImpl) KeymapManager.getInstance();
|
||||
// Get keymap to enable
|
||||
final String keymapName2Enable = enableVimKeymap ? "Vim" : VimPlugin.getInstance().getPreviousKeyMap();
|
||||
final String keymapName2Enable = enableVimKeymap ? VIM_KEYMAP_NAME : VimPlugin.getInstance().getPreviousKeyMap();
|
||||
if (keymapName2Enable.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
@ -186,9 +176,7 @@ public class VimKeyMapUtil {
|
||||
LOG.debug("Enabling keymap:" + keymapName2Enable);
|
||||
final Keymap keymap = manager.getKeymap(keymapName2Enable);
|
||||
if (keymap == null) {
|
||||
Notifications.Bus.notify(new Notification(VimPlugin.IDEAVIM_NOTIFICATION_ID, VimPlugin.IDEAVIM_NOTIFICATION_TITLE,
|
||||
"Failed to enable keymap: " + keymapName2Enable, NotificationType.ERROR));
|
||||
LOG.error("Failed to enable keymap: " + keymapName2Enable);
|
||||
reportError("Failed to enable keymap: " + keymapName2Enable);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -210,52 +198,52 @@ public class VimKeyMapUtil {
|
||||
public static void reconfigureParentKeymap(final Project project) {
|
||||
final VirtualFile vimKeymapFile = getVimKeymapFile();
|
||||
if (vimKeymapFile == null) {
|
||||
LOG.error("Failed to find Vim keymap");
|
||||
Notifications.Bus.notify(new Notification(VimPlugin.IDEAVIM_NOTIFICATION_ID, VimPlugin.IDEAVIM_NOTIFICATION_TITLE,
|
||||
"Failed to find Vim keymap", NotificationType.ERROR));
|
||||
reportError("Failed to find Vim keymap");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final String path = vimKeymapFile.getPath();
|
||||
final Document document = StorageUtil.loadDocument(new FileInputStream(path));
|
||||
if (document == null) {
|
||||
LOG.error("Failed to install vim keymap. Vim.xml file is corrupted");
|
||||
Notifications.Bus.notify(new Notification(VimPlugin.IDEAVIM_NOTIFICATION_ID, VimPlugin.IDEAVIM_NOTIFICATION_TITLE,
|
||||
"Vim.xml file is corrupted", NotificationType.ERROR));
|
||||
return;
|
||||
}
|
||||
final Document document = StorageUtil.loadDocument(new FileInputStream(vimKeymapFile.getPath()));
|
||||
// Prompt user to select the parent for the Vim keyboard
|
||||
if (configureVimParentKeymap(path, document, true)) {
|
||||
final KeymapManagerImpl manager = (KeymapManagerImpl) KeymapManager.getInstance();
|
||||
final KeymapImpl vimKeyMap = new KeymapImpl();
|
||||
final Keymap[] allKeymaps = manager.getAllKeymaps();
|
||||
vimKeyMap.readExternal(document.getRootElement(), allKeymaps);
|
||||
manager.addKeymap(vimKeyMap);
|
||||
if (configureVimParentKeymap(vimKeymapFile.getPath(), document, true)) {
|
||||
installKeymap(document);
|
||||
requestRestartOrShutdown(project);
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
reportError(e);
|
||||
}
|
||||
catch (IOException e) {
|
||||
reportError(e);
|
||||
}
|
||||
catch (InvalidDataException e) {
|
||||
reportError(e);
|
||||
} catch (FileNotFoundException e) {
|
||||
reportError("Failed to install vim keymap.", e);
|
||||
} catch (IOException e) {
|
||||
reportError("Failed to install vim keymap.", e);
|
||||
} catch (InvalidDataException e) {
|
||||
reportError("Failed to install vim keymap. Vim.xml file is corrupted", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportError(final Exception e) {
|
||||
LOG.error("Failed to reconfigure vim keymap.\n" + e);
|
||||
@NotNull
|
||||
private static InputStream retrieveSourceKeymapStream() throws IOException {
|
||||
String keymapPath = PATH_JOINER.join(PathManager.getPluginsPath(), VimPlugin.IDEAVIM_NOTIFICATION_TITLE, VIM_XML);
|
||||
try {
|
||||
return new FileInputStream(keymapPath);
|
||||
} catch (FileNotFoundException e) {
|
||||
if (ApplicationManager.getApplication().isInternal()) {
|
||||
LOG.debug("Development mode on. Trying to retrieve source keymap from resources");
|
||||
return Resources.getResource(VimKeyMapUtil.class, "/" + VIM_XML).openStream();
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private static void reportError(final String message) {
|
||||
reportError(message, null);
|
||||
}
|
||||
|
||||
private static void reportError(final String message, @Nullable final Exception e) {
|
||||
LOG.error(message, e);
|
||||
Notifications.Bus.notify(new Notification(VimPlugin.IDEAVIM_NOTIFICATION_ID, VimPlugin.IDEAVIM_NOTIFICATION_TITLE,
|
||||
"Failed to reconfigure vim keymap.\n" + e, NotificationType.ERROR));
|
||||
message + String.valueOf(e), NotificationType.ERROR));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static VirtualFile getVimKeymapFile() {
|
||||
final String keyMapsPath = PathManager.getConfigPath() + File.separatorChar + "keymaps";
|
||||
final LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
|
||||
return localFileSystem.refreshAndFindFileByPath(keyMapsPath + File.separatorChar + VIM_XML);
|
||||
return LocalFileSystem.getInstance().refreshAndFindFileByPath(INSTALLED_VIM_KEYMAP_PATH);
|
||||
}
|
||||
}
|
||||
}
|
@ -10,6 +10,8 @@ import com.maddyhome.idea.vim.VimPlugin;
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static com.maddyhome.idea.vim.VimKeyMapUtil.VIM_KEYMAP_NAME;
|
||||
|
||||
/**
|
||||
* @author oleg
|
||||
*/
|
||||
@ -23,12 +25,12 @@ public class VimKeymapPanel {
|
||||
Keymap preselectedKeymap = null;
|
||||
for (Keymap keymap : manager.getAllKeymaps()) {
|
||||
final String name = keymap.getName();
|
||||
if (!"Vim".equals(name) && matchesPlatform(keymap)) {
|
||||
if (name.equals(parentKeymap)) {
|
||||
preselectedKeymap = keymap;
|
||||
}
|
||||
keymaps.add(keymap);
|
||||
}
|
||||
if (!VIM_KEYMAP_NAME.equals(name) && matchesPlatform(keymap)) {
|
||||
if (name.equals(parentKeymap)) {
|
||||
preselectedKeymap = keymap;
|
||||
}
|
||||
keymaps.add(keymap);
|
||||
}
|
||||
}
|
||||
|
||||
myKeymapComboBox.setModel(new DefaultComboBoxModel(keymaps.toArray(new Keymap[keymaps.size()])));
|
||||
|
Loading…
Reference in New Issue
Block a user