1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-02-25 20:46:00 +01:00

VIM-1377 Normal mode needs to be more obvious

Add color customization to mode widget
This commit is contained in:
Filipp Vakhitov 2024-01-23 00:22:30 +02:00
parent 722cffbd48
commit a9ededc997
7 changed files with 476 additions and 12 deletions
src/main
java/com/maddyhome/idea/vim
resources
vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/services

View File

@ -0,0 +1,295 @@
/*
* Copyright 2003-2024 The IdeaVim authors
*
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE.txt file or at
* https://opensource.org/licenses/MIT.
*/
package com.maddyhome.idea.vim.ui.widgets.mode
import com.intellij.ide.ui.LafManager
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.ui.DialogPanel
import com.intellij.openapi.ui.popup.JBPopup
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.ui.components.JBScrollPane
import com.intellij.ui.components.JBTabbedPane
import com.intellij.ui.content.ContentFactory
import com.intellij.ui.dsl.builder.RowLayout
import com.intellij.ui.dsl.builder.bindText
import com.intellij.ui.dsl.builder.panel
import com.intellij.util.Alarm
import com.maddyhome.idea.vim.api.injector
import com.maddyhome.idea.vim.helper.MessageHelper
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
import java.awt.BorderLayout
import java.awt.Dimension
import java.awt.FlowLayout
import javax.swing.BorderFactory
import javax.swing.JButton
import javax.swing.JComponent
import javax.swing.JLabel
import javax.swing.JPanel
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
public class ModeWidgetPopup : AnAction() {
public override fun actionPerformed(e: AnActionEvent) {
val project = e.project ?: return
createPopup().showCenteredInCurrentWindow(project)
}
public companion object {
public fun createPopup(): JBPopup {
val mainPanel = JPanel(BorderLayout())
val buttonPanel = JPanel(FlowLayout(FlowLayout.RIGHT))
val applyButton = JButton("Apply")
val cancelButton = JButton("Close")
buttonPanel.add(applyButton)
buttonPanel.add(cancelButton)
mainPanel.add(buttonPanel, BorderLayout.SOUTH)
val tabbedPane = JBTabbedPane()
val lightThemeSettings = createPanel(getWidgetThemeColors(true))
val darkThemeSettings = createPanel(getWidgetThemeColors(false))
tabbedPane.addTab(MessageHelper.getMessage("widget.mode.popup.tab.light"), lightThemeSettings.addScrollPane())
tabbedPane.addTab(MessageHelper.getMessage("widget.mode.popup.tab.dark"), darkThemeSettings.addScrollPane())
tabbedPane.preferredSize = Dimension(300, 600)
for (i in 0 until tabbedPane.tabCount) {
val label = JLabel(tabbedPane.getTitleAt(i), JLabel.CENTER)
label.preferredSize = Dimension(126, tabbedPane.getTabComponentAt(i).preferredSize.height)
tabbedPane.setTabComponentAt(i, label)
}
tabbedPane.selectedIndex = if (LafManager.getInstance().currentUIThemeLookAndFeel.isDark) 1 else 0
mainPanel.add(tabbedPane, BorderLayout.CENTER)
val popupContent = ContentFactory.getInstance().createContent(mainPanel, "", false).component
val popup = JBPopupFactory.getInstance()
.createComponentPopupBuilder(popupContent, popupContent)
.setTitle(MessageHelper.getMessage("widget.mode.popup.title"))
.setMovable(true)
.setRequestFocus(true)
.setCancelOnClickOutside(false)
.setCancelKeyEnabled(false)
.createPopup()
applyButton.addActionListener {
lightThemeSettings.apply()
darkThemeSettings.apply()
// todo update widget
}
cancelButton.addActionListener {
popup.cancel()
}
val alarm = Alarm(popup)
fun updateApplyButtonVisibility() {
alarm.addRequest({
applyButton.isEnabled = lightThemeSettings.isModified() || darkThemeSettings.isModified()
updateApplyButtonVisibility()
}, 500L)
}
updateApplyButtonVisibility()
return popup
}
private fun getWidgetThemeColors(isLight: Boolean): ModeColors {
val keyPostfix = if (isLight) "_light" else "_dark"
return ModeColors(
"widget_mode_normal_background$keyPostfix",
"widget_mode_normal_foreground$keyPostfix",
"widget_mode_insert_background$keyPostfix",
"widget_mode_insert_foreground$keyPostfix",
"widget_mode_replace_background$keyPostfix",
"widget_mode_replace_foreground$keyPostfix",
"widget_mode_command_background$keyPostfix",
"widget_mode_command_foreground$keyPostfix",
"widget_mode_visual_background$keyPostfix",
"widget_mode_visual_foreground$keyPostfix",
"widget_mode_visual_line_background$keyPostfix",
"widget_mode_visual_line_foreground$keyPostfix",
"widget_mode_visual_block_background$keyPostfix",
"widget_mode_visual_block_foreground$keyPostfix",
"widget_mode_select_background$keyPostfix",
"widget_mode_select_foreground$keyPostfix",
"widget_mode_select_line_background$keyPostfix",
"widget_mode_select_line_foreground$keyPostfix",
"widget_mode_select_block_background$keyPostfix",
"widget_mode_select_block_foreground$keyPostfix",
)
}
private fun createPanel(modeColors: ModeColors): DialogPanel {
val panel = panel {
row { text(MessageHelper.getMessage("widget.mode.popup.color.instruction")) }
group(MessageHelper.getMessage("widget.mode.popup.group.normal.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::normalBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::normalFg)
}.layout(RowLayout.PARENT_GRID)
}
group(MessageHelper.getMessage("widget.mode.popup.group.insert.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::insertBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::insertFg)
}.layout(RowLayout.PARENT_GRID)
}
group(MessageHelper.getMessage("widget.mode.popup.group.replace.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::replaceBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::replaceFg)
}.layout(RowLayout.PARENT_GRID)
}
group(MessageHelper.getMessage("widget.mode.popup.group.command.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::commandBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::commandFg)
}.layout(RowLayout.PARENT_GRID)
}
group(MessageHelper.getMessage("widget.mode.popup.group.visual.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::visualBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::visualFg)
}.layout(RowLayout.PARENT_GRID)
collapsibleGroup(MessageHelper.getMessage("widget.mode.popup.group.visual.subgroup.line.title")) {
row { text(MessageHelper.getMessage("widget.mode.popup.group.visual.subgroup.instruction")) }
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::visualLineBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::visualLineFg)
}.layout(RowLayout.PARENT_GRID)
}
collapsibleGroup(MessageHelper.getMessage("widget.mode.popup.group.visual.subgroup.block.title")) {
row { text(MessageHelper.getMessage("widget.mode.popup.group.visual.subgroup.instruction")) }
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::visualBlockBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::visualBlockFg)
}.layout(RowLayout.PARENT_GRID)
}
}
group(MessageHelper.getMessage("widget.mode.popup.group.select.title")) {
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::selectBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::selectFg)
}.layout(RowLayout.PARENT_GRID)
collapsibleGroup(MessageHelper.getMessage("widget.mode.popup.group.select.subgroup.line.title")) {
row { text(MessageHelper.getMessage("widget.mode.popup.group.select.subgroup.instruction")) }
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::selectLineBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::selectLineFg)
}.layout(RowLayout.PARENT_GRID)
}
collapsibleGroup(MessageHelper.getMessage("widget.mode.popup.group.select.subgroup.block.title")) {
row { text(MessageHelper.getMessage("widget.mode.popup.group.select.subgroup.instruction")) }
row {
label(MessageHelper.getMessage("widget.mode.popup.field.background"))
textField().bindText(modeColors::selectBlockBg)
}.layout(RowLayout.PARENT_GRID)
row {
label(MessageHelper.getMessage("widget.mode.popup.field.foreground"))
textField().bindText(modeColors::selectBlockFg)
}.layout(RowLayout.PARENT_GRID)
}
}
}
return panel
}
private fun JComponent.addScrollPane(): JComponent {
val scrollPane = JBScrollPane(this, JBScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JBScrollPane.HORIZONTAL_SCROLLBAR_NEVER)
scrollPane.border = BorderFactory.createEmptyBorder()
return scrollPane
}
}
private class ModeColors(
normalBgKey: String, normalFgKey: String,
insertBgKey: String, insertFgKey: String,
replaceBgKey: String, replaceFgKey: String,
commandBgKey: String, commandFgKey: String,
visualBgKey: String, visualFgKey: String, visualLineBgKey: String, visualLineFgKey: String, visualBlockBgKey: String, visualBlockFgKey: String,
selectBgKey: String, selectFgKey: String, selectLineBgKey: String, selectLineFgKey: String, selectBlockBgKey: String, selectBlockFgKey: String
) {
var normalBg: String by VimScopeVariable(normalBgKey)
var normalFg: String by VimScopeVariable(normalFgKey)
var insertBg: String by VimScopeVariable(insertBgKey)
var insertFg: String by VimScopeVariable(insertFgKey)
var replaceBg: String by VimScopeVariable(replaceBgKey)
var replaceFg: String by VimScopeVariable(replaceFgKey)
var commandBg: String by VimScopeVariable(commandBgKey)
var commandFg: String by VimScopeVariable(commandFgKey)
var visualBg: String by VimScopeVariable(visualBgKey)
var visualFg: String by VimScopeVariable(visualFgKey)
var visualLineBg: String by VimScopeVariable(visualLineBgKey)
var visualLineFg: String by VimScopeVariable(visualLineFgKey)
var visualBlockBg: String by VimScopeVariable(visualBlockBgKey)
var visualBlockFg: String by VimScopeVariable(visualBlockFgKey)
var selectBg: String by VimScopeVariable(selectBgKey)
var selectFg: String by VimScopeVariable(selectFgKey)
var selectLineBg: String by VimScopeVariable(selectLineBgKey)
var selectLineFg: String by VimScopeVariable(selectLineFgKey)
var selectBlockBg: String by VimScopeVariable(selectBlockBgKey)
var selectBlockFg: String by VimScopeVariable(selectBlockFgKey)
private class VimScopeVariable(private var key: String): ReadWriteProperty<ModeColors, String> {
override fun getValue(thisRef: ModeColors, property: KProperty<*>): String {
return injector.variableService.getVimVariable(key)?.asString() ?: ""
}
override fun setValue(thisRef: ModeColors, property: KProperty<*>, value: String) {
injector.variableService.storeVimVariable(key, VimString(value))
}
}
}
}

