Skip to content

Commit

Permalink
Merge pull request #244 from rieonke/VIM-2068
Browse files Browse the repository at this point in the history
Implement tabc[lose] ex command
  • Loading branch information
AlexPl292 committed Jul 16, 2020
2 parents 2901bf4 + 6e1761a commit 008edc7
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 0 deletions.
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,6 +61,7 @@
<vimExCommand implementation="com.maddyhome.idea.vim.ex.handler.NextTabHandler" names="tabn[ext]"/>
<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.TabCloseHandler" names="tabc[lose]"/>
<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]"/>
</extensions>
Expand Down
157 changes: 157 additions & 0 deletions src/com/maddyhome/idea/vim/ex/handler/TabCloseHandler.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* 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.ex.FileEditorManagerEx
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

/**
* @author Rieon Ke
*/
class TabCloseHandler : CommandHandler.SingleExecution() {

override val argFlags = flags(RangeFlag.RANGE_OPTIONAL, ArgumentFlag.ARGUMENT_OPTIONAL, Access.READ_ONLY)

override fun execute(editor: Editor, context: DataContext, cmd: ExCommand): Boolean {

val project = PlatformDataKeys.PROJECT.getData(context) ?: return false;
val fileEditorManager = FileEditorManagerEx.getInstanceEx(project);
val currentWindow = fileEditorManager.currentWindow
val tabbedPane = currentWindow.tabbedPane

val current = tabbedPane.selectedIndex
val tabCount = tabbedPane.tabCount

val argument = cmd.argument
val index = getTabIndexToClose(argument, current, tabCount - 1)

if (index != null) {
val select = if (index == current) index + 1 else current
tabbedPane.removeTabAt(index, select)
} else {
VimPlugin.showMessage("Error: invalid command argument")
}

return true
}

/**
* parse command argument to tab index.
* :tabclose -2 close the two previous tab page
* :tabclose + close the next tab page
* :tabclose +2 close the two next tab page
* :tabclose 3 close the third tab page
* :tabclose $ close the last tab page
* @param arg command argument
* @param current current selected tab index
* @param last the last tab index of active tabbed pane
* @return tab index to close
*/
private fun getTabIndexToClose(arg: String, current: Int, last: Int): Int? {

if (arg.isEmpty()) {
return current
}

if (last < 0) {
return null
}

val sb = StringBuilder()
var sign = Char.MIN_VALUE
var end = false

for (c in arg) {
when {
c in '0'..'9' && !end -> {
sb.append(c)
}

(c == '-' || c == '+') && !end && sb.isEmpty() && sign == Char.MIN_VALUE -> {
sign = c
}

c == '$' && sb.isEmpty() && sign == Char.MIN_VALUE -> {
end = true
}

c == ' ' -> {
//ignore
}
else -> return null

}
}


val idxStr = sb.toString()

val index = when {
end -> {
last
}
sb.isEmpty() -> {
when (sign) {
'+' -> {
current + 1
}
'-' -> {
current - 1
}
else -> {
current
}
}
}
else -> {
try {
val idx = Integer.valueOf(idxStr)
when (sign) {
'+' -> {
current + idx
}

'-' -> {
current - idx
}

else -> {
idx
}

}
} catch (e: NumberFormatException) {
return null
}
}
}
if (index < 0) return 0
if (index > last) return last
return index

}


}

0 comments on commit 008edc7

Please sign in to comment.