mirror of
https://github.com/chylex/IntelliJ-IdeaVim.git
synced 2025-05-02 01:34:03 +02:00
Dictionary functions
This commit is contained in:
parent
769d900383
commit
e0b356c12d
src/com/maddyhome/idea/vim/vimscript/model
commands
datatypes
expressions
DictionaryExpression.ktFuncrefCallExpression.ktFunctionCallExpression.ktLambdaFunctionCallExpression.kt
functions/handlers
statements
test/org/jetbrains/plugins/ideavim/ex/implementation/functions
vimscript-info
@ -55,20 +55,15 @@ class CallCommand(val ranges: Ranges, val functionCall: Expression) : Command.Si
|
||||
return ExecutionResult.Success
|
||||
}
|
||||
|
||||
val name = (if (functionCall.scope != null) functionCall.scope.c + ":" else "") + functionCall.functionName
|
||||
val funcref = VariableService.getNullableVariableValue(Variable(functionCall.scope, functionCall.functionName), editor, context, parent)
|
||||
if (funcref is VimFuncref) {
|
||||
if (funcref.handler is DefinedFunctionHandler && funcref.handler.function.flags.contains(FunctionFlag.DICT) && funcref.handler.function.self == null) {
|
||||
throw ExException(
|
||||
"E725: Calling dict function without Dictionary: " +
|
||||
((if (functionCall.scope != null) functionCall.scope.c + ":" else "") + functionCall.functionName)
|
||||
)
|
||||
}
|
||||
funcref.handler.ranges = ranges
|
||||
funcref.execute(functionCall.arguments, editor, context, parent)
|
||||
funcref.execute(name, functionCall.arguments, editor, context, parent)
|
||||
return ExecutionResult.Success
|
||||
}
|
||||
|
||||
throw ExException("E117: Unknown function: ${if (functionCall.scope != null) functionCall.scope.c + ":" else ""}${functionCall.functionName}")
|
||||
throw ExException("E117: Unknown function: $name")
|
||||
} else if (functionCall is FuncrefCallExpression) {
|
||||
functionCall.evaluateWithRange(ranges, editor, context, parent)
|
||||
return ExecutionResult.Success
|
||||
|
@ -14,6 +14,7 @@ import com.maddyhome.idea.vim.vimscript.model.ExecutionResult
|
||||
import com.maddyhome.idea.vim.vimscript.model.Script
|
||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimBlob
|
||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDictionary
|
||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimFuncref
|
||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimInt
|
||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimList
|
||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
|
||||
@ -28,6 +29,7 @@ import com.maddyhome.idea.vim.vimscript.model.expressions.SublistExpression
|
||||
import com.maddyhome.idea.vim.vimscript.model.expressions.Variable
|
||||
import com.maddyhome.idea.vim.vimscript.model.expressions.operators.AssignmentOperator
|
||||
import com.maddyhome.idea.vim.vimscript.model.expressions.toVimDataType
|
||||
import com.maddyhome.idea.vim.vimscript.model.functions.DefinedFunctionHandler
|
||||
import com.maddyhome.idea.vim.vimscript.model.statements.FunctionDeclaration
|
||||
import com.maddyhome.idea.vim.vimscript.model.statements.FunctionFlag
|
||||
import com.maddyhome.idea.vim.vimscript.services.VariableService
|
||||
@ -66,15 +68,19 @@ data class LetCommand(
|
||||
if (operator != AssignmentOperator.ASSIGNMENT && !variableValue.dictionary.containsKey(dictKey)) {
|
||||
throw ExException("E716: Key not present in Dictionary: $dictKey")
|
||||
}
|
||||
if (variableValue.dictionary.containsKey(dictKey)) {
|
||||
variableValue.dictionary[dictKey] =
|
||||
operator.getNewValue(
|
||||
SimpleExpression(variableValue.dictionary[dictKey]!!), expression, editor,
|
||||
context, this
|
||||
)
|
||||
var valueToStore = if (variableValue.dictionary.containsKey(dictKey)) {
|
||||
operator.getNewValue(SimpleExpression(variableValue.dictionary[dictKey]!!), expression, editor, context, this)
|
||||
} else {
|
||||
variableValue.dictionary[dictKey] = expression.evaluate(editor, context, this)
|
||||
expression.evaluate(editor, context, this)
|
||||
}
|
||||
if (valueToStore is VimFuncref && !valueToStore.isSelfFixed &&
|
||||
valueToStore.handler is DefinedFunctionHandler &&
|
||||
(valueToStore.handler as DefinedFunctionHandler).function.flags.contains(FunctionFlag.DICT)
|
||||
) {
|
||||
valueToStore = valueToStore.copy()
|
||||
valueToStore.dictionary = variableValue
|
||||
}
|
||||
variableValue.dictionary[dictKey] = valueToStore
|
||||
}
|
||||
is VimList -> {
|
||||
// we use Integer.parseInt(........asString()) because in case if index's type is Float, List, Dictionary etc
|
||||
|
@ -18,14 +18,17 @@ data class VimDictionary(val dictionary: LinkedHashMap<VimString, VimDataType>)
|
||||
|
||||
override fun toString(): String {
|
||||
val result = StringBuffer("{")
|
||||
result.append(dictionary.map { it.stringOfEntry() }.joinToString(separator = ", "))
|
||||
result.append(dictionary.map { stringOfEntry(it) }.joinToString(separator = ", "))
|
||||
result.append("}")
|
||||
return result.toString()
|
||||
}
|
||||
|
||||
private fun Map.Entry<VimString, VimDataType>.stringOfEntry(): String {
|
||||
val valueString = if (this.value is VimString) "'${this.value}'" else this.value.toString()
|
||||
return "'${this.key}': $valueString"
|
||||
private fun stringOfEntry(entry: Map.Entry<VimString, VimDataType>): String {
|
||||
val valueString = when (entry.value) {
|
||||
is VimString -> "'${entry.value}'"
|
||||
else -> entry.value.toString()
|
||||
}
|
||||
return "'${entry.key}': $valueString"
|
||||
}
|
||||
|
||||
override fun asBoolean(): Boolean {
|
||||
|
@ -23,22 +23,27 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.maddyhome.idea.vim.ex.ExException
|
||||
import com.maddyhome.idea.vim.vimscript.model.Executable
|
||||
import com.maddyhome.idea.vim.vimscript.model.expressions.Expression
|
||||
import com.maddyhome.idea.vim.vimscript.model.expressions.Scope
|
||||
import com.maddyhome.idea.vim.vimscript.model.expressions.SimpleExpression
|
||||
import com.maddyhome.idea.vim.vimscript.model.expressions.Variable
|
||||
import com.maddyhome.idea.vim.vimscript.model.functions.DefinedFunctionHandler
|
||||
import com.maddyhome.idea.vim.vimscript.model.functions.FunctionHandler
|
||||
import com.maddyhome.idea.vim.vimscript.model.statements.FunctionFlag
|
||||
import com.maddyhome.idea.vim.vimscript.services.FunctionStorage
|
||||
import com.maddyhome.idea.vim.vimscript.services.VariableService
|
||||
|
||||
data class VimFuncref(
|
||||
val handler: FunctionHandler,
|
||||
val arguments: VimList,
|
||||
val dictionary: VimDictionary,
|
||||
var dictionary: VimDictionary?,
|
||||
val type: Type,
|
||||
) : VimDataType() {
|
||||
) : VimDataType(), Cloneable {
|
||||
|
||||
var isSelfFixed = false
|
||||
|
||||
companion object {
|
||||
var lambdaCounter = 0
|
||||
var lambdaCounter = 1
|
||||
var anonymousCounter = 1
|
||||
}
|
||||
|
||||
override fun asDouble(): Double {
|
||||
@ -50,14 +55,19 @@ data class VimFuncref(
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return if (arguments.values.isEmpty()) {
|
||||
return if (arguments.values.isEmpty() && dictionary == null) {
|
||||
when (type) {
|
||||
Type.LAMBDA -> "function('${handler.name}')"
|
||||
Type.FUNCREF -> "function('${handler.name}')"
|
||||
Type.FUNCTION -> handler.name
|
||||
}
|
||||
} else {
|
||||
"function('${handler.name}', $arguments)"
|
||||
val result = StringBuffer("function('${handler.name}'")
|
||||
if (arguments.values.isNotEmpty()) {
|
||||
result.append(", ").append(arguments.toString())
|
||||
}
|
||||
result.append(")")
|
||||
return result.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +75,21 @@ data class VimFuncref(
|
||||
throw ExException("E703: using Funcref as a Number")
|
||||
}
|
||||
|
||||
fun execute(args: List<Expression>, editor: Editor, context: DataContext, parent: Executable): VimDataType {
|
||||
fun execute(name: String, args: List<Expression>, editor: Editor, context: DataContext, parent: Executable): VimDataType {
|
||||
if (handler is DefinedFunctionHandler && handler.function.flags.contains(FunctionFlag.DICT)) {
|
||||
if (dictionary == null) {
|
||||
throw ExException("E725: Calling dict function without Dictionary: $name")
|
||||
} else {
|
||||
VariableService.storeVariable(
|
||||
Variable(Scope.LOCAL_VARIABLE, "self"),
|
||||
dictionary!!,
|
||||
editor,
|
||||
context,
|
||||
handler.function
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val allArguments = listOf(this.arguments.values.map { SimpleExpression(it) }, args).flatten()
|
||||
if (handler is DefinedFunctionHandler && handler.function.isDeleted) {
|
||||
throw ExException("E933: Function was deleted: ${handler.name}")
|
||||
@ -80,6 +104,10 @@ data class VimFuncref(
|
||||
return handler.executeFunction(allArguments, editor, context, parent)
|
||||
}
|
||||
|
||||
override fun clone(): Any {
|
||||
return VimFuncref(handler, arguments, dictionary, type)
|
||||
}
|
||||
|
||||
enum class Type {
|
||||
LAMBDA,
|
||||
FUNCREF,
|
||||
|
@ -23,15 +23,23 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.maddyhome.idea.vim.vimscript.model.Executable
|
||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDataType
|
||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimDictionary
|
||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimFuncref
|
||||
import com.maddyhome.idea.vim.vimscript.model.datatypes.VimString
|
||||
import com.maddyhome.idea.vim.vimscript.model.functions.DefinedFunctionHandler
|
||||
|
||||
data class DictionaryExpression(val dictionary: LinkedHashMap<Expression, Expression>) : Expression() {
|
||||
|
||||
override fun evaluate(editor: Editor, context: DataContext, parent: Executable): VimDataType {
|
||||
val dict: LinkedHashMap<VimString, VimDataType> = linkedMapOf()
|
||||
val dict = VimDictionary(linkedMapOf())
|
||||
for ((key, value) in dictionary) {
|
||||
dict[VimString(key.evaluate(editor, context, parent).asString())] = value.evaluate(editor, context, parent)
|
||||
val evaluatedVal = value.evaluate(editor, context, parent)
|
||||
var newFuncref = evaluatedVal
|
||||
if (evaluatedVal is VimFuncref && evaluatedVal.handler is DefinedFunctionHandler && !evaluatedVal.isSelfFixed) {
|
||||
newFuncref = evaluatedVal.copy()
|
||||
newFuncref.dictionary = dict
|
||||
}
|
||||
dict.dictionary[VimString(key.evaluate(editor, context, parent).asString())] = newFuncref
|
||||
}
|
||||
return VimDictionary(dict)
|
||||
return dict
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ data class FuncrefCallExpression(val expression: Expression, val args: List<Expr
|
||||
val value = expression.evaluate(editor, context, parent)
|
||||
if (value is VimFuncref) {
|
||||
value.handler.ranges = ranges
|
||||
return value.execute(args, editor, context, parent)
|
||||
return value.execute(value.handler.name, args, editor, context, parent)
|
||||
} else {
|
||||
// todo more exceptions
|
||||
throw ExException("E15: Invalid expression")
|
||||
|
@ -25,10 +25,8 @@ data class FunctionCallExpression(val scope: Scope?, val functionName: String, v
|
||||
|
||||
val funcref = VariableService.getNullableVariableValue(Variable(scope, functionName), editor, context, parent)
|
||||
if (funcref is VimFuncref) {
|
||||
if (funcref.handler is DefinedFunctionHandler && funcref.handler.function.flags.contains(FunctionFlag.DICT) && funcref.handler.function.self == null) {
|
||||
throw ExException("E725: Calling dict function without Dictionary: ${(if (scope != null) scope.c + ":" else "") + functionName}")
|
||||
}
|
||||
return funcref.execute(arguments, editor, context, parent)
|
||||
val name = (if (scope != null) scope.c + ":" else "") + functionName
|
||||
return funcref.execute(name, arguments, editor, context, parent)
|
||||
}
|
||||
throw ExException("E117: Unknown function: ${if (scope != null) scope.c + ":" else ""}$functionName")
|
||||
}
|
||||
|
@ -27,6 +27,6 @@ class LambdaFunctionCallExpression(val lambda: LambdaExpression, val arguments:
|
||||
|
||||
override fun evaluate(editor: Editor, context: DataContext, parent: Executable): VimDataType {
|
||||
val funcref = lambda.evaluate(editor, context, parent)
|
||||
return funcref.execute(arguments, editor, context, parent)
|
||||
return funcref.execute("", arguments, editor, context, parent)
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,11 @@ object FunctionFunctionHandler : FunctionHandler() {
|
||||
if (arg3 != null && arg3 !is VimDictionary) {
|
||||
throw ExException("E922: expected a dict")
|
||||
}
|
||||
return VimFuncref(function, arglist ?: VimList(mutableListOf()), dictionary ?: VimDictionary(LinkedHashMap()), VimFuncref.Type.FUNCTION)
|
||||
val funcref = VimFuncref(function, arglist ?: VimList(mutableListOf()), dictionary, VimFuncref.Type.FUNCTION)
|
||||
if (dictionary != null) {
|
||||
funcref.isSelfFixed = true
|
||||
}
|
||||
return funcref
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,7 +119,7 @@ object FuncrefFunctionHandler : FunctionHandler() {
|
||||
if (arg3 != null && arg3 !is VimDictionary) {
|
||||
throw ExException("E922: expected a dict")
|
||||
}
|
||||
return VimFuncref(handler, arglist ?: VimList(mutableListOf()), dictionary ?: VimDictionary(LinkedHashMap()), VimFuncref.Type.FUNCREF)
|
||||
return VimFuncref(handler, arglist ?: VimList(mutableListOf()), dictionary, VimFuncref.Type.FUNCREF)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@ data class FunctionDeclaration(
|
||||
) : Executable {
|
||||
override lateinit var parent: Executable
|
||||
var isDeleted = false
|
||||
var self: VimDataType? = null
|
||||
|
||||
/**
|
||||
* we store the "a:" and "l:" scope variables here
|
||||
|
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* IdeaVim - Vim emulator for IDEs based on the IntelliJ platform
|
||||
* Copyright (C) 2003-2021 The IdeaVim authors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.jetbrains.plugins.ideavim.ex.implementation.functions
|
||||
|
||||
import org.jetbrains.plugins.ideavim.SkipNeovimReason
|
||||
import org.jetbrains.plugins.ideavim.TestWithoutNeovim
|
||||
import org.jetbrains.plugins.ideavim.VimTestCase
|
||||
|
||||
class DictionaryFunctionTest : VimTestCase() {
|
||||
|
||||
fun `test self in dictionary function with assignment via function function`() {
|
||||
configureByText("\n")
|
||||
typeText(
|
||||
commandToKeys(
|
||||
"""
|
||||
function Print() dict |
|
||||
echo self.data |
|
||||
endfunction
|
||||
""".trimIndent()
|
||||
)
|
||||
)
|
||||
typeText(commandToKeys("let dict = {'data': [], 'print': function('Print')}"))
|
||||
typeText(commandToKeys("call dict.print()"))
|
||||
assertExOutput("[]\n")
|
||||
|
||||
typeText(commandToKeys("delfunction! Print"))
|
||||
}
|
||||
|
||||
fun `test self in dictionary function with assignment via let command`() {
|
||||
configureByText("\n")
|
||||
typeText(
|
||||
commandToKeys(
|
||||
"""
|
||||
function Print() dict |
|
||||
echo self.name |
|
||||
endfunction
|
||||
""".trimIndent()
|
||||
)
|
||||
)
|
||||
typeText(commandToKeys("let dict = {'name': 'dict_name'}"))
|
||||
typeText(commandToKeys("let PrintFr = function('Print')"))
|
||||
typeText(commandToKeys("let dict.print = PrintFr"))
|
||||
typeText(commandToKeys("call dict.print()"))
|
||||
assertExOutput("dict_name\n")
|
||||
|
||||
typeText(commandToKeys("delfunction! Print"))
|
||||
}
|
||||
|
||||
@TestWithoutNeovim(SkipNeovimReason.PLUGIN_ERROR)
|
||||
fun `test dictionary function without dict`() {
|
||||
configureByText("\n")
|
||||
typeText(
|
||||
commandToKeys(
|
||||
"""
|
||||
function Print() dict |
|
||||
echo self |
|
||||
endfunction
|
||||
""".trimIndent()
|
||||
)
|
||||
)
|
||||
typeText(commandToKeys("call Print()"))
|
||||
assertPluginError(true)
|
||||
assertPluginErrorMessageContains("E725: Calling dict function without Dictionary: Print")
|
||||
|
||||
typeText(commandToKeys("delfunction! Print"))
|
||||
}
|
||||
|
||||
// todo big brain logic
|
||||
// fun `test assigned dictionary function to another dictionary`() {
|
||||
// configureByText("\n")
|
||||
// typeText(
|
||||
// commandToKeys(
|
||||
// """
|
||||
// function Print() dict |
|
||||
// echo self.name |
|
||||
// endfunction
|
||||
// """.trimIndent()
|
||||
// )
|
||||
// )
|
||||
// typeText(commandToKeys("let dict = {'name': 'dict', 'print': function('Print')}"))
|
||||
// typeText(commandToKeys("echo dict.print"))
|
||||
// assertExOutput("function('Print', {'name': 'dict', 'print': function('Print')}")
|
||||
// typeText(commandToKeys("echo dict"))
|
||||
// assertExOutput("{'name': 'dict', 'print': function('Print')}")
|
||||
// typeText(commandToKeys("call dict.print()"))
|
||||
// assertExOutput("dict\n")
|
||||
//
|
||||
// typeText(commandToKeys("let dict2 = {'name': 'dict2', 'print': dict.print}"))
|
||||
// typeText(commandToKeys("echo dict2.print"))
|
||||
// assertExOutput("function('Print', {'name': 'dict2', 'print': function('Print', {name: 'dict', 'print': function('Print')})}")
|
||||
// typeText(commandToKeys("echo dict2"))
|
||||
// assertExOutput("{'name': 'dict2', 'print': function('Print', {name: 'dict', 'print': function('Print')})}")
|
||||
// typeText(commandToKeys("call dict2.print()"))
|
||||
// assertExOutput("dict2\n")
|
||||
//
|
||||
// typeText(commandToKeys("delfunction! Print"))
|
||||
// }
|
||||
|
||||
fun `test self is not changed after let assignment`() {
|
||||
configureByText("\n")
|
||||
typeText(
|
||||
commandToKeys(
|
||||
"""
|
||||
function Print() dict |
|
||||
echo self.name |
|
||||
endfunction
|
||||
""".trimIndent()
|
||||
)
|
||||
)
|
||||
typeText(commandToKeys("let dict = {'name': 'dict', 'print': function('Print')}"))
|
||||
typeText(commandToKeys("let dict2 = {'name': 'dict2'}"))
|
||||
typeText(commandToKeys("let dict2.print = dict.print"))
|
||||
|
||||
typeText(commandToKeys("call dict2.print()"))
|
||||
assertExOutput("dict2\n")
|
||||
|
||||
typeText(commandToKeys("call dict.print()"))
|
||||
assertExOutput("dict\n")
|
||||
|
||||
typeText(commandToKeys("delfunction! Print"))
|
||||
}
|
||||
|
||||
fun `test self is not changed after in-dictionary assignment`() {
|
||||
configureByText("\n")
|
||||
typeText(
|
||||
commandToKeys(
|
||||
"""
|
||||
function Print() dict |
|
||||
echo self.name |
|
||||
endfunction
|
||||
""".trimIndent()
|
||||
)
|
||||
)
|
||||
typeText(commandToKeys("let dict = {'name': 'dict', 'print': function('Print')}"))
|
||||
typeText(commandToKeys("let dict2 = {'name': 'dict2', 'print': dict.print}"))
|
||||
|
||||
typeText(commandToKeys("call dict2.print()"))
|
||||
assertExOutput("dict2\n")
|
||||
|
||||
typeText(commandToKeys("call dict.print()"))
|
||||
assertExOutput("dict\n")
|
||||
|
||||
typeText(commandToKeys("delfunction! Print"))
|
||||
}
|
||||
|
||||
fun `test assigned partial to another dictionary`() {
|
||||
configureByText("\n")
|
||||
typeText(
|
||||
commandToKeys(
|
||||
"""
|
||||
function Print() dict |
|
||||
echo self.name |
|
||||
endfunction
|
||||
""".trimIndent()
|
||||
)
|
||||
)
|
||||
typeText(commandToKeys("let dict = {'name': 'dict'}"))
|
||||
typeText(commandToKeys("let dict.print = function('Print', dict)"))
|
||||
typeText(commandToKeys("call dict.print()"))
|
||||
assertExOutput("dict\n")
|
||||
|
||||
typeText(commandToKeys("let dict2 = {'name': 'dict2', 'print': dict.print}"))
|
||||
typeText(commandToKeys("call dict2.print()"))
|
||||
assertExOutput("dict\n")
|
||||
|
||||
typeText(commandToKeys("delfunction! Print"))
|
||||
}
|
||||
|
||||
@TestWithoutNeovim(SkipNeovimReason.PLUGIN_ERROR)
|
||||
fun `test self is read-only`() {
|
||||
configureByText("\n")
|
||||
typeText(
|
||||
commandToKeys(
|
||||
"""
|
||||
function Print() dict |
|
||||
let self = [] |
|
||||
endfunction
|
||||
""".trimIndent()
|
||||
)
|
||||
)
|
||||
typeText(commandToKeys("let dict = {'name': 'dict', 'print': function('Print')}"))
|
||||
typeText(commandToKeys("call dict.print()"))
|
||||
assertPluginError(true)
|
||||
assertPluginErrorMessageContains("E46: Cannot change read-only variable \"self\"")
|
||||
|
||||
typeText(commandToKeys("delfunction! Print"))
|
||||
}
|
||||
|
||||
fun `test self in inner dictionary`() {
|
||||
configureByText("\n")
|
||||
typeText(
|
||||
commandToKeys(
|
||||
"""
|
||||
function Print() dict |
|
||||
echo self.name |
|
||||
endfunction
|
||||
""".trimIndent()
|
||||
)
|
||||
)
|
||||
typeText(commandToKeys("let dict = {'name': 'dict', 'innerDict': {'name': 'innerDict', 'print': function('Print')}}"))
|
||||
typeText(commandToKeys("call dict.innerDict.print()"))
|
||||
assertExOutput("innerDict\n")
|
||||
|
||||
typeText(commandToKeys("delfunction! Print"))
|
||||
}
|
||||
}
|
@ -27,9 +27,8 @@
|
||||
- [x] function as method
|
||||
- [x] `function` function
|
||||
- [x] `funcref` function
|
||||
- [ ] dictionary functions
|
||||
- [x] `dict` function flag
|
||||
- [ ] anonymous functions
|
||||
- [ ] `dict` function flag
|
||||
- [ ] default value in functions e.g. `function F1(a, b = 10)`
|
||||
- [ ] delayed parsing of if/for/while etc.
|
||||
- [ ] `has("ide")` or "ide" option
|
||||
|
Loading…
Reference in New Issue
Block a user