in vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/commands/SetCommand.kt [103:220]
fun parseOptionLine(
editor: VimEditor,
context: ExecutionContext,
commandModifier: CommandModifier,
argument: String,
scope: OptionAccessScope,
) {
val optionGroup = injector.optionGroup
val columnFormat = commandModifier == CommandModifier.BANG
when {
argument.isEmpty() -> {
// No arguments mean we show only changed values
val changedOptions = optionGroup.getAllOptions()
.filter {
!optionGroup.isDefaultValue(
it,
scope
) && (!it.isHidden || (injector.application.isInternal() && !injector.application.isUnitTest()))
}
.map { Pair(it.name, it.name) }
showOptions(editor, context, changedOptions, scope, true, columnFormat)
return
}
argument == "all" -> {
val options = optionGroup.getAllOptions()
.filter { !it.isHidden || (injector.application.isInternal() && !injector.application.isUnitTest()) }
.map { Pair(it.name, it.name) }
showOptions(editor, context, options, scope, true, columnFormat)
return
}
argument == "all&" -> {
// Note that `all&` resets all options in the current editor at local and global scope. This includes global,
// global-local and local-to-buffer options, which will affect other windows. It does not affect the local values
// of local-to-window options in other windows
optionGroup.resetAllOptions(editor)
return
}
}
// We now have 1 or more option operators separator by spaces
var error: String? = null
val tokenizer = StringTokenizer(argument)
val toShow = mutableListOf<Pair<String, String>>()
while (tokenizer.hasMoreTokens()) {
var token = tokenizer.nextToken()
// See if a space has been backslashed, if not get the rest of the text
while (token.endsWith("\\")) {
token = token.take(token.length - 1) + ' '
if (tokenizer.hasMoreTokens()) {
token += tokenizer.nextToken()
}
}
val eq = token.indexOf('=')
val colon = token.indexOf(':')
val isKeyValueOperation = eq != -1 || colon != -1
if (!isKeyValueOperation) {
when {
token.endsWith("?") -> toShow.add(Pair(token.dropLast(1), token))
token.startsWith("no") -> optionGroup.unsetToggleOption(getValidToggleOption(token.substring(2), token), scope)
token.startsWith("inv") -> optionGroup.invertToggleOption(
getValidToggleOption(token.substring(3), token),
scope
)
token.endsWith("!") -> optionGroup.invertToggleOption(getValidToggleOption(token.dropLast(1), token), scope)
token.endsWith("&") -> optionGroup.resetToDefaultValue(getValidOption(token.dropLast(1), token), scope)
token.endsWith("<") -> optionGroup.resetToGlobalValue(getValidOption(token.dropLast(1), token), scope, editor)
else -> {
// `getOption` returns `Option<VimDataType>?`, but we need to treat it as `Option<out VimDataType>?` because
// `ToggleOption` derives from `Option<out VimDataType>`, and the compiler will complain if the types are
// different.
val option: Option<out VimDataType>? = optionGroup.getOption(token)
when (option) {
null -> error = injector.messages.message("E518", token)
is ToggleOption -> optionGroup.setToggleOption(option, scope)
else -> toShow.add(Pair(option.name, option.abbrev))
}
}
}
} else {
// This must be one of =, :, +=, -=, or ^=
// Could be option:value, option=value, option+=value, option-=value or option^=value
val idx = if (eq > 0) eq else colon
val op = if (eq > 0) token[eq - 1] else Char(0)
val end = if (eq > 0 && op in "+-^") idx - 1 else idx
// Get option name and value after operator
val optionName = token.take(end)
val option = getValidOption(optionName)
val existingValue = optionGroup.getOptionValue(option, scope)
val value = option.parseValue(token.substring(idx + 1), token)
val newValue = when (op) {
'+' -> appendValue(option, existingValue, value)
'^' -> prependValue(option, existingValue, value)
'-' -> removeValue(option, existingValue, value)
else -> value
} ?: throw exExceptionMessage("E474.arg", token)
optionGroup.setOptionValue(option, scope, newValue)
}
if (error != null) {
break
}
}
// Now show all options that were individually requested
if (toShow.isNotEmpty()) {
showOptions(editor, context, toShow, scope, false, columnFormat)
}
if (error != null) {
throw ExException(error)
}
}