From 41c822fde13d60c53e3c4c583a55b69182ef564a Mon Sep 17 00:00:00 2001 From: John Weigel Date: Sun, 23 Feb 2020 20:45:06 -0600 Subject: [PATCH 1/4] Add support for buffer command. --- resources/META-INF/includes/VimExCommands.xml | 1 + .../idea/vim/ex/handler/BufferHandler.kt | 108 ++++++++++++++++++ .../idea/vim/helper/EditorHelper.java | 17 +++ .../ideavim/ex/handler/BufferHandlerTest.kt | 100 ++++++++++++++++ 4 files changed, 226 insertions(+) create mode 100644 src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt create mode 100644 test/org/jetbrains/plugins/ideavim/ex/handler/BufferHandlerTest.kt diff --git a/resources/META-INF/includes/VimExCommands.xml b/resources/META-INF/includes/VimExCommands.xml index f9595b9926..7fafaf9ef9 100644 --- a/resources/META-INF/includes/VimExCommands.xml +++ b/resources/META-INF/includes/VimExCommands.xml @@ -61,5 +61,6 @@ + diff --git a/src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt b/src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt new file mode 100644 index 0000000000..d44b46f2ed --- /dev/null +++ b/src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt @@ -0,0 +1,108 @@ +/* + * IdeaVim - Vim emulator for IDEs based on the IntelliJ platform + * Copyright (C) 2003-2020 The IdeaVim authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.maddyhome.idea.vim.ex.handler + +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.actionSystem.PlatformDataKeys +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.editor.impl.EditorImpl +import com.intellij.openapi.fileEditor.FileDocumentManager +import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.openapi.vfs.VirtualFile +import com.maddyhome.idea.vim.VimPlugin +import com.maddyhome.idea.vim.ex.CommandHandler +import com.maddyhome.idea.vim.ex.ExCommand +import com.maddyhome.idea.vim.ex.flags +import com.maddyhome.idea.vim.group.EditorGroup +import com.maddyhome.idea.vim.group.FileGroup +import com.maddyhome.idea.vim.helper.EditorHelper + +/** + * Handles buffer, buf, bu, b. + * + * @author John Weigel + */ +class BufferHandler : CommandHandler.SingleExecution() { + override val argFlags = flags(RangeFlag.RANGE_FORBIDDEN, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY) + + override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean { + val arg = cmd.argument.trim() + val overrideModified = arg.startsWith('!') + val buffer = if (overrideModified) arg.replace(Regex("^!\\s*"), "") else arg + var result = true + + if (buffer.isNotEmpty()) { + if (buffer.matches(Regex("^\\d+$"))) { + val bufNum = buffer.toInt() - 1 + + if (!VimPlugin.getFile().selectFile(bufNum, context)) { + VimPlugin.showMessage("Buffer $bufNum does not exist") + result = false + } + } else { + val editors = findPartialMatch(context, buffer) + + when { + editors.size == 1 -> { + + if (EditorHelper.hasUnsavedChanges(editor) && !overrideModified) { + VimPlugin.showMessage("No write since last change (add ! to override)") + result = false + } + else { + VimPlugin.getFile().openFile(EditorHelper.getVirtualFile(editors[0])!!.name, context) + } + } + editors.isEmpty() -> { + VimPlugin.showMessage("No matching buffer for $buffer") + result = false + } + editors.size > 1 -> { + VimPlugin.showMessage("More than one match for $buffer") + result = false + } + } + } + } + + return result + } + + private fun findPartialMatch(context: DataContext, fileName: String): List { + val project = PlatformDataKeys.PROJECT.getData(context) + val matchedFiles = mutableListOf() + + if (project != null) { + val fem = FileEditorManager.getInstance(project) + + for (file in fem.openFiles) { + if (file.name.contains(Regex.fromLiteral(fileName))) { + val editor = EditorHelper.getEditor(file) + + if (editor != null) { + matchedFiles.add(editor) + } + } + } + } + + return matchedFiles + } +} + diff --git a/src/com/maddyhome/idea/vim/helper/EditorHelper.java b/src/com/maddyhome/idea/vim/helper/EditorHelper.java index 5fcd3a81f3..e8b9b519b1 100644 --- a/src/com/maddyhome/idea/vim/helper/EditorHelper.java +++ b/src/com/maddyhome/idea/vim/helper/EditorHelper.java @@ -851,4 +851,21 @@ public static boolean isFileEditor(@NotNull Editor editor) { public static boolean isDiffEditor(@NotNull Editor editor) { return editor.getEditorKind() == EditorKind.DIFF; } + + /** + * Checks if the document in the editor is modified. + */ + public static boolean hasUnsavedChanges(@NotNull Editor editor) { + int line = 0; + Document document = editor.getDocument(); + + while (line < document.getLineCount()) { + if (document.isLineModified(line)) { + return true; + } + line++; + } + + return false; + } } diff --git a/test/org/jetbrains/plugins/ideavim/ex/handler/BufferHandlerTest.kt b/test/org/jetbrains/plugins/ideavim/ex/handler/BufferHandlerTest.kt new file mode 100644 index 0000000000..00b1111034 --- /dev/null +++ b/test/org/jetbrains/plugins/ideavim/ex/handler/BufferHandlerTest.kt @@ -0,0 +1,100 @@ +/* + * IdeaVim - Vim emulator for IDEs based on the IntelliJ platform + * Copyright (C) 2003-2020 The IdeaVim authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.jetbrains.plugins.ideavim.ex.handler + +import com.maddyhome.idea.vim.helper.StringHelper +import org.jetbrains.plugins.ideavim.VimTestCase + +/** + * @author John Weigel + */ +class BufferHandlerTest : VimTestCase() { + fun testBufferActionByNumber() { + configureByFileName("aaa.txt") + configureByFileName("bbb.txt") + typeText(commandToKeys("buffer 2")) + + assertPluginError(false) + } + + fun testBufferActionByName() { + configureByFileName("aaa.txt") + configureByFileName("bbb.txt") + typeText(commandToKeys("buffer aaa")) + + assertPluginError(false) + } + + fun testBufferActionWithNoArg() { + configureByText("\n") + typeText(commandToKeys("buffer")) + + assertPluginError(false) + } + + fun testBufferActionWithInvalidBufferNumber() { + configureByText("\n") + typeText(commandToKeys("buffer 999")) + + assertPluginError(true) + } + + fun testBufferActionWithInvalidBufferName() { + configureByText("\n") + typeText(commandToKeys("buffer invalidbuffer")) + + assertPluginError(true) + } + + fun testBufferActionWithModifications() { + configureByFileName("aaa.txt") + configureByFileName("bbb.txt") + typeText(StringHelper.parseKeys("aa:buffer aaa")) + + assertPluginError(true) + } + + fun testBufferActionWithMultipleMatches() { + configureByFileName("aaa.txt") + configureByFileName("aaa2.txt") + typeText(commandToKeys("buffer aaa")) + + assertPluginError(true) + } + + fun testBufAction() { + configureByText("\n") + typeText(commandToKeys("buf 1")) + + assertPluginError(false) + } + + fun testBuAction() { + configureByText("\n") + typeText(commandToKeys("bu 1")) + + assertPluginError(false) + } + + fun testBAction() { + configureByText("\n") + typeText(commandToKeys("b 1")) + + assertPluginError(false) + } +} From 158cea51db49d1514e14161a56b126547fccfecd Mon Sep 17 00:00:00 2001 From: John Weigel Date: Sun, 23 Feb 2020 22:02:06 -0600 Subject: [PATCH 2/4] Add override test --- .../plugins/ideavim/ex/handler/BufferHandlerTest.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/org/jetbrains/plugins/ideavim/ex/handler/BufferHandlerTest.kt b/test/org/jetbrains/plugins/ideavim/ex/handler/BufferHandlerTest.kt index 00b1111034..69a592583b 100644 --- a/test/org/jetbrains/plugins/ideavim/ex/handler/BufferHandlerTest.kt +++ b/test/org/jetbrains/plugins/ideavim/ex/handler/BufferHandlerTest.kt @@ -69,6 +69,14 @@ class BufferHandlerTest : VimTestCase() { assertPluginError(true) } + fun testBufferActionWithModificationsOverride() { + configureByFileName("aaa.txt") + configureByFileName("bbb.txt") + typeText(StringHelper.parseKeys("aa:buffer! aaa")) + + assertPluginError(false) + } + fun testBufferActionWithMultipleMatches() { configureByFileName("aaa.txt") configureByFileName("aaa2.txt") From 559b56c8a2368d3b2a99102c9680111c4a36a7b5 Mon Sep 17 00:00:00 2001 From: John Weigel Date: Tue, 3 Mar 2020 23:05:32 -0600 Subject: [PATCH 3/4] Minor updates --- .../idea/vim/ex/handler/BufferHandler.kt | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt b/src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt index d44b46f2ed..46705f5c9d 100644 --- a/src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt +++ b/src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt @@ -58,9 +58,12 @@ class BufferHandler : CommandHandler.SingleExecution() { } else { val editors = findPartialMatch(context, buffer) - when { - editors.size == 1 -> { - + when(editors.size) { + 0 -> { + VimPlugin.showMessage("No matching buffer for $buffer") + result = false + } + 1 -> { if (EditorHelper.hasUnsavedChanges(editor) && !overrideModified) { VimPlugin.showMessage("No write since last change (add ! to override)") result = false @@ -69,11 +72,7 @@ class BufferHandler : CommandHandler.SingleExecution() { VimPlugin.getFile().openFile(EditorHelper.getVirtualFile(editors[0])!!.name, context) } } - editors.isEmpty() -> { - VimPlugin.showMessage("No matching buffer for $buffer") - result = false - } - editors.size > 1 -> { + else -> { VimPlugin.showMessage("More than one match for $buffer") result = false } @@ -85,20 +84,13 @@ class BufferHandler : CommandHandler.SingleExecution() { } private fun findPartialMatch(context: DataContext, fileName: String): List { - val project = PlatformDataKeys.PROJECT.getData(context) val matchedFiles = mutableListOf() + val project = PlatformDataKeys.PROJECT.getData(context) ?: return matchedFiles - if (project != null) { - val fem = FileEditorManager.getInstance(project) - - for (file in fem.openFiles) { - if (file.name.contains(Regex.fromLiteral(fileName))) { - val editor = EditorHelper.getEditor(file) - - if (editor != null) { - matchedFiles.add(editor) - } - } + for (file in FileEditorManager.getInstance(project).openFiles) { + if (file.name.contains(fileName)) { + val editor = EditorHelper.getEditor(file) ?: continue + matchedFiles.add(editor) } } From 2f148255f7a3e2077be11f143d6571b67352374d Mon Sep 17 00:00:00 2001 From: John Weigel Date: Tue, 3 Mar 2020 23:14:11 -0600 Subject: [PATCH 4/4] Cleanup --- src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt b/src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt index 46705f5c9d..4f638116de 100644 --- a/src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt +++ b/src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt @@ -21,16 +21,11 @@ package com.maddyhome.idea.vim.ex.handler import com.intellij.openapi.actionSystem.DataContext import com.intellij.openapi.actionSystem.PlatformDataKeys import com.intellij.openapi.editor.Editor -import com.intellij.openapi.editor.impl.EditorImpl -import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.fileEditor.FileEditorManager -import com.intellij.openapi.vfs.VirtualFile import com.maddyhome.idea.vim.VimPlugin import com.maddyhome.idea.vim.ex.CommandHandler import com.maddyhome.idea.vim.ex.ExCommand import com.maddyhome.idea.vim.ex.flags -import com.maddyhome.idea.vim.group.EditorGroup -import com.maddyhome.idea.vim.group.FileGroup import com.maddyhome.idea.vim.helper.EditorHelper /**