diff --git a/src/main/java/com/maddyhome/idea/vim/extension/VimExtensionRegistrar.kt b/src/main/java/com/maddyhome/idea/vim/extension/VimExtensionRegistrar.kt
index 4f72aeaa9..834781807 100644
--- a/src/main/java/com/maddyhome/idea/vim/extension/VimExtensionRegistrar.kt
+++ b/src/main/java/com/maddyhome/idea/vim/extension/VimExtensionRegistrar.kt
@@ -15,8 +15,8 @@ import com.maddyhome.idea.vim.api.VimExtensionRegistrator
 import com.maddyhome.idea.vim.api.injector
 import com.maddyhome.idea.vim.api.setToggleOption
 import com.maddyhome.idea.vim.key.MappingOwner.Plugin.Companion.remove
-import com.maddyhome.idea.vim.options.OptionDeclaredScope
 import com.maddyhome.idea.vim.options.OptionAccessScope
+import com.maddyhome.idea.vim.options.OptionDeclaredScope
 import com.maddyhome.idea.vim.options.ToggleOption
 import com.maddyhome.idea.vim.statistic.PluginState
 
@@ -60,7 +60,7 @@ internal object VimExtensionRegistrar : VimExtensionRegistrator {
     val option = ToggleOption(name, OptionDeclaredScope.GLOBAL, getAbbrev(name), false)
     VimPlugin.getOptionGroup().addOption(option)
     VimPlugin.getOptionGroup().addGlobalOptionChangeListener(option) {
-      if (injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL).asBoolean()) {
+      if (injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(null)).asBoolean()) {
         initExtension(extensionBean, name)
         PluginState.enabledExtensions.add(name)
       } else {
@@ -106,7 +106,7 @@ internal object VimExtensionRegistrar : VimExtensionRegistrator {
   override fun setOptionByPluginAlias(alias: String): Boolean {
     val name = extensionAliases[alias] ?: return false
     val option = injector.optionGroup.getOption(name) as? ToggleOption ?: return false
-    injector.optionGroup.setToggleOption(option, OptionAccessScope.GLOBAL)
+    injector.optionGroup.setToggleOption(option, OptionAccessScope.GLOBAL(null))
     return true
   }
 
diff --git a/src/main/java/com/maddyhome/idea/vim/group/IjOptionProperties.kt b/src/main/java/com/maddyhome/idea/vim/group/IjOptionProperties.kt
index 77df292cf..4a344fab1 100644
--- a/src/main/java/com/maddyhome/idea/vim/group/IjOptionProperties.kt
+++ b/src/main/java/com/maddyhome/idea/vim/group/IjOptionProperties.kt
@@ -19,7 +19,7 @@ import com.maddyhome.idea.vim.options.OptionAccessScope
  * options
  */
 @Suppress("SpellCheckingInspection")
-public open class GlobalIjOptions(scope: OptionAccessScope = OptionAccessScope.GLOBAL) : OptionsPropertiesBase(scope) {
+public open class GlobalIjOptions(scope: OptionAccessScope) : OptionsPropertiesBase(scope) {
   public var closenotebooks: Boolean by optionProperty(IjOptions.closenotebooks)
   public var ide: String by optionProperty(IjOptions.ide)
   public var ideamarks: Boolean by optionProperty(IjOptions.ideamarks)
diff --git a/src/main/java/com/maddyhome/idea/vim/group/OptionGroup.kt b/src/main/java/com/maddyhome/idea/vim/group/OptionGroup.kt
index 7e66dce27..a45837f77 100644
--- a/src/main/java/com/maddyhome/idea/vim/group/OptionGroup.kt
+++ b/src/main/java/com/maddyhome/idea/vim/group/OptionGroup.kt
@@ -26,15 +26,13 @@ internal interface IjVimOptionGroup: VimOptionGroup {
 }
 
 internal class OptionGroup : VimOptionGroupBase(), IjVimOptionGroup {
-  private val globalOptionsAccessor = GlobalIjOptions()
-
   override fun initialiseOptions() {
     // We MUST call super!
     super.initialiseOptions()
     IjOptions.initialise()
   }
 
-  override fun getGlobalIjOptions() = globalOptionsAccessor
+  override fun getGlobalIjOptions() = GlobalIjOptions(OptionAccessScope.GLOBAL(null))
   override fun getEffectiveIjOptions(editor: VimEditor) = EffectiveIjOptions(OptionAccessScope.EFFECTIVE(editor))
 }
 
diff --git a/src/main/java/com/maddyhome/idea/vim/helper/CommandStateExtensions.kt b/src/main/java/com/maddyhome/idea/vim/helper/CommandStateExtensions.kt
index a84e5ae6c..9dde66eb0 100644
--- a/src/main/java/com/maddyhome/idea/vim/helper/CommandStateExtensions.kt
+++ b/src/main/java/com/maddyhome/idea/vim/helper/CommandStateExtensions.kt
@@ -16,8 +16,8 @@ import com.maddyhome.idea.vim.api.hasValue
 import com.maddyhome.idea.vim.api.injector
 import com.maddyhome.idea.vim.command.CommandState
 import com.maddyhome.idea.vim.newapi.vim
-import com.maddyhome.idea.vim.options.OptionConstants
 import com.maddyhome.idea.vim.options.OptionAccessScope
+import com.maddyhome.idea.vim.options.OptionConstants
 import com.maddyhome.idea.vim.state.mode.Mode
 import com.maddyhome.idea.vim.state.mode.inVisualMode
 import com.maddyhome.idea.vim.state.mode.mode
@@ -55,8 +55,10 @@ public val Editor.mode: CommandState.Mode
 public val CommandState.Mode.isEndAllowed: Boolean
   get() {
     fun possiblyUsesVirtualSpace(): Boolean {
-      // virtualedit is GLOBAL_OR_LOCAL_TO_WINDOW. We should NOT be using the global value!
-      return injector.optionGroup.hasValue(Options.virtualedit, OptionAccessScope.GLOBAL, OptionConstants.virtualedit_onemore)
+      // virtualedit is GLOBAL_OR_LOCAL_TO_WINDOW. We should be using EFFECTIVE, but we don't have a valid editor (which
+      // is why this property is deprecated). Fetch the global value, passing in the fallback window to avoid asserts
+      // DO NOT COPY THIS APPROACH - ALWAYS USE A REAL WINDOW FOR NON-GLOBAL OPTIONS!
+      return injector.optionGroup.hasValue(Options.virtualedit, OptionAccessScope.GLOBAL(injector.fallbackWindow), OptionConstants.virtualedit_onemore)
     }
 
     return when (this) {
diff --git a/src/main/java/com/maddyhome/idea/vim/statistic/OptionsState.kt b/src/main/java/com/maddyhome/idea/vim/statistic/OptionsState.kt
index 12245cbd5..4d0d4ea3e 100644
--- a/src/main/java/com/maddyhome/idea/vim/statistic/OptionsState.kt
+++ b/src/main/java/com/maddyhome/idea/vim/statistic/OptionsState.kt
@@ -19,8 +19,8 @@ import com.maddyhome.idea.vim.api.injector
 import com.maddyhome.idea.vim.group.IjOptionConstants
 import com.maddyhome.idea.vim.group.IjOptions
 import com.maddyhome.idea.vim.newapi.globalIjOptions
-import com.maddyhome.idea.vim.options.OptionConstants
 import com.maddyhome.idea.vim.options.OptionAccessScope
+import com.maddyhome.idea.vim.options.OptionConstants
 
 internal class OptionsState : ApplicationUsagesCollector() {
 
@@ -33,10 +33,11 @@ internal class OptionsState : ApplicationUsagesCollector() {
     return setOf(
       // ideajoin and idearefactor area global-local. We're only interested in the global value, not the effective
       // value, which a) might be set at local scope and b) isn't accessible without an editor
+      // We don't need to pass a window, since the global values will only ever be global
       OPTIONS.metric(
-        IDEAJOIN with injector.optionGroup.getOptionValue(IjOptions.ideajoin, OptionAccessScope.GLOBAL).asBoolean(),
+        IDEAJOIN with injector.optionGroup.getOptionValue(IjOptions.ideajoin, OptionAccessScope.GLOBAL(null)).asBoolean(),
         IDEAMARKS with globalIjOptions.ideamarks,
-        IDEAREFACTOR with injector.optionGroup.getOptionValue(IjOptions.idearefactormode, OptionAccessScope.GLOBAL).asString(),
+        IDEAREFACTOR with injector.optionGroup.getOptionValue(IjOptions.idearefactormode, OptionAccessScope.GLOBAL(null)).asString(),
         IDEAPUT with globalOptions.clipboard.contains(OptionConstants.clipboard_ideaput),
         IDEASTATUSICON with globalIjOptions.ideastatusicon,
         IDEAWRITE with globalIjOptions.ideawrite,
diff --git a/src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt b/src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt
index 679fd6df2..98fad0d87 100644
--- a/src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt
+++ b/src/test/java/org/jetbrains/plugins/ideavim/VimTestCase.kt
@@ -178,7 +178,9 @@ abstract class VimTestCase {
   protected fun enableExtensions(vararg extensionNames: String) {
     for (name in extensionNames) {
       val option = injector.optionGroup.getOption(name) as ToggleOption
-      injector.optionGroup.setToggleOption(option, OptionAccessScope.GLOBAL)
+
+      // Global value of a global option. We can pass null
+      injector.optionGroup.setToggleOption(option, OptionAccessScope.GLOBAL(null))
     }
   }
 
diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/ChangeNumberActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/ChangeNumberActionTest.kt
index 3dcd80677..8c1ca22f7 100644
--- a/src/test/java/org/jetbrains/plugins/ideavim/action/ChangeNumberActionTest.kt
+++ b/src/test/java/org/jetbrains/plugins/ideavim/action/ChangeNumberActionTest.kt
@@ -9,10 +9,7 @@ package org.jetbrains.plugins.ideavim.action
 
 import com.google.common.collect.Lists
 import com.maddyhome.idea.vim.state.mode.Mode
-import org.jetbrains.plugins.ideavim.TestOptionConstants
 import org.jetbrains.plugins.ideavim.VimTestCase
-import org.jetbrains.plugins.ideavim.impl.OptionTest
-import org.jetbrains.plugins.ideavim.impl.VimOption
 import org.junit.jupiter.api.Test
 
 class ChangeNumberActionTest : VimTestCase() {
@@ -92,15 +89,17 @@ class ChangeNumberActionTest : VimTestCase() {
     )
   }
 
-  @OptionTest(VimOption(TestOptionConstants.nrformats, limitedValues = ["octal"]))
+  @Test
   fun testDecrementNegativeOctal() {
     // Minus isn't processed
     doTest(
-      Lists.newArrayList(":set nf=octal<Enter>", "<C-X>"),
+      "<C-X>",
       "-010",
       "-007",
       Mode.NORMAL(),
-    )
+    ) {
+      enterCommand("set nf=octal")
+    }
   }
 
   @Test
diff --git a/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/LetCommandTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/LetCommandTest.kt
index 788133ae2..6b83a196e 100644
--- a/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/LetCommandTest.kt
+++ b/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/LetCommandTest.kt
@@ -137,7 +137,7 @@ class LetCommandTest : VimTestCase() {
 
     // 'number' is a local-to-window toggle option
     enterCommand("let &number = 12")
-    val globalValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL)
+    val globalValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL(fixture.editor.vim))
     val localValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.LOCAL(fixture.editor.vim))
     assertEquals(12, globalValue.value)
     assertEquals(12, localValue.value)
@@ -150,7 +150,7 @@ class LetCommandTest : VimTestCase() {
 
     // 'number' is a local-to-window option
     enterCommand("let &l:number = 12")
-    val globalValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL)
+    val globalValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL(fixture.editor.vim))
     val localValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.LOCAL(fixture.editor.vim))
     assertEquals(0, globalValue.value)
     assertEquals(12, localValue.value)
@@ -163,7 +163,7 @@ class LetCommandTest : VimTestCase() {
 
     // 'number' is a local-to-window option
     enterCommand("let &g:number = 12")
-    val globalValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL)
+    val globalValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL(fixture.editor.vim))
     val localValue = injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.LOCAL(fixture.editor.vim))
     assertEquals(12, globalValue.value)
     assertEquals(0, localValue.value)
@@ -177,7 +177,7 @@ class LetCommandTest : VimTestCase() {
     // 'scroll' is a local to window number option
     enterCommand("set scroll=42")
     enterCommand("let &scroll+=10")
-    val globalValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.GLOBAL)
+    val globalValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.GLOBAL(fixture.editor.vim))
     val localValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.LOCAL(fixture.editor.vim))
     assertEquals(52, globalValue.value)
     assertEquals(52, localValue.value)
@@ -190,7 +190,7 @@ class LetCommandTest : VimTestCase() {
 
     enterCommand("setlocal scroll=42")
     enterCommand("let &l:scroll+=10")
-    val globalValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.GLOBAL)
+    val globalValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.GLOBAL(fixture.editor.vim))
     val localValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.LOCAL(fixture.editor.vim))
     assertEquals(0, globalValue.value)
     assertEquals(52, localValue.value)
@@ -203,7 +203,7 @@ class LetCommandTest : VimTestCase() {
 
     enterCommand("setglobal scroll=42")
     enterCommand("let &g:scroll+=10")
-    val globalValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.GLOBAL)
+    val globalValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.GLOBAL(fixture.editor.vim))
     val localValue = injector.optionGroup.getOptionValue(Options.scroll, OptionAccessScope.LOCAL(fixture.editor.vim))
     assertEquals(52, globalValue.value)
     assertEquals(0, localValue.value)