View File

@ -8,10 +8,12 @@
package com.maddyhome.idea.vim.ui.widgets.mode
import com.intellij.ide.ui.LafManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.wm.CustomStatusBarWidget
import com.intellij.ui.awt.RelativePoint
import com.intellij.ui.components.JBLabel
import com.intellij.ui.util.width
import com.intellij.util.ui.UIUtil
@ -25,6 +27,9 @@ import com.maddyhome.idea.vim.ui.widgets.mode.listeners.ModeWidgetFocusListener
import com.maddyhome.idea.vim.ui.widgets.mode.listeners.ModeWidgetModeListener
import java.awt.Color
import java.awt.Dimension
import java.awt.Point
import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent
import javax.swing.JComponent
import kotlin.math.max
@ -54,6 +59,19 @@ public class VimModeWidget(public val project: Project) : CustomStatusBarWidget,
modeChangeListeners.add(ModeWidgetModeListener(this@VimModeWidget))
myEditorListeners.add(ModeWidgetFocusListener(this@VimModeWidget))
}
label.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
val popup = ModeWidgetPopup.createPopup()
val dimension = popup.content.preferredSize
val widgetLocation = e.component.locationOnScreen
popup.show(RelativePoint(Point(
widgetLocation.x + e.component.width - dimension.width,
widgetLocation.y - dimension.height,
)))
}
})
}
override fun ID(): String {
@ -112,21 +130,83 @@ public class VimModeWidget(public val project: Project) : CustomStatusBarWidget,
}
private fun getModeForeground(mode: Mode?): Color {
// TODO make it customizable via settings (color picker) or .idevimrc
return UIUtil.getPanelBackground()
val keyPostfix = if (LafManager.getInstance().currentUIThemeLookAndFeel.isDark) "_dark" else "_light"
val colorString = when (mode) {
Mode.INSERT -> injector.variableService.getVimVariable("widget_mode_insert_foreground$keyPostfix")
Mode.REPLACE -> injector.variableService.getVimVariable("widget_mode_replace_foreground$keyPostfix")
is Mode.NORMAL -> injector.variableService.getVimVariable("widget_mode_normal_foreground$keyPostfix")
is Mode.CMD_LINE -> injector.variableService.getVimVariable("widget_mode_command_foreground$keyPostfix")
is Mode.VISUAL -> {
val visualModeBackground = injector.variableService.getVimVariable("widget_mode_visual_foreground$keyPostfix")
when (mode.selectionType) {
SelectionType.CHARACTER_WISE -> visualModeBackground
SelectionType.LINE_WISE -> injector.variableService.getVimVariable("widget_mode_visual_line_foreground$keyPostfix") ?: visualModeBackground
SelectionType.BLOCK_WISE -> injector.variableService.getVimVariable("widget_mode_visual_block_foreground$keyPostfix") ?: visualModeBackground
}
}
is Mode.SELECT -> {
val selectModeBackground = injector.variableService.getVimVariable("widget_mode_select_foreground$keyPostfix")
when (mode.selectionType) {
SelectionType.CHARACTER_WISE -> selectModeBackground
SelectionType.LINE_WISE -> injector.variableService.getVimVariable("widget_mode_select_line_foreground$keyPostfix") ?: selectModeBackground
SelectionType.BLOCK_WISE -> injector.variableService.getVimVariable("widget_mode_select_block_foreground$keyPostfix") ?: selectModeBackground
}
}
is Mode.OP_PENDING, null -> null
}?.asString()
val defaultColor = UIUtil.getLabelForeground()
val color = when (colorString) {
"v:status_bar_bg" -> UIUtil.getPanelBackground()
"v:status_bar_fg" -> UIUtil.getLabelForeground()
else -> {
if (colorString == null) {
defaultColor
} else {
try { Color.decode(colorString) } catch (e: Exception) { defaultColor }
}
}
}
return color
}
private fun getModeBackground(mode: Mode?): Color? {
// TODO make it customizable via settings (color picker) or .idevimrc
return when (mode) {
Mode.INSERT -> Color(134, 174, 213)
Mode.REPLACE -> Color(213, 134, 134)
is Mode.NORMAL -> Color(174, 213, 134)
is Mode.CMD_LINE -> Color(174, 213, 134)
is Mode.VISUAL -> Color(213, 174, 213)
is Mode.SELECT -> Color(213, 174, 213)
is Mode.OP_PENDING, null -> label.parent?.background
private fun getModeBackground(mode: Mode?): Color {
val keyPostfix = if (LafManager.getInstance().currentUIThemeLookAndFeel.isDark) "_dark" else "_light"
val colorString = when (mode) {
Mode.INSERT -> injector.variableService.getVimVariable("widget_mode_insert_background$keyPostfix")
Mode.REPLACE -> injector.variableService.getVimVariable("widget_mode_replace_background$keyPostfix")
is Mode.NORMAL -> injector.variableService.getVimVariable("widget_mode_normal_background$keyPostfix")
is Mode.CMD_LINE -> injector.variableService.getVimVariable("widget_mode_command_background$keyPostfix")
is Mode.VISUAL -> {
val visualModeBackground = injector.variableService.getVimVariable("widget_mode_visual_background$keyPostfix")
when (mode.selectionType) {
SelectionType.CHARACTER_WISE -> visualModeBackground
SelectionType.LINE_WISE -> injector.variableService.getVimVariable("widget_mode_visual_line_background$keyPostfix") ?: visualModeBackground
SelectionType.BLOCK_WISE -> injector.variableService.getVimVariable("widget_mode_visual_block_background$keyPostfix") ?: visualModeBackground
}
}
is Mode.SELECT -> {
val selectModeBackground = injector.variableService.getVimVariable("widget_mode_select_background$keyPostfix")
when (mode.selectionType) {
SelectionType.CHARACTER_WISE -> selectModeBackground
SelectionType.LINE_WISE -> injector.variableService.getVimVariable("widget_mode_select_line_background$keyPostfix") ?: selectModeBackground
SelectionType.BLOCK_WISE -> injector.variableService.getVimVariable("widget_mode_select_block_background$keyPostfix") ?: selectModeBackground
}
}
is Mode.OP_PENDING, null -> null
}?.asString()
val defaultColor = UIUtil.getPanelBackground()
val color = when (colorString) {
"v:status_bar_bg" -> UIUtil.getPanelBackground()
"v:status_bar_fg" -> UIUtil.getLabelForeground()
else -> {
if (colorString == null) {
defaultColor
} else {
try { Color.decode(colorString) } catch (e: Exception) { defaultColor }
}
}
}
return color
}
private class JBLabelWiderThan(private val words: Collection<String>): JBLabel("", CENTER) {

View File

@ -47,4 +47,55 @@ internal class IjVariableService : VimVariableServiceBase() {
else -> error("Unexpected")
}
}
override fun getVimVariable(name: String): VimDataType? {
val userSetValue = super.getVimVariable(name)
if (userSetValue != null) return userSetValue
return when (name) {
"widget_mode_normal_background_light" -> VimString("#aed586")
"widget_mode_normal_foreground_light" -> VimString("v:status_bar_fg")
"widget_mode_insert_background_light" -> VimString("#86aed5")
"widget_mode_insert_foreground_light" -> VimString("v:status_bar_fg")
"widget_mode_replace_background_light" -> VimString("#d58686")
"widget_mode_replace_foreground_light" -> VimString("v:status_bar_fg")
"widget_mode_command_background_light" -> VimString("#aed586")
"widget_mode_command_foreground_light" -> VimString("v:status_bar_fg")
"widget_mode_visual_background_light" -> VimString("#d5aed5")
"widget_mode_visual_foreground_light" -> VimString("v:status_bar_fg")
// "widget_mode_visual_line_background_light" -> VimString("")
// "widget_mode_visual_line_foreground_light" -> VimString("v:status_bar_fg")
// "widget_mode_visual_block_background_light" -> VimString("")
// "widget_mode_visual_block_foreground_light" -> VimString("v:status_bar_fg")
"widget_mode_select_background_light" -> VimString("#d5aed5")
"widget_mode_select_foreground_light" -> VimString("v:status_bar_fg")
// "widget_mode_select_line_background_light" -> VimString("")
// "widget_mode_select_line_foreground_light" -> VimString("v:status_bar_fg")
// "widget_mode_select_block_background_light" -> VimString("")
// "widget_mode_select_block_foreground_light" -> VimString("v:status_bar_fg")
"widget_mode_normal_background_dark" -> VimString("#aed586")
"widget_mode_normal_foreground_dark" -> VimString("v:status_bar_fg")
"widget_mode_insert_background_dark" -> VimString("#86aed5")
"widget_mode_insert_foreground_dark" -> VimString("v:status_bar_fg")
"widget_mode_replace_background_dark" -> VimString("#d58686")
"widget_mode_replace_foreground_dark" -> VimString("v:status_bar_fg")
"widget_mode_command_background_dark" -> VimString("#aed586")
"widget_mode_command_foreground_dark" -> VimString("v:status_bar_fg")
"widget_mode_visual_background_dark" -> VimString("#d5aed5")
"widget_mode_visual_foreground_dark" -> VimString("v:status_bar_fg")
// "widget_mode_visual_line_background_dark" -> VimString("")
// "widget_mode_visual_line_foreground_dark" -> VimString("v:status_bar_fg")
// "widget_mode_visual_block_background_dark" -> VimString("")
// "widget_mode_visual_block_foreground_dark" -> VimString("v:status_bar_fg")
"widget_mode_select_background_dark" -> VimString("#d5aed5")
"widget_mode_select_foreground_dark" -> VimString("v:status_bar_fg")
// "widget_mode_select_line_background_dark" -> VimString("")
// "widget_mode_select_line_foreground_dark" -> VimString("v:status_bar_fg")
// "widget_mode_select_block_background_dark" -> VimString("")
// "widget_mode_select_block_foreground_dark" -> VimString("v:status_bar_fg")
else -> null
}
}
}

View File

@ -160,6 +160,7 @@
<action id="VimShortcutKeyAction" class="com.maddyhome.idea.vim.action.VimShortcutKeyAction"/>
<action id="VimActions" class="com.maddyhome.idea.vim.ui.VimActions"/>
<action id="CustomizeModeWidget" class="com.maddyhome.idea.vim.ui.widgets.mode.ModeWidgetPopup"/>
<group id="IdeaVim.ReloadVimRc.group" class="com.maddyhome.idea.vim.ui.ReloadFloatingToolbarActionGroup">
<action id="IdeaVim.ReloadVimRc.reload" class="com.maddyhome.idea.vim.ui.ReloadVimRc"

View File

@ -84,6 +84,8 @@ action.VimShortcutKeyAction.text=Shortcuts
action.VimActions.text=Vim Actions
action.not.found.0=Action not found: {0}
action.CustomizeModeWidget.text=Mode Widget Settings
action.VimFindActionIdAction.text=IdeaVim: Track Action Ids
action.VimFindActionIdAction.description=Starts tracking ids of executed actions
@ -129,6 +131,26 @@ action.finish.eap.text=Finish EAP
# Don't forget to update README if you modify this entry
action.subscribe.to.eap.text=Subscribe to EAP
widget.mode.popup.title=Mode Widget Colors
widget.mode.popup.tab.light=Light Theme
widget.mode.popup.tab.dark=Dark Theme
widget.mode.popup.color.instruction=Use HEX color values for exact colors; use v:status_bar_bg to use your IDE's status bar background color and v:status_bar_fg for the foreground
widget.mode.popup.group.normal.title=Normal Mode
widget.mode.popup.group.insert.title=Insert Mode
widget.mode.popup.group.replace.title=Replace Mode
widget.mode.popup.group.command.title=Command Mode
widget.mode.popup.group.visual.title=Visual Mode
widget.mode.popup.group.visual.subgroup.instruction=Leave fields empty to inherit colors from Visual Mode
widget.mode.popup.group.visual.subgroup.line.title=Visual Line
widget.mode.popup.group.visual.subgroup.block.title=Visual Block
widget.mode.popup.group.select.title=Select Mode
widget.mode.popup.group.select.subgroup.instruction=Leave fields empty to inherit colors from Select Mode
widget.mode.popup.group.select.subgroup.line.title=Select Line
widget.mode.popup.group.select.subgroup.block.title=Select Block
widget.mode.popup.field.background=Background:
widget.mode.popup.field.foreground=Foreground:
configurable.name.vim.emulation=Vim
configurable.keyhandler.link=<html>Use <a>sethandler</a> command to configure handlers from the .ideavimrc file</html>
configurable.noneditablehandler.helper.text.with.example=Non-editable handlers are defined in .ideavimrc file. E.g. ''{0}'' for {1}.

View File

@ -14,6 +14,7 @@ import com.maddyhome.idea.vim.ex.ExException
import com.maddyhome.idea.vim.vimscript.model.VimLContext
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType
import com.maddyhome.idea.vim.vimscript.model.expressions.Variable
import org.jetbrains.annotations.ApiStatus.Internal
import org.jetbrains.annotations.TestOnly
/**
@ -109,4 +110,9 @@ public interface VariableService {
*/
@TestOnly
public fun clear()
@Internal
public fun getVimVariable(name: String): VimDataType?
@Internal
public fun storeVimVariable(name: String, value: VimDataType)
}

View File

@ -32,6 +32,7 @@ public abstract class VimVariableServiceBase : VariableService {
private val windowVariablesKey = Key<MutableMap<String, VimDataType>>("TabVariables")
private val bufferVariablesKey = Key<MutableMap<String, VimDataType>>("BufferVariables")
private val tabVariablesKey = Key<MutableMap<String, VimDataType>>("WindowVariables")
private var vimVariables: MutableMap<String, VimDataType> = mutableMapOf()
private fun getWindowVariables(editor: VimEditor) =
injector.vimStorageService.getOrPutWindowData(editor, windowVariablesKey) { mutableMapOf() }
@ -241,4 +242,12 @@ public abstract class VimVariableServiceBase : VariableService {
override fun clear() {
globalVariables.clear()
}
override fun getVimVariable(name: String): VimDataType? {
return vimVariables[name]
}
override fun storeVimVariable(name: String, value: VimDataType) {
vimVariables[name] = value
}
}