1
0
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:
Andrey Vlasovskikh 2012-11-26 18:32:41 +04:00
commit 2186945729
3 changed files with 99 additions and 108 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
*.iml
/.idea/
/idea/
/out/

View File

@ -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);
}
}
}

View File

@ -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()])));