diff --git a/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/SetCommandTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/SetCommandTest.kt
index ce775d245..9477e7d05 100644
--- a/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/SetCommandTest.kt
+++ b/src/test/java/org/jetbrains/plugins/ideavim/ex/implementation/commands/SetCommandTest.kt
@@ -77,7 +77,7 @@ class SetCommandTest : VimTestCase() {
     // Should have the same effect as `:set` (although `:set` doesn't allow assigning a number to a boolean)
     // I.e. this sets the local value and the per-window "global" value
     enterCommand("let &nu=1000")
-    assertEquals(1000, injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL).asDouble().toInt())
+    assertEquals(1000, injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.GLOBAL(fixture.editor.vim)).asDouble().toInt())
     assertEquals(1000, injector.optionGroup.getOptionValue(Options.number, OptionAccessScope.LOCAL(fixture.editor.vim)).asDouble().toInt())
     assertCommandOutput("set number?", "  number\n")
   }
diff --git a/src/test/java/org/jetbrains/plugins/ideavim/extension/CommonExtensionTests.kt b/src/test/java/org/jetbrains/plugins/ideavim/extension/CommonExtensionTests.kt
index 5e1ff3110..e992889ea 100644
--- a/src/test/java/org/jetbrains/plugins/ideavim/extension/CommonExtensionTests.kt
+++ b/src/test/java/org/jetbrains/plugins/ideavim/extension/CommonExtensionTests.kt
@@ -309,12 +309,12 @@ class PlugMissingKeysTest : VimTestCase() {
 
   private fun assertOptionSet(name: String) {
     val option = injector.optionGroup.getOption(name)!!
-    assertTrue(injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL).asBoolean())
+    assertTrue(injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)).asBoolean())
   }
 
   private fun assertOptionUnset(name: String) {
     val option = injector.optionGroup.getOption(name)!!
-    assertFalse(injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL).asBoolean())
+    assertFalse(injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)).asBoolean())
   }
 
   private fun executeLikeVimrc(vararg text: String) {
diff --git a/src/test/java/org/jetbrains/plugins/ideavim/impl/OptionsVerificator.kt b/src/test/java/org/jetbrains/plugins/ideavim/impl/OptionsVerificator.kt
index 6b82c486b..d6e1203a6 100644
--- a/src/test/java/org/jetbrains/plugins/ideavim/impl/OptionsVerificator.kt
+++ b/src/test/java/org/jetbrains/plugins/ideavim/impl/OptionsVerificator.kt
@@ -422,7 +422,10 @@ class OptionsSetup(private val options: List<Pair<Option<out VimDataType>, VimDa
         // compiler will treat the value as type `CapturedType(out VimDataType)`, which cannot be passed in (producer vs
         // consumer)
         @Suppress("UNCHECKED_CAST") val option = key as Option<VimDataType>
-        injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, value)
+
+        // We don't have a window at this point, so we can only pass null. This means we can't set the global value of a
+        // local option (local-to-window's global options are per-window), or we will hit asserts
+        injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(null), value)
       }
     }
   }
