override fun doFunction()

in vim-engine/src/main/kotlin/com/maddyhome/idea/vim/vimscript/model/functions/handlers/listFunctions/SortUniqFunctionHandlers.kt [53:136]


  override fun doFunction(
    arguments: Arguments,
    editor: VimEditor,
    context: ExecutionContext,
    vimContext: VimLContext,
  ): VimList {
    val list = arguments[0]
    if (list !is VimList) {
      throw exExceptionMessage("E686", "${name}()")
    }

    if (list.isLocked) {
      throw exExceptionMessage("E741", "${name}() argument")
    }

    val how = arguments.getOrNull(1)?.let { it as? VimFuncref ?: it.toVimString() }

    val dict = arguments.getOrNull(2)
    if (dict != null && dict !is VimDictionary) {
      throw exExceptionMessage("E1206", 3)
    }

    val comparator = when (how) {
      is VimFuncref -> {
        val func = if (dict != null) how.apply(dict) else how
        { a: VimDataType, b: VimDataType ->
          val args = listOf(SimpleExpression(a), SimpleExpression(b))
          val result = func.execute(args, range = null, editor, context, vimContext)
          result.toVimNumber().value
        }
      }

      is VimString -> {
        when (how.value) {
          "i", "1" -> getTypeAndStringValueComparator(String.CASE_INSENSITIVE_ORDER)
          "l" -> getTypeAndStringValueComparator(Collator.getInstance())

          // Allows Float and Number, everything else is treated as 0
          "n" -> { a: VimDataType, b: VimDataType ->
            val a1 = a.toNumericalValueOrZero()
            val b1 = b.toNumericalValueOrZero()
            a1.compareTo(b1)
          }

          // Allows Number, String is parsed. Float is not allowed
          "N" -> { a: VimDataType, b: VimDataType ->
            val a1 = a.toVimNumber().value
            val b1 = b.toVimNumber().value
            a1.compareTo(b1)
          }

          // Allows Float and Number only
          "f" -> { a: VimDataType, b: VimDataType ->
            val a1 = a.toNumericalValue()
            val b1 = b.toNumericalValue()
            a1.compareTo(b1)
          }

          "", "0" -> getTypeAndStringValueComparator(Comparator.naturalOrder())

          else -> {
            val handler = injector.functionService.getFunctionHandlerOrNull(Scope.GLOBAL_VARIABLE, how.value, vimContext)
              ?: throw exExceptionMessage("E117", how.value)
            val funcref = VimFuncref(handler, VimList(mutableListOf()), dict, VimFuncref.Type.FUNCTION);
            { a: VimDataType, b: VimDataType ->
              funcref.execute(
                listOf(SimpleExpression(a), SimpleExpression(b)),
                range = null,
                editor,
                context,
                vimContext
              ).toVimNumber().value
            }
          }
        }
      }

      null -> getTypeAndStringValueComparator(Comparator.naturalOrder())
      else -> throw exExceptionMessage("E474")
    }

    processList(list, comparator)
    return list
  }