text: // Copyright (c) 2015-2020 Vladimir Schneider <vladimir.schneider@gmail.com> Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
  
  package com.vladsch.md.nav.language.completion.util
  
  import com.intellij.codeInsight.lookup.CharFilter
  import com.intellij.codeInsight.lookup.Lookup
  import com.intellij.codeInsight.lookup.LookupElement
  import com.intellij.codeInsight.lookup.impl.LookupImpl
  import com.intellij.openapi.util.ClassConditionKey
  import com.intellij.util.containers.ContainerUtil
  
  class MdCompletionCharFilter : CharFilter() {
      override fun acceptChar(c: Char, prefixLength: Int, lookup: Lookup): CharFilter.Result? {
          val item = lookup.currentItem ?: return null
          if (!lookup.isCompletion) return null
          val completionCharFiltering = item.`as`(COMPLETION_CHAR_FILTERING) ?: return null
  
          val lookupContext = MdLookupContext.get(lookup.editor)
          val isAutoPopup = lookupContext?.isAutoPopup ?: false
          lookup as LookupImpl
  
          if (completionCharFiltering.isSelectAndFinishChar(c, isAutoPopup)) {
              // here we only let the IDE insert the text supplied and really select item and finish lookup
              if (completionCharFiltering.isPreventingPartialCompletions) {
                  val matcher = lookup.itemMatcher(item)
                  val expanded = matcher.cloneWithPrefix(matcher.prefix + lookup.additionalPrefix + c)
                  completionCharFiltering.preventPartialCompletionFor(expanded.prefix) // now trying to do partial completion will fail
              }
  
              return CharFilter.Result.SELECT_ITEM_AND_FINISH_LOOKUP
          }
  
          if (completionCharFiltering.isAddToPrefixChar(c) && willHaveMatchAfterAppendingChar(lookup, c)) {
              return CharFilter.Result.ADD_TO_PREFIX
          }
  
          return CharFilter.Result.HIDE_LOOKUP
      }
  
      companion object {
          val COMPLETION_CHAR_FILTERING: ClassConditionKey<MdPreventPartialCompletion> = ClassConditionKey.create(MdPreventPartialCompletion::class.java)
  
          private fun willHaveMatchAfterAppendingChar(lookup: LookupImpl, c: Char): Boolean {
              return ContainerUtil.exists(lookup.items) { matchesAfterAppendingChar(lookup, it, c) }
          }
  
          private fun matchesAfterAppendingChar(lookup: LookupImpl, item: LookupElement, c: Char): Boolean {
              val matcher = lookup.itemMatcher(item)
              return matcher.cloneWithPrefix(matcher.prefix + lookup.additionalPrefix + c).prefixMatches(item)
          }
      }
  }
  