diff --git a/src/test/java/org/jetbrains/plugins/ideavim/option/EffectiveOptionChangeListenerTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/option/EffectiveOptionChangeListenerTest.kt
index 7b2508ec2..e328df087 100644
--- a/src/test/java/org/jetbrains/plugins/ideavim/option/EffectiveOptionChangeListenerTest.kt
+++ b/src/test/java/org/jetbrains/plugins/ideavim/option/EffectiveOptionChangeListenerTest.kt
@@ -22,8 +22,8 @@ import com.maddyhome.idea.vim.api.injector
 import com.maddyhome.idea.vim.newapi.ij
 import com.maddyhome.idea.vim.newapi.vim
 import com.maddyhome.idea.vim.options.EffectiveOptionValueChangeListener
-import com.maddyhome.idea.vim.options.OptionDeclaredScope
 import com.maddyhome.idea.vim.options.OptionAccessScope
+import com.maddyhome.idea.vim.options.OptionDeclaredScope
 import com.maddyhome.idea.vim.options.StringOption
 import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
 import org.jetbrains.plugins.ideavim.SkipNeovimReason
@@ -116,7 +116,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() {
   @Test
   fun `test listener called for all editors when global option changes`() {
     val option = addOption(OptionDeclaredScope.GLOBAL)
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue"))
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue"))
 
     assertNotifiedEditors(originalEditor, splitWindow, otherBufferWindow)
   }
@@ -140,7 +140,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() {
   @Test
   fun `test listener not called when local-to-buffer option changes at global scope`() {
     val option = addOption(OptionDeclaredScope.LOCAL_TO_BUFFER)
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue"))
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue"))
 
     assertNotifiedEditors()
   }
@@ -164,7 +164,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() {
   @Test
   fun `test listener not called when local-to-window option changes at global scope`() {
     val option = addOption(OptionDeclaredScope.LOCAL_TO_WINDOW)
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue"))
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue"))
 
     assertNotifiedEditors()
   }
@@ -188,7 +188,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() {
   @Test
   fun `test listener called for all editors when unset global-local local-to-buffer option changes at global scope`() {
     val option = addOption(OptionDeclaredScope.GLOBAL_OR_LOCAL_TO_BUFFER)
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue"))
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue"))
 
     assertNotifiedEditors(originalEditor, splitWindow, otherBufferWindow)
   }
@@ -226,7 +226,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() {
     injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(otherBufferWindow.vim), VimString("localValue"))
     Listener.notifiedEditors.clear()
 
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue"))
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue"))
 
     assertNotifiedEditors(originalEditor, splitWindow)
   }
@@ -234,7 +234,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() {
   @Test
   fun `test listener called for all editors when unset global-local local-to-window option changes at global scope`() {
     val option = addOption(OptionDeclaredScope.GLOBAL_OR_LOCAL_TO_WINDOW)
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue"))
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue"))
 
     assertNotifiedEditors(originalEditor, splitWindow, otherBufferWindow)
   }
@@ -272,7 +272,7 @@ class EffectiveOptionChangeListenerTest : VimTestCase() {
     injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(otherBufferWindow.vim), VimString("localValue"))
     Listener.notifiedEditors.clear()
 
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue"))
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), VimString("newValue"))
 
     assertNotifiedEditors(originalEditor, splitWindow)
   }
diff --git a/src/test/java/org/jetbrains/plugins/ideavim/option/GlobalOptionChangeListenerTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/option/GlobalOptionChangeListenerTest.kt
index d15b402b1..bde39e5ac 100644
--- a/src/test/java/org/jetbrains/plugins/ideavim/option/GlobalOptionChangeListenerTest.kt
+++ b/src/test/java/org/jetbrains/plugins/ideavim/option/GlobalOptionChangeListenerTest.kt
@@ -11,8 +11,8 @@ package org.jetbrains.plugins.ideavim.option
 import com.maddyhome.idea.vim.api.injector
 import com.maddyhome.idea.vim.newapi.vim
 import com.maddyhome.idea.vim.options.GlobalOptionChangeListener
-import com.maddyhome.idea.vim.options.OptionDeclaredScope
 import com.maddyhome.idea.vim.options.OptionAccessScope
+import com.maddyhome.idea.vim.options.OptionDeclaredScope
 import com.maddyhome.idea.vim.options.StringOption
 import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
 import org.jetbrains.plugins.ideavim.SkipNeovimReason
@@ -48,7 +48,8 @@ class GlobalOptionChangeListenerTest: VimTestCase() {
       injector.optionGroup.addOption(option)
       injector.optionGroup.addGlobalOptionChangeListener(option, Listener)
 
-      injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, VimString("newValue"))
+      // Global value of a global option, we can pass null
+      injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(null), VimString("newValue"))
 
       assertTrue(Listener.called)
     }
