{-# OPTIONS_GHC -Wunused-imports #-}
{-# OPTIONS_GHC -Wunused-matches #-}
{-# OPTIONS_GHC -Wunused-binds #-}
module Agda.Interaction.Options.BashCompletion where
import Prelude hiding (null)
import Data.Bifunctor ( first )
import Data.Map qualified as Map
import Data.Maybe
import Text.Read ( readMaybe )
import Agda.Interaction.Options.Arguments ( optionValues )
import Agda.Interaction.Options.Base ( standardOptions )
import Agda.Utils.Function ( applyWhenJust )
import Agda.Utils.GetOpt ( OptDescr(..), ArgDescr(..) )
import Agda.Utils.List ( (!!!) )
import Agda.Utils.List1 qualified as List1
import Agda.Utils.Null
import Agda.Utils.Trie (Trie)
import Agda.Utils.Trie qualified as Trie
import Agda.Utils.CompressedTrie qualified as CompressedTrie
type Help = String
printedOptions :: [String]
printedOptions :: [Help]
printedOptions = ((Help, Help) -> Help) -> [(Help, Help)] -> [Help]
forall a b. (a -> b) -> [a] -> [b]
map (Help, Help) -> Help
forall a b. (a, b) -> a
fst [(Help, Help)]
printedOptionsWithHelp
printedOptionsWithHelp :: [(String, Help)]
printedOptionsWithHelp :: [(Help, Help)]
printedOptionsWithHelp = [OptDescr (Flag CommandLineOptions)] -> [(Help, Help)]
forall a. [OptDescr a] -> [(Help, Help)]
printOptions [OptDescr (Flag CommandLineOptions)]
standardOptions
printOptions :: [OptDescr a] -> [(String, Help)]
printOptions :: forall a. [OptDescr a] -> [(Help, Help)]
printOptions = [[(Help, Help)]] -> [(Help, Help)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[(Help, Help)]] -> [(Help, Help)])
-> ([OptDescr a] -> [[(Help, Help)]])
-> [OptDescr a]
-> [(Help, Help)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (OptDescr a -> [(Help, Help)]) -> [OptDescr a] -> [[(Help, Help)]]
forall a b. (a -> b) -> [a] -> [b]
map \case
Option Help
short [Help]
long ArgDescr a
arg Help
help -> [[(Help, Help)]] -> [(Help, Help)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[(Help, Help)]] -> [(Help, Help)])
-> [[(Help, Help)]] -> [(Help, Help)]
forall a b. (a -> b) -> a -> b
$
(Help -> (Help, Help)) -> [Help] -> [(Help, Help)]
forall a b. (a -> b) -> [a] -> [b]
map (,Help
help) [Help]
ss [(Help, Help)] -> [[(Help, Help)]] -> [[(Help, Help)]]
forall a. a -> [a] -> [a]
:
(Help -> (Help, Help)) -> [Help] -> [(Help, Help)]
forall a b. (a -> b) -> [a] -> [b]
map (,Help
help) [Help]
ls [(Help, Help)] -> [[(Help, Help)]] -> [[(Help, Help)]]
forall a. a -> [a] -> [a]
:
([Help] -> [(Help, Help)]) -> [[Help]] -> [[(Help, Help)]]
forall a b. (a -> b) -> [a] -> [b]
map ((Help -> (Help, Help)) -> [Help] -> [(Help, Help)]
forall a b. (a -> b) -> [a] -> [b]
map (,Help
noHelp))
[ [ Help
s Help -> Help -> Help
forall a. [a] -> [a] -> [a]
++ Help
a | Help
s <- [Help]
ss ] [Help] -> [Help] -> [Help]
forall a. [a] -> [a] -> [a]
++
[ Help
l Help -> Help -> Help
forall a. [a] -> [a] -> [a]
++ Help
"=" Help -> Help -> Help
forall a. [a] -> [a] -> [a]
++ Help
a | Help
l <- [Help]
ls ]
| Help
a <- [Help]
as
]
where
ss :: [String]
ss :: [Help]
ss = [ Char
'-' Char -> Help -> Help
forall a. a -> [a] -> [a]
: Char
s Char -> Help -> Help
forall a. a -> [a] -> [a]
: Help
"" | Char
s <- Help
short ]
ls :: [String]
ls :: [Help]
ls = [ Help
"--" Help -> Help -> Help
forall a. [a] -> [a] -> [a]
++ Help
l | Help
l <- [Help]
long ]
as :: [String]
as :: [Help]
as = [Help] -> Maybe [Help] -> [Help]
forall a. a -> Maybe a -> a
fromMaybe [] do
t <- Maybe Help
argType
Map.lookup t optionValues
argType :: Maybe String
argType :: Maybe Help
argType = case ArgDescr a
arg of
NoArg{} -> Maybe Help
forall a. Maybe a
Nothing
ReqArg Help -> a
_ Help
t -> Help -> Maybe Help
forall a. a -> Maybe a
Just Help
t
OptArg Maybe Help -> a
_ Help
t -> Help -> Maybe Help
forall a. a -> Maybe a
Just Help
t
noHelp :: Help
noHelp :: Help
noHelp = Help
""
type Truncate = Maybe Int
bashComplete ::
Truncate
-> [String]
-> Either String String
bashComplete :: Truncate -> [Help] -> Either Help Help
bashComplete Truncate
tr = \case
Help
cword : [Help]
words
| Just Int
i <- Help -> Truncate
forall a. Read a => Help -> Maybe a
readMaybe Help
cword
, [Help] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Help]
words Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
i
, Just Help
w <- [Help]
words [Help] -> Int -> Maybe Help
forall a. [a] -> Int -> Maybe a
!!! Int
i
-> case Truncate -> Help -> Completion
complete Truncate
tr Help
w of
Completion (Just Help
s) [(Help, Help)]
_ -> Help -> Either Help Help
forall a. a -> Either Help a
forall (m :: * -> *) a. Monad m => a -> m a
return Help
s
Completion Maybe Help
ms [(Help, Help)]
cs ->
Help -> Either Help Help
forall a. a -> Either Help a
forall (m :: * -> *) a. Monad m => a -> m a
return (Help -> Either Help Help) -> Help -> Either Help Help
forall a b. (a -> b) -> a -> b
$ [Help] -> Help
unlines ([Help] -> Help) -> [Help] -> Help
forall a b. (a -> b) -> a -> b
$ [[Help]] -> [Help]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
[ Maybe Help -> [Help]
forall a. Maybe a -> [a]
maybeToList Maybe Help
ms
, ((Help, Help) -> Help) -> [(Help, Help)] -> [Help]
forall a b. (a -> b) -> [a] -> [b]
map (Help, Help) -> Help
forall a b. (a, b) -> a
fst [(Help, Help)]
cs
]
[Help]
_args -> Help -> Either Help Help
forall a b. a -> Either a b
Left Help
"Error: Wrong invokation of --bash-complete"
data Completion = Completion
{ Completion -> Maybe Help
extended :: Maybe String
, Completion -> [(Help, Help)]
completions :: [(String, Help)]
}
optionsTrie :: Trie Char Help
optionsTrie :: Trie Char Help
optionsTrie = [(Help, Help)] -> Trie Char Help
forall k v. Ord k => [([k], v)] -> Trie k v
Trie.fromList [(Help, Help)]
printedOptionsWithHelp
complete :: Truncate -> String -> Completion
complete :: Truncate -> Help -> Completion
complete Truncate
trunc Help
s
| Trie Char Help -> Bool
forall a. Null a => a -> Bool
null Trie Char Help
t =
Maybe Help -> [(Help, Help)] -> Completion
Completion Maybe Help
forall a. Maybe a
Nothing []
| Just (List1 Char
k, Trie Char Help
_t') <- Trie Char Help -> Maybe (List1 Char, Trie Char Help)
forall k v. Trie k v -> Maybe (List1 k, Trie k v)
CompressedTrie.isSingleBranch Trie Char Help
t =
Maybe Help -> [(Help, Help)] -> Completion
Completion (Help -> Maybe Help
forall a. a -> Maybe a
Just (Help -> Maybe Help) -> Help -> Maybe Help
forall a b. (a -> b) -> a -> b
$ Help
s Help -> Help -> Help
forall a. [a] -> [a] -> [a]
++ List1 Char -> [Item (List1 Char)]
forall l. IsList l => l -> [Item l]
List1.toList List1 Char
k) [(Help, Help)]
compls
| Bool
otherwise =
Maybe Help -> [(Help, Help)] -> Completion
Completion Maybe Help
forall a. Maybe a
Nothing [(Help, Help)]
compls
where
t :: Trie Char Help
t = Trie Char Help -> Trie Char Help
forall k v. Ord k => Trie k v -> Trie k v
CompressedTrie.compress (Trie Char Help -> Trie Char Help)
-> Trie Char Help -> Trie Char Help
forall a b. (a -> b) -> a -> b
$ Help -> Trie Char Help -> Trie Char Help
forall k v. Ord k => [k] -> Trie k v -> Trie k v
Trie.delete [] (Trie Char Help -> Trie Char Help)
-> Trie Char Help -> Trie Char Help
forall a b. (a -> b) -> a -> b
$ Help -> Trie Char Help -> Trie Char Help
forall k v. Ord k => [k] -> Trie k v -> Trie k v
Trie.lookupTrie Help
s Trie Char Help
optionsTrie
compls :: [(Help, Help)]
compls = ((Help, Help) -> (Help, Help)) -> [(Help, Help)] -> [(Help, Help)]
forall a b. (a -> b) -> [a] -> [b]
map ((Help -> Help) -> (Help, Help) -> (Help, Help)
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first (Help
s Help -> Help -> Help
forall a. [a] -> [a] -> [a]
++)) ([(Help, Help)] -> [(Help, Help)])
-> [(Help, Help)] -> [(Help, Help)]
forall a b. (a -> b) -> a -> b
$ Trie Char Help -> [(Help, Help)]
forall k v. Ord k => Trie k v -> [([k], v)]
CompressedTrie.toList (Trie Char Help -> [(Help, Help)])
-> Trie Char Help -> [(Help, Help)]
forall a b. (a -> b) -> a -> b
$ (Maybe Help -> Trie Char Help) -> Trie Char Help -> Trie Char Help
forall v k. (Maybe v -> Trie k v) -> Trie k v -> Trie k v
CompressedTrie.substLeaves Maybe Help -> Trie Char Help
f Trie Char Help
tt
where
tt :: Trie Char Help
tt = Truncate
-> (Int -> Trie Char Help -> Trie Char Help)
-> Trie Char Help
-> Trie Char Help
forall b a. Maybe b -> (b -> a -> a) -> a -> a
applyWhenJust Truncate
trunc Int -> Trie Char Help -> Trie Char Help
forall k v. Int -> Trie k v -> Trie k v
CompressedTrie.truncateSizeWithLeaves Trie Char Help
t
f :: Maybe Help -> Trie Char Help
f = Trie Char Help
-> (Help -> Trie Char Help) -> Maybe Help -> Trie Char Help
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Help -> Help -> Trie Char Help
forall k v. [k] -> v -> Trie k v
CompressedTrie.singleton Help
"..." Help
forall a. Null a => a
empty) Help -> Trie Char Help
forall v k. v -> Trie k v
CompressedTrie.root