module Yi.Completion
( completeInList, completeInList'
, completeInListCustomShow
, commonPrefix
, prefixMatch, infixMatch
, containsMatch', containsMatch, containsMatchCaseInsensitive
, mkIsPrefixOf
)
where
import Prelude ()
import Yi.Prelude hiding (elem, find)
import Yi.Editor
import Data.List
import Data.Maybe
import Data.Char (toLower)
mkIsPrefixOf :: Bool -> String -> String -> Bool
mkIsPrefixOf caseSensitive = if caseSensitive
then isPrefixOf
else isPrefixOfIC
where isPrefixOfIC x y = map toLower x `isPrefixOf` map toLower y
prefixMatch :: String -> String -> Maybe String
prefixMatch prefix s = if prefix `isPrefixOf` s then Just s else Nothing
infixMatch :: String -> String -> Maybe String
infixMatch needle haystack = fmap (\n -> drop n haystack) $ findIndex (needle `isPrefixOf`) (tails haystack)
containsMatch' :: Bool -> String -> String -> Maybe String
containsMatch' caseSensitive pattern str = fmap (const str) $ find (pattern `tstPrefix`) (tails str)
where tstPrefix = mkIsPrefixOf caseSensitive
containsMatch :: String -> String -> Maybe String
containsMatch = containsMatch' True
containsMatchCaseInsensitive :: String -> String -> Maybe String
containsMatchCaseInsensitive = containsMatch' False
completeInList :: String -> (String -> Maybe String) -> [String] -> EditorM String
completeInList = completeInListCustomShow id
completeInListCustomShow :: (String -> String) -> String -> (String -> Maybe String) ->
[String] -> EditorM String
completeInListCustomShow showFunction s match possibilities
| null filtered = printMsg "No match" >> return s
| prefix /= s = return prefix
| isSingleton filtered = printMsg "Sole completion" >> return s
| prefix `elem` filtered = printMsg ("Complete, but not unique: " ++ show filtered) >> return s
| otherwise = printMsgs (map showFunction filtered) >> return s
where
prefix = commonPrefix filtered
filtered = filterMatches match possibilities
completeInList' :: String -> (String -> Maybe String) -> [String] -> EditorM String
completeInList' s match l
| null filtered = printMsg "No match" >> return s
| isSingleton filtered && s == (head filtered) = printMsg "Sole completion" >> return s
| isSingleton filtered = return $ head filtered
| otherwise = printMsgs filtered >> return s
where
filtered = filterMatches match l
filterMatches :: Eq a => (b -> Maybe a) -> [b] -> [a]
filterMatches match = nub . catMaybes . fmap match
isSingleton :: [a] -> Bool
isSingleton [_] = True
isSingleton _ = False