diff --git a/src/test/java/org/jetbrains/plugins/ideavim/option/OptionAccessScopeTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/option/OptionAccessScopeTest.kt
index bc2cbab80..521a8aed8 100644
--- a/src/test/java/org/jetbrains/plugins/ideavim/option/OptionAccessScopeTest.kt
+++ b/src/test/java/org/jetbrains/plugins/ideavim/option/OptionAccessScopeTest.kt
@@ -51,9 +51,9 @@ class OptionAccessScopeTest: VimTestCase() {
     injector.optionGroup.addOption(option)
 
     val globalValue = VimInt(100)
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue)
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue)
 
-    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -67,7 +67,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val setValue = VimInt(100)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), setValue)
 
-    assertEquals(setValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(setValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(setValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(setValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -80,7 +80,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val effectiveValue = VimInt(100)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue)
 
-    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -94,9 +94,9 @@ class OptionAccessScopeTest: VimTestCase() {
     injector.optionGroup.addOption(option)
 
     val globalValue = VimInt(100)
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue)
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue)
 
-    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -110,7 +110,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val localValue = VimInt(100)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue)
 
-    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -124,7 +124,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val effectiveValue = VimInt(100)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue)
 
-    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -138,9 +138,9 @@ class OptionAccessScopeTest: VimTestCase() {
     injector.optionGroup.addOption(option)
 
     val globalValue = VimInt(100)
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue)
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue)
 
-    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -154,7 +154,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val localValue = VimInt(100)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue)
 
-    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -168,7 +168,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val effectiveValue = VimInt(100)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue)
 
-    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -203,9 +203,9 @@ class OptionAccessScopeTest: VimTestCase() {
     injector.optionGroup.addOption(option)
 
     val globalValue = VimInt(100)
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue)
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue)
 
-    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -219,7 +219,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val localValue = VimInt(100)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue)
 
-    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -233,7 +233,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val effectiveValue = VimInt(100)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue)
 
-    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -250,7 +250,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val newValue = VimInt(200)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), newValue)
 
-    assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -263,9 +263,9 @@ class OptionAccessScopeTest: VimTestCase() {
     injector.optionGroup.addOption(option)
 
     val globalValue = VimInt.ZERO
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue)
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue)
 
-    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -279,7 +279,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val localValue = VimInt.ZERO
     injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue)
 
-    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -293,7 +293,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val effectiveValue = VimInt.ZERO
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue)
 
-    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -310,7 +310,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val newValue = VimInt(100)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), newValue)
 
-    assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -323,9 +323,9 @@ class OptionAccessScopeTest: VimTestCase() {
     injector.optionGroup.addOption(option)
 
     val globalValue = VimString("lorem ipsum")
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue)
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue)
 
-    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -339,7 +339,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val localValue = VimString("lorem ipsum")
     injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue)
 
-    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -353,7 +353,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val effectiveValue = VimString("lorem ipsum")
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue)
 
-    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -371,7 +371,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val newValue = VimString("dolor sit amet")
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), newValue)
 
-    assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -386,9 +386,9 @@ class OptionAccessScopeTest: VimTestCase() {
     injector.optionGroup.addOption(option)
 
     val globalValue = VimInt(100)
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue)
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue)
 
-    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -402,7 +402,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val localValue = VimInt(100)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue)
 
-    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -416,7 +416,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val effectiveValue = VimInt(100)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue)
 
-    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -433,7 +433,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val newValue = VimInt(200)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), newValue)
 
-    assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -448,9 +448,9 @@ class OptionAccessScopeTest: VimTestCase() {
     injector.optionGroup.addOption(option)
 
     val globalValue = VimInt.ZERO
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue)
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue)
 
-    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -464,7 +464,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val localValue = VimInt.ZERO
     injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue)
 
-    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -478,7 +478,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val effectiveValue = VimInt.ZERO
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue)
 
-    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -495,7 +495,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val newValue = VimInt(100)
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), newValue)
 
-    assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -508,9 +508,9 @@ class OptionAccessScopeTest: VimTestCase() {
     injector.optionGroup.addOption(option)
 
     val globalValue = VimString("lorem ipsum")
-    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, globalValue)
+    injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim), globalValue)
 
