Improve completion behaviour

pull/5/head
Lennart Spitzner 2018-02-12 15:47:27 +01:00
parent a495e13e53
commit 0313b0d68d
1 changed files with 23 additions and 18 deletions

View File

@ -30,30 +30,32 @@ simpleCompletion
-- subcommand. See 'UI.Butcher.Monadic.runCmdParserExt'. -- subcommand. See 'UI.Butcher.Monadic.runCmdParserExt'.
-> String -- ^ completion, i.e. a string that might be appended -> String -- ^ completion, i.e. a string that might be appended
-- to the current prompt when user presses tab. -- to the current prompt when user presses tab.
simpleCompletion line cdesc pcRest = simpleCompletion line cdesc pcRest = List.drop (List.length lastWord)
List.drop (List.length lastWord) $ case choices of $ longestCommonPrefix choices
[] -> ""
(c1:cr) ->
case
filter (\s -> List.all (s`isPrefixOf`) cr) $ reverse $ List.inits c1
of
[] -> ""
(x:_) -> x
where where
longestCommonPrefix [] = ""
longestCommonPrefix (c1:cr) =
case find (\s -> List.all (s `isPrefixOf`) cr) $ reverse $ List.inits c1 of
Nothing -> ""
Just x -> x
nameDesc = case _cmd_mParent cdesc of nameDesc = case _cmd_mParent cdesc of
Nothing -> cdesc Nothing -> cdesc
Just (_, parent) | null pcRest -> parent Just (_, parent) | null pcRest && not (null lastWord) -> parent
Just{} -> cdesc -- not finished writing a command. if we have commands abc and abcdef,
-- we may want "def" as a completion after "abc".
Just{} -> cdesc
lastWord = reverse $ takeWhile (not . Char.isSpace) $ reverse $ line lastWord = reverse $ takeWhile (not . Char.isSpace) $ reverse $ line
choices :: [String] choices :: [String]
choices = join choices = join
[ [ r [ [ r
| (Just r, _) <- Data.Foldable.toList (_cmd_children nameDesc) | (Just r, _) <- Data.Foldable.toList (_cmd_children nameDesc)
, lastWord `isPrefixOf` r , lastWord `isPrefixOf` r
, lastWord /= r
] ]
, [ s , [ s
| s <- partDescStrings =<< _cmd_parts nameDesc | s <- partDescStrings =<< _cmd_parts nameDesc
, lastWord `isPrefixOf` s , lastWord `isPrefixOf` s
, lastWord /= s
] ]
] ]
@ -71,21 +73,24 @@ shellCompletionWords
-> [CompletionItem] -> [CompletionItem]
shellCompletionWords line cdesc pcRest = choices shellCompletionWords line cdesc pcRest = choices
where where
_nameDesc = case _cmd_mParent cdesc of nameDesc = case _cmd_mParent cdesc of
Nothing -> cdesc Nothing -> cdesc
Just (_, parent) | null pcRest -> parent Just (_, parent) | null pcRest && not (null lastWord) -> parent
Just{} -> cdesc -- not finished writing a command. if we have commands abc and abcdef,
-- we may want "def" as a completion after "abc".
Just{} -> cdesc
lastWord = reverse $ takeWhile (not . Char.isSpace) $ reverse $ line lastWord = reverse $ takeWhile (not . Char.isSpace) $ reverse $ line
choices :: [CompletionItem] choices :: [CompletionItem]
choices = join choices = join
[ [ CompletionString r [ [ CompletionString r
| (Just r, _) <- Data.Foldable.toList (_cmd_children cdesc) | (Just r, _) <- Data.Foldable.toList (_cmd_children nameDesc)
, lastWord `isPrefixOf` r , lastWord `isPrefixOf` r
, lastWord /= r
] ]
, [ c , [ c
| c <- partDescCompletions =<< _cmd_parts cdesc | c <- partDescCompletions =<< _cmd_parts cdesc
, case c of , case c of
CompletionString s -> lastWord `isPrefixOf` s CompletionString s -> lastWord `isPrefixOf` s && lastWord /= s
_ -> True _ -> True
] ]
] ]