Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for buffer command #227

Merged
merged 8 commits into from
May 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions resources/META-INF/includes/VimExCommands.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,6 @@
<vimExCommand implementation="com.maddyhome.idea.vim.ex.handler.PreviousTabHandler" names="tabp[revious],tabN[ext]"/>
<vimExCommand implementation="com.maddyhome.idea.vim.ex.handler.TabOnlyHandler" names="tabo[nly]"/>
<vimExCommand implementation="com.maddyhome.idea.vim.ex.handler.BufferListHandler" names="buffers,ls,files"/>
<vimExCommand implementation="com.maddyhome.idea.vim.ex.handler.BufferHandler" names="b[uffer],bu[f]"/>
</extensions>
</idea-plugin>
95 changes: 95 additions & 0 deletions src/com/maddyhome/idea/vim/ex/handler/BufferHandler.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/

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.fileEditor.FileEditorManager
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.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) {
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
}
else {
VimPlugin.getFile().openFile(EditorHelper.getVirtualFile(editors[0])!!.name, context)
}
}
else -> {
VimPlugin.showMessage("More than one match for $buffer")
result = false
}
}
}
}

return result
}

private fun findPartialMatch(context: DataContext, fileName: String): List<Editor> {
val matchedFiles = mutableListOf<Editor>()
val project = PlatformDataKeys.PROJECT.getData(context) ?: return matchedFiles

for (file in FileEditorManager.getInstance(project).openFiles) {
if (file.name.contains(fileName)) {
val editor = EditorHelper.getEditor(file) ?: continue
matchedFiles.add(editor)
}
}

return matchedFiles
}
}

17 changes: 17 additions & 0 deletions src/com/maddyhome/idea/vim/helper/EditorHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
108 changes: 108 additions & 0 deletions test/org/jetbrains/plugins/ideavim/ex/handler/BufferHandlerTest.kt
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.
*/
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<esc>:buffer aaa<enter>"))

assertPluginError(true)
}

fun testBufferActionWithModificationsOverride() {
configureByFileName("aaa.txt")
configureByFileName("bbb.txt")
typeText(StringHelper.parseKeys("aa<esc>:buffer! aaa<enter>"))

assertPluginError(false)
}

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