-    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(globalValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -524,7 +524,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val localValue = VimString("lorem ipsum")
     injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim), localValue)
 
-    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(defaultValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(localValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -538,7 +538,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val effectiveValue = VimString("lorem ipsum")
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), effectiveValue)
 
-    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(effectiveValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
@@ -556,7 +556,7 @@ class OptionAccessScopeTest: VimTestCase() {
     val newValue = VimString("dolor sit amet")
     injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim), newValue)
 
-    assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL))
+    assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim)))
     assertEquals(option.unsetValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(fixture.editor.vim)))
     assertEquals(newValue, injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(fixture.editor.vim)))
   }
diff --git a/src/test/java/org/jetbrains/plugins/ideavim/option/OptionDeclaredScopeTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/option/OptionDeclaredScopeTest.kt
index 8a4bd2d23..e2eea6a26 100644
--- a/src/test/java/org/jetbrains/plugins/ideavim/option/OptionDeclaredScopeTest.kt
+++ b/src/test/java/org/jetbrains/plugins/ideavim/option/OptionDeclaredScopeTest.kt
@@ -20,8 +20,8 @@ import com.intellij.util.childScope
 import com.maddyhome.idea.vim.api.injector
 import com.maddyhome.idea.vim.newapi.vim
 import com.maddyhome.idea.vim.options.Option
-import com.maddyhome.idea.vim.options.OptionDeclaredScope
 import com.maddyhome.idea.vim.options.OptionAccessScope
+import com.maddyhome.idea.vim.options.OptionDeclaredScope
 import com.maddyhome.idea.vim.options.StringOption
 import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
 import org.jetbrains.plugins.ideavim.SkipNeovimReason
@@ -377,7 +377,7 @@ class OptionDeclaredScopeTest : VimTestCase() {
   }
 
   private fun Option<VimString>.setGlobalValue() =
-    injector.optionGroup.setOptionValue(this, OptionAccessScope.GLOBAL, setValue)
+    injector.optionGroup.setOptionValue(this, OptionAccessScope.GLOBAL(fixture.editor.vim), setValue)
 
   private fun Option<VimString>.setLocalValue(editor: Editor) =
     injector.optionGroup.setOptionValue(this, OptionAccessScope.LOCAL(editor.vim), setValue)
@@ -387,7 +387,7 @@ class OptionDeclaredScopeTest : VimTestCase() {
   }
 
   private fun getGlobalValue(option: Option<VimString>) =
-    injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)
+    injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(fixture.editor.vim))
 
   private fun getLocalValue(option: Option<VimString>, editor: Editor) =
     injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(editor.vim))
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/OptionProperties.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/OptionProperties.kt
index 095cc6ad8..5d12611ee 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/OptionProperties.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/OptionProperties.kt
@@ -17,7 +17,7 @@ import com.maddyhome.idea.vim.options.OptionAccessScope
  * buffer (document) or window (editor).
  */
 @Suppress("unused", "SpellCheckingInspection")
-public open class GlobalOptions(scope: OptionAccessScope = OptionAccessScope.GLOBAL): OptionsPropertiesBase(scope) {
+public open class GlobalOptions(scope: OptionAccessScope): OptionsPropertiesBase(scope) {
   public val clipboard: StringListOptionValue by optionProperty(Options.clipboard)
   public var digraph: Boolean by optionProperty(Options.digraph)
   public var gdefault: Boolean by optionProperty(Options.gdefault)
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/Options.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/Options.kt
index e5acfe49b..b443d6829 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/Options.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/Options.kt
@@ -13,13 +13,13 @@ import com.maddyhome.idea.vim.ex.exExceptionMessage
 import com.maddyhome.idea.vim.helper.StrictMode
 import com.maddyhome.idea.vim.options.NumberOption
 import com.maddyhome.idea.vim.options.Option
+import com.maddyhome.idea.vim.options.OptionAccessScope
 import com.maddyhome.idea.vim.options.OptionConstants
 import com.maddyhome.idea.vim.options.OptionDeclaredScope.GLOBAL
 import com.maddyhome.idea.vim.options.OptionDeclaredScope.GLOBAL_OR_LOCAL_TO_BUFFER
 import com.maddyhome.idea.vim.options.OptionDeclaredScope.GLOBAL_OR_LOCAL_TO_WINDOW
 import com.maddyhome.idea.vim.options.OptionDeclaredScope.LOCAL_TO_BUFFER
 import com.maddyhome.idea.vim.options.OptionDeclaredScope.LOCAL_TO_WINDOW
-import com.maddyhome.idea.vim.options.OptionAccessScope
 import com.maddyhome.idea.vim.options.StringListOption
 import com.maddyhome.idea.vim.options.StringOption
 import com.maddyhome.idea.vim.options.ToggleOption
@@ -265,8 +265,8 @@ public object Options {
   public val shellcmdflag: StringOption = addOption(object : StringOption("shellcmdflag", GLOBAL, "shcf", "") {
     override val defaultValue: VimString
       get() {
-        // Default value depends on the "shell" option
-        val shell = injector.optionGroup.getOptionValue(shell, OptionAccessScope.GLOBAL).asString()
+        // Default value depends on the `'shell'` option. Since it's a global option, we can pass null as the editor
+        val shell = injector.optionGroup.getOptionValue(shell, OptionAccessScope.GLOBAL(null)).asString()
         return VimString(
           when {
             injector.systemInfoService.isWindows && shell.contains("powershell") -> "-Command"
@@ -280,8 +280,8 @@ public object Options {
   public val shellxquote: StringOption = addOption(object : StringOption("shellxquote", GLOBAL, "sxq", "") {
     override val defaultValue: VimString
       get() {
-        // Default value depends on the "shell" option
-        val shell = injector.optionGroup.getOptionValue(shell, OptionAccessScope.GLOBAL).asString()
+        // Default value depends on the `'shell'` option. Since it's a global option, we can pass null as the editor
+        val shell = injector.optionGroup.getOptionValue(shell, OptionAccessScope.GLOBAL(null)).asString()
         return VimString(
           when {
             injector.systemInfoService.isWindows && shell == "cmd.exe" -> "("
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimOptionGroupBase.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimOptionGroupBase.kt
index df74398f2..5afc6a08f 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimOptionGroupBase.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/api/VimOptionGroupBase.kt
@@ -22,7 +22,6 @@ import com.maddyhome.idea.vim.options.ToggleOption
 import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType
 
 public abstract class VimOptionGroupBase : VimOptionGroup {
-  private val globalOptionsAccessor = GlobalOptions()
   private val globalValues = mutableMapOf<String, VimDataType>()
   private val globalParsedValues = mutableMapOf<String, Any>()
   private val globalOptionListeners = MultiSet<String, GlobalOptionChangeListener>()
@@ -114,7 +113,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
       mutableMapOf<String, VimDataType>().also { bufferOptions ->
         getAllOptions().forEach { option ->
           if (option.declaredScope == LOCAL_TO_BUFFER) {
-            bufferOptions[option.name] = getGlobalOptionValue(option)
+            bufferOptions[option.name] = getGlobalOptionValue(option, editor)
           } else if (option.declaredScope == GLOBAL_OR_LOCAL_TO_BUFFER) {
             bufferOptions[option.name] = option.unsetValue
           }
@@ -157,7 +156,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
     val localValues = getWindowLocalOptionStorage(editor)
     getAllOptions().forEach { option ->
       if (option.declaredScope == LOCAL_TO_WINDOW) {
-        localValues[option.name] = getGlobalOptionValue(option)
+        localValues[option.name] = getGlobalOptionValue(option, editor)
       }
       else if (option.declaredScope == GLOBAL_OR_LOCAL_TO_WINDOW) {
         localValues[option.name] = option.unsetValue
@@ -169,13 +168,13 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
   // These functions are here so we know what the semantics should be when it comes time to implement.
   // Default to getting the per-instance global value for now (per-instance meaning per VimOptionGroup service instance)
   // Set does nothing, because it's called with the current "global" value, which would be a no-op
-  private fun getPerWindowGlobalOptionValue(option: Option<VimDataType>, editor: VimEditor?) = getGlobalOptionValue(option)
+  private fun getPerWindowGlobalOptionValue(option: Option<VimDataType>, editor: VimEditor?) = getGlobalOptionValue(option, editor)
   private fun setPerWindowGlobalOptionValue(option: Option<VimDataType>, editor: VimEditor, value: VimDataType) {}
 
   override fun <T : VimDataType> getOptionValue(option: Option<T>, scope: OptionAccessScope): T = when (scope) {
     is OptionAccessScope.EFFECTIVE -> getEffectiveOptionValue(option, scope.editor)
     is OptionAccessScope.LOCAL -> getLocalOptionValue(option, scope.editor)
-    OptionAccessScope.GLOBAL -> getGlobalOptionValue(option)
+    is OptionAccessScope.GLOBAL -> getGlobalOptionValue(option, scope.editor)
   }
 
   override fun <T : VimDataType> setOptionValue(option: Option<T>, scope: OptionAccessScope, value: T) {
@@ -184,7 +183,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
     when (scope) {
       is OptionAccessScope.EFFECTIVE -> setEffectiveOptionValue(option, scope.editor, value)
       is OptionAccessScope.LOCAL -> setLocalOptionValue(option, scope.editor, value)
-      OptionAccessScope.GLOBAL -> setGlobalOptionValue(option, value)
+      is OptionAccessScope.GLOBAL -> setGlobalOptionValue(option, scope.editor, value)
     }
   }
 
@@ -210,10 +209,10 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
     }
 
     // Unless the user is calling this method multiple times with different providers, we can be confident this cast
-    // will succeed
+    // will succeed. Editor will only be null with global options, so it's safe to use null
     @Suppress("UNCHECKED_CAST")
     return cachedValues.getOrPut(option.name) {
-      provider(getOptionValue(option, if (editor == null) OptionAccessScope.GLOBAL else OptionAccessScope.EFFECTIVE(editor)))
+      provider(getOptionValue(option, if (editor == null) OptionAccessScope.GLOBAL(null) else OptionAccessScope.EFFECTIVE(editor)))
     } as TData
   }
 
@@ -223,7 +222,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
   override fun resetAllOptions(editor: VimEditor) {
     // Reset all options to default values at global and local scope. This will fire any listeners and clear any caches
     Options.getAllOptions().forEach { option ->
-      resetDefaultValue(option, OptionAccessScope.GLOBAL)
+      resetDefaultValue(option, OptionAccessScope.GLOBAL(editor))
       when (option.declaredScope) {
         GLOBAL -> {}
         LOCAL_TO_BUFFER, LOCAL_TO_WINDOW -> resetDefaultValue(option, OptionAccessScope.LOCAL(editor))
@@ -235,11 +234,17 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
   }
 
   override fun resetAllOptionsForTesting() {
-    Options.getAllOptions().forEach {
-      resetDefaultValue(it, OptionAccessScope.GLOBAL)
-    }
-    // During testing, this collection is usually empty
+    // During testing, this collection is usually empty. Just in case, make sure all editors have default options
     injector.editorGroup.localEditors().forEach { resetAllOptions(it) }
+
+    // Make sure we reset global options even if we don't have any editors. This fires listeners and clears caches
+    Options.getAllOptions().filter { it.declaredScope == GLOBAL }.forEach { resetDefaultValue(it, OptionAccessScope.GLOBAL(null)) }
+
+    // Reset global value of other options manually, without firing listeners or clearing caches. This is safe because
+    // we only cache values or listen to changes for the effective values of local options (and not global-local). But
+    // local-to-window options will store global values per-window (which we don't have). So this will have the same
+    // result as resetDefaultValue but without the asserts for setting a local option without a window.
+    Options.getAllOptions().filter { it.declaredScope != GLOBAL }.forEach { globalValues[it.name] = it.defaultValue }
   }
 
   override fun addOption(option: Option<out VimDataType>) {
@@ -290,7 +295,8 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
     option.overrideDefaultValue(newDefaultValue)
   }
 
-  override fun getGlobalOptions(): GlobalOptions = globalOptionsAccessor
+  // We can pass null as the editor because we are only accessing global options
+  override fun getGlobalOptions(): GlobalOptions = GlobalOptions(OptionAccessScope.GLOBAL(null))
 
   override fun getEffectiveOptions(editor: VimEditor): EffectiveOptions = EffectiveOptions(OptionAccessScope.EFFECTIVE(editor))
 
@@ -319,15 +325,35 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
   }
 
 
-  private fun <T : VimDataType> getGlobalOptionValue(option: Option<T>): T {
+  private fun <T : VimDataType> getGlobalOptionValue(option: Option<T>, editor: VimEditor?): T {
+    if (editor == null) {
+      check(option.declaredScope == GLOBAL
+        || option.declaredScope == GLOBAL_OR_LOCAL_TO_BUFFER
+        || option.declaredScope == GLOBAL_OR_LOCAL_TO_WINDOW) {
+        "Editor must be provided for local option"
+      }
+    }
     // We set the value via Option<T> so it's safe to cast to T. But note that the value might be null because we don't
     // explicitly populate global option values in the same way we do local options
+    // TODO: Use editor to get global value of non-global options
     @Suppress("UNCHECKED_CAST")
     return globalValues[option.name] as? T ?: option.defaultValue
   }
 
-  private fun <T : VimDataType> setGlobalOptionValue(option: Option<T>, value: T) {
+  private fun <T : VimDataType> setGlobalOptionValue(option: Option<T>, editor: VimEditor?, value: T) {
+    if (editor == null) {
+      // Ideally, we would require an editor for all options apart from GLOBAL, but we want to set some global-local
+      // options from tests. Since we only really need the editor for local-to-window, this check is fine
+      check(option.declaredScope == GLOBAL
+              || option.declaredScope == GLOBAL_OR_LOCAL_TO_BUFFER
+              || option.declaredScope == GLOBAL_OR_LOCAL_TO_WINDOW) {
+        "Editor must be provided for local options"
+      }
+    }
+
+    // TODO: Use editor for local-to-window options
     doSetGlobalOptionValue(option, value)
+
     when (option.declaredScope) {
       GLOBAL -> {
         onGlobalOptionValueChanged(option)
@@ -353,16 +379,16 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
    */
   private fun <T : VimDataType> getEffectiveOptionValue(option: Option<T>, editor: VimEditor) =
     when (option.declaredScope) {
-      GLOBAL -> getGlobalOptionValue(option)
+      GLOBAL -> getGlobalOptionValue(option, editor)
       LOCAL_TO_BUFFER -> getBufferLocalOptionValue(option, editor)
       LOCAL_TO_WINDOW -> getWindowLocalOptionValue(option, editor)
       GLOBAL_OR_LOCAL_TO_BUFFER -> {
         tryGetBufferLocalOptionValue(option, editor).takeUnless { it == option.unsetValue }
-          ?: getGlobalOptionValue(option)
+          ?: getGlobalOptionValue(option, editor)
       }
       GLOBAL_OR_LOCAL_TO_WINDOW -> {
         tryGetWindowLocalOptionValue(option, editor).takeUnless { it == option.unsetValue }
-          ?: getGlobalOptionValue(option)
+          ?: getGlobalOptionValue(option, editor)
       }
     }
 
@@ -422,7 +448,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
 
   private fun <T : VimDataType> getLocalOptionValue(option: Option<T>, editor: VimEditor) =
     when (option.declaredScope) {
-      GLOBAL -> getGlobalOptionValue(option)
+      GLOBAL -> getGlobalOptionValue(option, editor)
       LOCAL_TO_BUFFER -> getBufferLocalOptionValue(option, editor)
       LOCAL_TO_WINDOW -> getWindowLocalOptionValue(option, editor)
       GLOBAL_OR_LOCAL_TO_BUFFER -> {
@@ -479,7 +505,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
     // options dynamically, e.g. registering an extension. We fall back to global option, just in case
     return tryGetBufferLocalOptionValue(option, editor).also {
       strictModeAssert(it != null, "Buffer local option value is missing: ${option.name}")
-    } ?: getGlobalOptionValue(option)
+    } ?: getGlobalOptionValue(option, editor)
   }
 
   private fun <T : VimDataType> tryGetBufferLocalOptionValue(option: Option<T>, editor: VimEditor): T? {
@@ -508,7 +534,7 @@ public abstract class VimOptionGroupBase : VimOptionGroup {
     // options dynamically, e.g. registering an extension. We fall back to global option, just in case
     val value = tryGetWindowLocalOptionValue(option, editor)
     strictModeAssert(value != null, "Window local option value is missing: ${option.name}")
-    return value ?: getGlobalOptionValue(option)
+    return value ?: getGlobalOptionValue(option, editor)
   }
 
   private fun <T : VimDataType> tryGetWindowLocalOptionValue(option: Option<T>, editor: VimEditor): T? {
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/option/ToggleOption.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/option/ToggleOption.kt
index 7d775d555..39a7aec60 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/option/ToggleOption.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/option/ToggleOption.kt
@@ -23,5 +23,7 @@ public open class ToggleOption(private val option: com.maddyhome.idea.vim.option
    * COMPATIBILITY-LAYER: Method added
    * Please see: https://jb.gg/zo8n0r
    */
-  public fun isSet(): Boolean = injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL).asBoolean()
+  // We have to use the fallback window to avoid any possible asserts. This is not ideal and should not be replicated
+  // in non-deprecated code
+  public fun isSet(): Boolean = injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(injector.fallbackWindow)).asBoolean()
 }
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/OptionAccessScope.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/OptionAccessScope.kt
index 8091d48eb..007cc7625 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/OptionAccessScope.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/OptionAccessScope.kt
@@ -25,9 +25,10 @@ public sealed class OptionAccessScope {
    * "global" value is a per-window copy, and not a truly global value. See [OptionDeclaredScope.LOCAL_TO_WINDOW] for
    * more details.
    *
-   * TODO: Support per-window global options. This requires passing an editor to GLOBAL
+   * @param editor  The editor to access global option values from. This can only be `null` for global and global-local
+   * options.
    */
-  public object GLOBAL : OptionAccessScope()
+  public class GLOBAL(public val editor: VimEditor?) : OptionAccessScope()
 
   /**
    * Explicitly get or set the local value of the option, relative to the given editor
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/helpers/KeywordOptionHelper.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/helpers/KeywordOptionHelper.kt
index f2e5de87b..972a9c821 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/helpers/KeywordOptionHelper.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/options/helpers/KeywordOptionHelper.kt
@@ -47,8 +47,10 @@ public object KeywordOptionHelper {
   // Perhaps pass in VimEditor, or allow retrieving the list of KeywordSpec
   @Deprecated("Only maintained for compatibility. Does not handle local-to-buffer iskeyword option")
   public fun toRegex(): List<String> {
-    // 'iskeyword' is a local-to-buffer option, but we're not passed an editor. We have to use the global value
-    val isKeyword = injector.optionGroup.getOptionValue(Options.iskeyword, OptionAccessScope.GLOBAL).value
+    // 'iskeyword' is a local-to-buffer option, but we're not passed an editor. We have to use the global value. We also
+    // have to use the fallback window to avoid any asserts about accessing a non-global option as a global option.
+    // This is not ideal and should not be replicated in non-deprecated code
+    val isKeyword = injector.optionGroup.getOptionValue(Options.iskeyword, OptionAccessScope.GLOBAL(injector.fallbackWindow)).value
     val specs = valuesToValidatedAndReversedSpecs(parseValues(isKeyword)) ?: emptyList()
     return specs.map {
       it.initializeValues()
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/LetCommand.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/LetCommand.kt
index 4e5a8d872..4291ec012 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/LetCommand.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/LetCommand.kt
@@ -183,7 +183,7 @@ public data class LetCommand(
             ?: throw exExceptionMessage("E518", variable.originalString)
           val newValue = operator.getNewValue(optionValue, expression.evaluate(editor, context, this))
           when (variable.scope) {
-            Scope.GLOBAL_VARIABLE -> injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL, newValue)
+            Scope.GLOBAL_VARIABLE -> injector.optionGroup.setOptionValue(option, OptionAccessScope.GLOBAL(editor), newValue)
             Scope.LOCAL_VARIABLE -> injector.optionGroup.setOptionValue(option, OptionAccessScope.LOCAL(editor), newValue)
             null -> injector.optionGroup.setOptionValue(option, OptionAccessScope.EFFECTIVE(editor), newValue)
             else -> throw ExException("Invalid option scope")
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/PackaddCommand.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/PackaddCommand.kt
index fce154e50..aed919f45 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/PackaddCommand.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/PackaddCommand.kt
@@ -27,7 +27,7 @@ public class PackaddCommand(public val ranges: Ranges, public val argument: Stri
   override fun processCommand(editor: VimEditor, context: ExecutionContext, operatorArguments: OperatorArguments): ExecutionResult {
     if (argument == "matchit" || (argument.startsWith("!") && argument.drop(1).trim() == "matchit")) {
       val option = injector.optionGroup.getOption("matchit") as ToggleOption
-      injector.optionGroup.setToggleOption(option, OptionAccessScope.GLOBAL)
+      injector.optionGroup.setToggleOption(option, OptionAccessScope.GLOBAL(editor))
     }
     return ExecutionResult.Success
   }
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt
index 1ab80f6d6..6cb3a6692 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt
@@ -24,8 +24,8 @@ import com.maddyhome.idea.vim.ex.ranges.Ranges
 import com.maddyhome.idea.vim.helper.Msg
 import com.maddyhome.idea.vim.options.NumberOption
 import com.maddyhome.idea.vim.options.Option
-import com.maddyhome.idea.vim.options.OptionDeclaredScope
 import com.maddyhome.idea.vim.options.OptionAccessScope
+import com.maddyhome.idea.vim.options.OptionDeclaredScope
 import com.maddyhome.idea.vim.options.StringListOption
 import com.maddyhome.idea.vim.options.StringOption
 import com.maddyhome.idea.vim.options.ToggleOption
@@ -46,7 +46,7 @@ public data class SetCommand(val ranges: Ranges, val argument: String) : SetComm
 
 @ExCommand(command = "setg[lobal]")
 public data class SetglobalCommand(val ranges: Ranges, val argument: String) : SetCommandBase(ranges, argument) {
-  override fun getScope(editor: VimEditor): OptionAccessScope = OptionAccessScope.GLOBAL
+  override fun getScope(editor: VimEditor): OptionAccessScope = OptionAccessScope.GLOBAL(editor)
 }
 
 @ExCommand(command = "setl[ocal]")
@@ -153,7 +153,7 @@ public fun parseOptionLine(editor: VimEditor, args: String, scope: OptionAccessS
           // string global-local option to effective scope, Vim's behaviour matches setting that option at effective
           // scope. That is, it sets the global value (a no-op) and resets the local value.
           val option = getValidOption(token.dropLast(1), token)
-          val globalValue = optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)
+          val globalValue = optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(editor))
           optionGroup.setOptionValue(option, scope, globalValue)
         }
         else -> {
@@ -258,7 +258,7 @@ private fun showOptions(
       when (scope) {
         is OptionAccessScope.EFFECTIVE -> appendLine("--- Options ---")
         is OptionAccessScope.LOCAL -> appendLine("--- Local option values ---")
-        OptionAccessScope.GLOBAL -> appendLine("--- Global option values ---")
+        is OptionAccessScope.GLOBAL -> appendLine("--- Global option values ---")
       }
     }
 
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/expressions/OptionExpression.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/expressions/OptionExpression.kt
index 591d6ec6e..c654cc2f9 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/expressions/OptionExpression.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/expressions/OptionExpression.kt
@@ -22,7 +22,7 @@ public data class OptionExpression(val scope: Scope?, val optionName: String) :
   override fun evaluate(editor: VimEditor, context: ExecutionContext, vimContext: VimLContext): VimDataType {
     val option = injector.optionGroup.getOption(optionName) ?: throw exExceptionMessage("E518", originalString)
     return when (scope) {
-      Scope.GLOBAL_VARIABLE -> injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL)
+      Scope.GLOBAL_VARIABLE -> injector.optionGroup.getOptionValue(option, OptionAccessScope.GLOBAL(editor))
       Scope.LOCAL_VARIABLE -> injector.optionGroup.getOptionValue(option, OptionAccessScope.LOCAL(editor))
       null -> injector.optionGroup.getOptionValue(option, OptionAccessScope.EFFECTIVE(editor))
       else -> throw ExException("Invalid option scope")
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/services/OptionService.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/services/OptionService.kt
index 83e746466..47accddce 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/services/OptionService.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/services/OptionService.kt
@@ -64,8 +64,9 @@ internal class OptionServiceImpl : OptionService {
   }
 
   override fun setOption(scope: OptionService.Scope, optionName: String, token: String) {
+    // Use the fallback window to avoid any possible asserts. Do not do this in non-deprecated code!
     val newScope = when (scope) {
-      is OptionService.Scope.GLOBAL -> OptionAccessScope.GLOBAL
+      is OptionService.Scope.GLOBAL -> OptionAccessScope.GLOBAL(injector.fallbackWindow)
       is OptionService.Scope.LOCAL -> OptionAccessScope.LOCAL(scope.editor)
     }
     val option = injector.optionGroup.getOption(optionName) ?: throw exExceptionMessage("E518", token)