{-# LANGUAGE ViewPatterns, TupleSections, ScopedTypeVariables, DeriveDataTypeable, PatternGuards, GADTs #-}

module Output.Tags(writeTags, completionTags, applyTags) where

import Data.Bifunctor
import Data.Function
import Data.List.Extra
import Data.Tuple.Extra
import Data.Maybe
import Foreign.Storable.Tuple()
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.Vector.Storable as V
import qualified Data.ByteString.Char8 as BS

import Input.Item
import Query
import General.Util
import General.Store
import General.Str

---------------------------------------------------------------------
-- DATA TYPE

-- matches (a,b) if i >= a && i <= b

data Packages a where Packages :: Packages (BStr0, V.Vector (TargetId, TargetId)) deriving Typeable
    -- list of packages, sorted by popularity, lowercase, interspersed with \0
    -- for each index in PackageNames, the first is the module item, any in the bounds are in that package

data Modules a where Modules :: Modules (BStr0, V.Vector (TargetId, TargetId)) deriving Typeable
    -- list of modules, sorted by popularity, not unique, lowercase, interspersed with \0
    -- for each index in ModuleNames, the first is the module item, any in the bounds are in that module

data Categories a where Categories :: Categories (BStr0, Jagged (TargetId, TargetId)) deriving Typeable
    -- list of categories, sorted by name, interspersed with \0
    -- for each index in CategoryNames, a range of items containing a category, first item is a package

data Completions a where Completions :: Completions BStr0 deriving Typeable
    -- a list of things to complete to, interspersed with \0


writeTags :: StoreWrite -> (PkgName -> Bool) -> (PkgName -> [(String,String)]) -> [(Maybe TargetId, Item)] -> IO ()
writeTags :: StoreWrite
-> (PkgName -> Bool)
-> (PkgName -> [(String, String)])
-> [(Maybe TargetId, Item)]
-> IO ()
writeTags StoreWrite
store PkgName -> Bool
keep PkgName -> [(String, String)]
extra [(Maybe TargetId, Item)]
xs = do
    let splitPkg :: [(PkgName, [(Maybe TargetId, Item)])]
splitPkg = [(Maybe TargetId, Item)] -> [(PkgName, [(Maybe TargetId, Item)])]
forall a. [(a, Item)] -> [(PkgName, [(a, Item)])]
splitIPackage [(Maybe TargetId, Item)]
xs
    let packages :: [(PkgName, (TargetId, TargetId))]
packages = [(PkgName, [(Maybe TargetId, Item)])]
-> [(PkgName, (TargetId, TargetId))]
forall a.
[(PkgName, [(Maybe TargetId, a)])]
-> [(PkgName, (TargetId, TargetId))]
addRange [(PkgName, [(Maybe TargetId, Item)])]
splitPkg
    StoreWrite
-> Packages (BStr0, Vector (TargetId, TargetId))
-> (BStr0, Vector (TargetId, TargetId))
-> IO ()
forall (t :: * -> *) a.
(Typeable (t a), Typeable a, Stored a) =>
StoreWrite -> t a -> a -> IO ()
storeWrite StoreWrite
store Packages (BStr0, Vector (TargetId, TargetId))
Packages ([String] -> BStr0
bstr0Join ([String] -> BStr0) -> [String] -> BStr0
forall a b. (a -> b) -> a -> b
$ ((PkgName, (TargetId, TargetId)) -> String)
-> [(PkgName, (TargetId, TargetId))] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (PkgName -> String
strUnpack (PkgName -> String)
-> ((PkgName, (TargetId, TargetId)) -> PkgName)
-> (PkgName, (TargetId, TargetId))
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PkgName, (TargetId, TargetId)) -> PkgName
forall a b. (a, b) -> a
fst) [(PkgName, (TargetId, TargetId))]
packages, [(TargetId, TargetId)] -> Vector (TargetId, TargetId)
forall a. Storable a => [a] -> Vector a
V.fromList ([(TargetId, TargetId)] -> Vector (TargetId, TargetId))
-> [(TargetId, TargetId)] -> Vector (TargetId, TargetId)
forall a b. (a -> b) -> a -> b
$ ((PkgName, (TargetId, TargetId)) -> (TargetId, TargetId))
-> [(PkgName, (TargetId, TargetId))] -> [(TargetId, TargetId)]
forall a b. (a -> b) -> [a] -> [b]
map (PkgName, (TargetId, TargetId)) -> (TargetId, TargetId)
forall a b. (a, b) -> b
snd [(PkgName, (TargetId, TargetId))]
packages)

    let categories :: [(String, [(TargetId, TargetId)])]
categories = ((((Double, (String, String)), String), [(TargetId, TargetId)])
 -> (String, [(TargetId, TargetId)]))
-> [(((Double, (String, String)), String), [(TargetId, TargetId)])]
-> [(String, [(TargetId, TargetId)])]
forall a b. (a -> b) -> [a] -> [b]
map ((((Double, (String, String)), String) -> String)
-> ([(TargetId, TargetId)] -> [(TargetId, TargetId)])
-> (((Double, (String, String)), String), [(TargetId, TargetId)])
-> (String, [(TargetId, TargetId)])
forall (p :: * -> * -> *) a b c d.
Bifunctor p =>
(a -> b) -> (c -> d) -> p a c -> p b d
bimap ((Double, (String, String)), String) -> String
forall a b. (a, b) -> b
snd [(TargetId, TargetId)] -> [(TargetId, TargetId)]
forall a. [a] -> [a]
reverse) ([(((Double, (String, String)), String), [(TargetId, TargetId)])]
 -> [(String, [(TargetId, TargetId)])])
-> [(((Double, (String, String)), String), [(TargetId, TargetId)])]
-> [(String, [(TargetId, TargetId)])]
forall a b. (a -> b) -> a -> b
$ Map ((Double, (String, String)), String) [(TargetId, TargetId)]
-> [(((Double, (String, String)), String), [(TargetId, TargetId)])]
forall k a. Map k a -> [(k, a)]
Map.toList (Map ((Double, (String, String)), String) [(TargetId, TargetId)]
 -> [(((Double, (String, String)), String),
      [(TargetId, TargetId)])])
-> Map ((Double, (String, String)), String) [(TargetId, TargetId)]
-> [(((Double, (String, String)), String), [(TargetId, TargetId)])]
forall a b. (a -> b) -> a -> b
$ ([(TargetId, TargetId)]
 -> [(TargetId, TargetId)] -> [(TargetId, TargetId)])
-> [(((Double, (String, String)), String), [(TargetId, TargetId)])]
-> Map ((Double, (String, String)), String) [(TargetId, TargetId)]
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith [(TargetId, TargetId)]
-> [(TargetId, TargetId)] -> [(TargetId, TargetId)]
forall a. [a] -> [a] -> [a]
(++)
            [((((String, String) -> Double
forall p. Fractional p => (String, String) -> p
weightTag (String, String)
ex, (String -> String) -> (String, String) -> (String, String)
forall a b. (a -> b) -> (a, a) -> (b, b)
both String -> String
lower (String, String)
ex), String -> (String, String) -> String
forall a. [a] -> ([a], [a]) -> [a]
joinPair String
":" (String, String)
ex),[(TargetId, TargetId)
rng]) | (PkgName
p,(TargetId, TargetId)
rng) <- [(PkgName, (TargetId, TargetId))]
packages, (String, String)
ex <- PkgName -> [(String, String)]
extra PkgName
p]
    StoreWrite
-> Categories (BStr0, Jagged (TargetId, TargetId))
-> (BStr0, Jagged (TargetId, TargetId))
-> IO ()
forall (t :: * -> *) a.
(Typeable (t a), Typeable a, Stored a) =>
StoreWrite -> t a -> a -> IO ()
storeWrite StoreWrite
store Categories (BStr0, Jagged (TargetId, TargetId))
Categories ([String] -> BStr0
bstr0Join ([String] -> BStr0) -> [String] -> BStr0
forall a b. (a -> b) -> a -> b
$ ((String, [(TargetId, TargetId)]) -> String)
-> [(String, [(TargetId, TargetId)])] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, [(TargetId, TargetId)]) -> String
forall a b. (a, b) -> a
fst [(String, [(TargetId, TargetId)])]
categories, [[(TargetId, TargetId)]] -> Jagged (TargetId, TargetId)
forall a. Storable a => [[a]] -> Jagged a
jaggedFromList ([[(TargetId, TargetId)]] -> Jagged (TargetId, TargetId))
-> [[(TargetId, TargetId)]] -> Jagged (TargetId, TargetId)
forall a b. (a -> b) -> a -> b
$ ((String, [(TargetId, TargetId)]) -> [(TargetId, TargetId)])
-> [(String, [(TargetId, TargetId)])] -> [[(TargetId, TargetId)]]
forall a b. (a -> b) -> [a] -> [b]
map (String, [(TargetId, TargetId)]) -> [(TargetId, TargetId)]
forall a b. (a, b) -> b
snd [(String, [(TargetId, TargetId)])]
categories)

    let modules :: [(PkgName, (TargetId, TargetId))]
modules = [(PkgName, [(Maybe TargetId, Item)])]
-> [(PkgName, (TargetId, TargetId))]
forall a.
[(PkgName, [(Maybe TargetId, a)])]
-> [(PkgName, (TargetId, TargetId))]
addRange ([(PkgName, [(Maybe TargetId, Item)])]
 -> [(PkgName, (TargetId, TargetId))])
-> [(PkgName, [(Maybe TargetId, Item)])]
-> [(PkgName, (TargetId, TargetId))]
forall a b. (a -> b) -> a -> b
$ ((PkgName, [(Maybe TargetId, Item)])
 -> [(PkgName, [(Maybe TargetId, Item)])])
-> [(PkgName, [(Maybe TargetId, Item)])]
-> [(PkgName, [(Maybe TargetId, Item)])]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([(Maybe TargetId, Item)] -> [(PkgName, [(Maybe TargetId, Item)])]
forall a. [(a, Item)] -> [(PkgName, [(a, Item)])]
splitIModule ([(Maybe TargetId, Item)] -> [(PkgName, [(Maybe TargetId, Item)])])
-> ((PkgName, [(Maybe TargetId, Item)])
    -> [(Maybe TargetId, Item)])
-> (PkgName, [(Maybe TargetId, Item)])
-> [(PkgName, [(Maybe TargetId, Item)])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PkgName, [(Maybe TargetId, Item)]) -> [(Maybe TargetId, Item)]
forall a b. (a, b) -> b
snd) [(PkgName, [(Maybe TargetId, Item)])]
splitPkg
    StoreWrite
-> Modules (BStr0, Vector (TargetId, TargetId))
-> (BStr0, Vector (TargetId, TargetId))
-> IO ()
forall (t :: * -> *) a.
(Typeable (t a), Typeable a, Stored a) =>
StoreWrite -> t a -> a -> IO ()
storeWrite StoreWrite
store Modules (BStr0, Vector (TargetId, TargetId))
Modules ([String] -> BStr0
bstr0Join ([String] -> BStr0) -> [String] -> BStr0
forall a b. (a -> b) -> a -> b
$ ((PkgName, (TargetId, TargetId)) -> String)
-> [(PkgName, (TargetId, TargetId))] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String -> String
lower (String -> String)
-> ((PkgName, (TargetId, TargetId)) -> String)
-> (PkgName, (TargetId, TargetId))
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PkgName -> String
strUnpack (PkgName -> String)
-> ((PkgName, (TargetId, TargetId)) -> PkgName)
-> (PkgName, (TargetId, TargetId))
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PkgName, (TargetId, TargetId)) -> PkgName
forall a b. (a, b) -> a
fst) [(PkgName, (TargetId, TargetId))]
modules, [(TargetId, TargetId)] -> Vector (TargetId, TargetId)
forall a. Storable a => [a] -> Vector a
V.fromList ([(TargetId, TargetId)] -> Vector (TargetId, TargetId))
-> [(TargetId, TargetId)] -> Vector (TargetId, TargetId)
forall a b. (a -> b) -> a -> b
$ ((PkgName, (TargetId, TargetId)) -> (TargetId, TargetId))
-> [(PkgName, (TargetId, TargetId))] -> [(TargetId, TargetId)]
forall a b. (a -> b) -> [a] -> [b]
map (PkgName, (TargetId, TargetId)) -> (TargetId, TargetId)
forall a b. (a, b) -> b
snd [(PkgName, (TargetId, TargetId))]
modules)

    StoreWrite -> Completions BStr0 -> BStr0 -> IO ()
forall (t :: * -> *) a.
(Typeable (t a), Typeable a, Stored a) =>
StoreWrite -> t a -> a -> IO ()
storeWrite StoreWrite
store Completions BStr0
Completions (BStr0 -> IO ()) -> BStr0 -> IO ()
forall a b. (a -> b) -> a -> b
$ [String] -> BStr0
bstr0Join ([String] -> BStr0) -> [String] -> BStr0
forall a b. (a -> b) -> a -> b
$
        (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (String
"set:" String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`) (((String, [(TargetId, TargetId)]) -> String)
-> [(String, [(TargetId, TargetId)])] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, [(TargetId, TargetId)]) -> String
forall a b. (a, b) -> a
fst [(String, [(TargetId, TargetId)])]
categories) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
        (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String
"package:"String -> String -> String
forall a. [a] -> [a] -> [a]
++) ((String -> String) -> [String] -> [String]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn String -> String
lower ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ (PkgName -> String) -> [PkgName] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map PkgName -> String
strUnpack ([PkgName] -> [String]) -> [PkgName] -> [String]
forall a b. (a -> b) -> a -> b
$ [PkgName] -> [PkgName]
forall a. Ord a => [a] -> [a]
nubOrd ([PkgName] -> [PkgName]) -> [PkgName] -> [PkgName]
forall a b. (a -> b) -> a -> b
$ (PkgName -> Bool) -> [PkgName] -> [PkgName]
forall a. (a -> Bool) -> [a] -> [a]
filter PkgName -> Bool
keep ([PkgName] -> [PkgName]) -> [PkgName] -> [PkgName]
forall a b. (a -> b) -> a -> b
$ ((PkgName, (TargetId, TargetId)) -> PkgName)
-> [(PkgName, (TargetId, TargetId))] -> [PkgName]
forall a b. (a -> b) -> [a] -> [b]
map (PkgName, (TargetId, TargetId)) -> PkgName
forall a b. (a, b) -> a
fst [(PkgName, (TargetId, TargetId))]
packages) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
        ((String, String) -> String) -> [(String, String)] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String -> (String, String) -> String
forall a. [a] -> ([a], [a]) -> [a]
joinPair String
":") (((String, String) -> (Double, (String, String)))
-> [(String, String)] -> [(String, String)]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn ((String, String) -> Double
forall p. Fractional p => (String, String) -> p
weightTag ((String, String) -> Double)
-> ((String, String) -> (String, String))
-> (String, String)
-> (Double, (String, String))
forall a b c. (a -> b) -> (a -> c) -> a -> (b, c)
&&& (String -> String) -> (String, String) -> (String, String)
forall a b. (a -> b) -> (a, a) -> (b, b)
both String -> String
lower) ([(String, String)] -> [(String, String)])
-> [(String, String)] -> [(String, String)]
forall a b. (a -> b) -> a -> b
$ [(String, String)] -> [(String, String)]
forall a. Ord a => [a] -> [a]
nubOrd [(String, String)
ex | (PkgName
p,(TargetId, TargetId)
_) <- [(PkgName, (TargetId, TargetId))]
packages, PkgName -> Bool
keep PkgName
p, (String, String)
ex <- PkgName -> [(String, String)]
extra PkgName
p, (String, String) -> String
forall a b. (a, b) -> a
fst (String, String)
ex String -> String -> Bool
forall a. Eq a => a -> a -> Bool
/= String
"set"])
    where
        addRange :: [(Str, [(Maybe TargetId,a)])] -> [(Str, (TargetId, TargetId))]
        addRange :: [(PkgName, [(Maybe TargetId, a)])]
-> [(PkgName, (TargetId, TargetId))]
addRange [(PkgName, [(Maybe TargetId, a)])]
xs = [(PkgName
a, ([TargetId] -> TargetId
forall a. Ord a => [a] -> a
minimum' [TargetId]
is, [TargetId] -> TargetId
forall a. Ord a => [a] -> a
maximum' [TargetId]
is)) | (PkgName
a,[(Maybe TargetId, a)]
b) <- [(PkgName, [(Maybe TargetId, a)])]
xs, let is :: [TargetId]
is = ((Maybe TargetId, a) -> Maybe TargetId)
-> [(Maybe TargetId, a)] -> [TargetId]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (Maybe TargetId, a) -> Maybe TargetId
forall a b. (a, b) -> a
fst [(Maybe TargetId, a)]
b, Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ PkgName -> Bool
strNull PkgName
a, [TargetId]
is [TargetId] -> [TargetId] -> Bool
forall a. Eq a => a -> a -> Bool
/= []]

        weightTag :: (String, String) -> p
weightTag (String
"set",String
x) = p -> Maybe p -> p
forall a. a -> Maybe a -> a
fromMaybe p
0.9 (Maybe p -> p) -> Maybe p -> p
forall a b. (a -> b) -> a -> b
$ String -> [(String, p)] -> Maybe p
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup String
x [(String
"stackage",p
0.0),(String
"haskell-platform",p
0.1)]
        weightTag (String
"package",String
x) = p
1
        weightTag (String
"category",String
x) = p
2
        weightTag (String
"license",String
x) = p
3
        weightTag (String, String)
_ = p
4


---------------------------------------------------------------------
-- SIMPLE SELECTORS

completionTags :: StoreRead -> [String]
completionTags :: StoreRead -> [String]
completionTags StoreRead
store = (BStr0 -> String) -> [BStr0] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map BStr0 -> String
BS.unpack ([BStr0] -> [String]) -> [BStr0] -> [String]
forall a b. (a -> b) -> a -> b
$ BStr0 -> [BStr0]
bstr0Split (BStr0 -> [BStr0]) -> BStr0 -> [BStr0]
forall a b. (a -> b) -> a -> b
$ StoreRead -> Completions BStr0 -> BStr0
forall (t :: * -> *) a.
(Typeable (t a), Typeable a, Stored a) =>
StoreRead -> t a -> a
storeRead StoreRead
store Completions BStr0
Completions


---------------------------------------------------------------------
-- DATA TYPE, PARSE, PRINT

data Tag = IsExact | IsPackage | IsModule | EqPackage String | EqModule String | EqCategory String String deriving Tag -> Tag -> Bool
(Tag -> Tag -> Bool) -> (Tag -> Tag -> Bool) -> Eq Tag
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Tag -> Tag -> Bool
$c/= :: Tag -> Tag -> Bool
== :: Tag -> Tag -> Bool
$c== :: Tag -> Tag -> Bool
Eq

parseTag :: String -> String -> Maybe Tag
parseTag :: String -> String -> Maybe Tag
parseTag String
k String
v
    | String
k String -> String -> Bool
~~ String
"is" = case () of
        ()
_ | String
v String -> String -> Bool
~~ String
"exact" -> Tag -> Maybe Tag
forall a. a -> Maybe a
Just Tag
IsExact
          | String
v String -> String -> Bool
~~ String
"package" -> Tag -> Maybe Tag
forall a. a -> Maybe a
Just Tag
IsPackage
          | String
v String -> String -> Bool
~~ String
"module" -> Tag -> Maybe Tag
forall a. a -> Maybe a
Just Tag
IsModule
          | Bool
otherwise -> Maybe Tag
forall a. Maybe a
Nothing
    | String
k String -> String -> Bool
~~ String
"package" = if String
v String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"" then Maybe Tag
forall a. Maybe a
Nothing else Tag -> Maybe Tag
forall a. a -> Maybe a
Just (Tag -> Maybe Tag) -> Tag -> Maybe Tag
forall a b. (a -> b) -> a -> b
$ String -> Tag
EqPackage String
v
    | String
k String -> String -> Bool
~~ String
"module" = if String
v String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"" then Maybe Tag
forall a. Maybe a
Nothing else Tag -> Maybe Tag
forall a. a -> Maybe a
Just (Tag -> Maybe Tag) -> Tag -> Maybe Tag
forall a b. (a -> b) -> a -> b
$ String -> Tag
EqModule String
v
    | String
v String -> String -> Bool
forall a. Eq a => a -> a -> Bool
/= String
"" = Tag -> Maybe Tag
forall a. a -> Maybe a
Just (Tag -> Maybe Tag) -> Tag -> Maybe Tag
forall a b. (a -> b) -> a -> b
$ String -> String -> Tag
EqCategory String
k String
v
    | Bool
otherwise = Maybe Tag
forall a. Maybe a
Nothing
    where
        -- make the assumption the first letter always disambiguates
        String
x ~~ :: String -> String -> Bool
~~ String
lit = String
x String -> String -> Bool
forall a. Eq a => a -> a -> Bool
/= String
"" Bool -> Bool -> Bool
&& String -> String
lower String
x String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` String
lit

showTag :: Tag -> (String, String)
showTag :: Tag -> (String, String)
showTag Tag
IsExact = (String
"is",String
"exact")
showTag Tag
IsPackage = (String
"is",String
"package")
showTag Tag
IsModule = (String
"is",String
"module")
showTag (EqPackage String
x) = (String
"package",String
x)
showTag (EqModule String
x) = (String
"module",String
x)
showTag (EqCategory String
k String
v) = (String
k,String
v)


---------------------------------------------------------------------
-- TAG SEMANTICS

-- | Given a tag, find the ranges of identifiers it covers (if it restricts the range)
-- An empty range means an empty result, while a Nothing means a search on the entire range
resolveTag :: StoreRead -> Tag -> (Tag, Maybe [(TargetId,TargetId)])
resolveTag :: StoreRead -> Tag -> (Tag, Maybe [(TargetId, TargetId)])
resolveTag StoreRead
store Tag
x = case Tag
x of
    Tag
IsExact -> (Tag
IsExact, Maybe [(TargetId, TargetId)]
forall a. Maybe a
Nothing)
    Tag
IsPackage -> (Tag
IsPackage, [(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)]
forall a. a -> Maybe a
Just ([(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)])
-> [(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)]
forall a b. (a -> b) -> a -> b
$ ((TargetId, TargetId) -> (TargetId, TargetId))
-> [(TargetId, TargetId)] -> [(TargetId, TargetId)]
forall a b. (a -> b) -> [a] -> [b]
map (TargetId -> (TargetId, TargetId)
forall a. a -> (a, a)
dupe (TargetId -> (TargetId, TargetId))
-> ((TargetId, TargetId) -> TargetId)
-> (TargetId, TargetId)
-> (TargetId, TargetId)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TargetId, TargetId) -> TargetId
forall a b. (a, b) -> a
fst) ([(TargetId, TargetId)] -> [(TargetId, TargetId)])
-> [(TargetId, TargetId)] -> [(TargetId, TargetId)]
forall a b. (a -> b) -> a -> b
$ Vector (TargetId, TargetId) -> [(TargetId, TargetId)]
forall a. Storable a => Vector a -> [a]
V.toList Vector (TargetId, TargetId)
packageIds)
    Tag
IsModule -> (Tag
IsModule, [(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)]
forall a. a -> Maybe a
Just ([(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)])
-> [(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)]
forall a b. (a -> b) -> a -> b
$ ((TargetId, TargetId) -> (TargetId, TargetId))
-> [(TargetId, TargetId)] -> [(TargetId, TargetId)]
forall a b. (a -> b) -> [a] -> [b]
map (TargetId -> (TargetId, TargetId)
forall a. a -> (a, a)
dupe (TargetId -> (TargetId, TargetId))
-> ((TargetId, TargetId) -> TargetId)
-> (TargetId, TargetId)
-> (TargetId, TargetId)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TargetId, TargetId) -> TargetId
forall a b. (a, b) -> a
fst) ([(TargetId, TargetId)] -> [(TargetId, TargetId)])
-> [(TargetId, TargetId)] -> [(TargetId, TargetId)]
forall a b. (a -> b) -> a -> b
$ Vector (TargetId, TargetId) -> [(TargetId, TargetId)]
forall a. Storable a => Vector a -> [a]
V.toList Vector (TargetId, TargetId)
moduleIds)
    EqPackage orig :: String
orig@(String -> BStr0
BS.pack -> BStr0
val)
        -- look for people who are an exact prefix, sort by remaining length, if there are ties, pick the first one
        | res :: [(Int, (Int, BStr0))]
res@((Int, (Int, BStr0))
_:[(Int, (Int, BStr0))]
_) <- [(BStr0 -> Int
BS.length BStr0
x, (Int
i,BStr0
x)) | (Int
i,BStr0
x) <- Int -> [BStr0] -> [(Int, BStr0)]
forall a b. Enum a => a -> [b] -> [(a, b)]
zipFrom Int
0 ([BStr0] -> [(Int, BStr0)]) -> [BStr0] -> [(Int, BStr0)]
forall a b. (a -> b) -> a -> b
$ BStr0 -> [BStr0]
bstr0Split BStr0
packageNames, BStr0
val BStr0 -> BStr0 -> Bool
`BS.isPrefixOf` BStr0
x]
            -> let (Int
i,BStr0
x) = (Int, (Int, BStr0)) -> (Int, BStr0)
forall a b. (a, b) -> b
snd ((Int, (Int, BStr0)) -> (Int, BStr0))
-> (Int, (Int, BStr0)) -> (Int, BStr0)
forall a b. (a -> b) -> a -> b
$ ((Int, (Int, BStr0)) -> (Int, (Int, BStr0)) -> Ordering)
-> [(Int, (Int, BStr0))] -> (Int, (Int, BStr0))
forall (t :: * -> *) a.
Foldable t =>
(a -> a -> Ordering) -> t a -> a
minimumBy (Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Int -> Int -> Ordering)
-> ((Int, (Int, BStr0)) -> Int)
-> (Int, (Int, BStr0))
-> (Int, (Int, BStr0))
-> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (Int, (Int, BStr0)) -> Int
forall a b. (a, b) -> a
fst) [(Int, (Int, BStr0))]
res in (String -> Tag
EqPackage (String -> Tag) -> String -> Tag
forall a b. (a -> b) -> a -> b
$ BStr0 -> String
BS.unpack BStr0
x, [(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)]
forall a. a -> Maybe a
Just [Vector (TargetId, TargetId)
packageIds Vector (TargetId, TargetId) -> Int -> (TargetId, TargetId)
forall a. Storable a => Vector a -> Int -> a
V.! Int
i])
        | Bool
otherwise -> (String -> Tag
EqPackage String
orig , [(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)]
forall a. a -> Maybe a
Just [])
    EqModule String
x -> (String -> Tag
EqModule String
x, [(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)]
forall a. a -> Maybe a
Just ([(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)])
-> [(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)]
forall a b. (a -> b) -> a -> b
$ (Int -> (TargetId, TargetId)) -> [Int] -> [(TargetId, TargetId)]
forall a b. (a -> b) -> [a] -> [b]
map (Vector (TargetId, TargetId)
moduleIds Vector (TargetId, TargetId) -> Int -> (TargetId, TargetId)
forall a. Storable a => Vector a -> Int -> a
V.!) ([Int] -> [(TargetId, TargetId)])
-> [Int] -> [(TargetId, TargetId)]
forall a b. (a -> b) -> a -> b
$ (BStr0 -> Bool) -> [BStr0] -> [Int]
forall a. (a -> Bool) -> [a] -> [Int]
findIndices (String -> BStr0 -> Bool
eqModule (String -> BStr0 -> Bool) -> String -> BStr0 -> Bool
forall a b. (a -> b) -> a -> b
$ String -> String
lower String
x) ([BStr0] -> [Int]) -> [BStr0] -> [Int]
forall a b. (a -> b) -> a -> b
$ BStr0 -> [BStr0]
bstr0Split BStr0
moduleNames)
    EqCategory String
cat String
val -> (String -> String -> Tag
EqCategory String
cat String
val, [(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)]
forall a. a -> Maybe a
Just ([(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)])
-> [(TargetId, TargetId)] -> Maybe [(TargetId, TargetId)]
forall a b. (a -> b) -> a -> b
$ [[(TargetId, TargetId)]] -> [(TargetId, TargetId)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
        [ Vector (TargetId, TargetId) -> [(TargetId, TargetId)]
forall a. Storable a => Vector a -> [a]
V.toList (Vector (TargetId, TargetId) -> [(TargetId, TargetId)])
-> Vector (TargetId, TargetId) -> [(TargetId, TargetId)]
forall a b. (a -> b) -> a -> b
$ Jagged (TargetId, TargetId) -> Int -> Vector (TargetId, TargetId)
forall a. Storable a => Jagged a -> Int -> Vector a
jaggedAsk Jagged (TargetId, TargetId)
categoryIds Int
i
        | Int
i <- BStr0 -> [BStr0] -> [Int]
forall a. Eq a => a -> [a] -> [Int]
elemIndices (String -> BStr0
BS.pack (String
cat String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
val)) ([BStr0] -> [Int]) -> [BStr0] -> [Int]
forall a b. (a -> b) -> a -> b
$ BStr0 -> [BStr0]
bstr0Split BStr0
categoryNames])
    where
        eqModule :: String -> BStr0 -> Bool
eqModule String
x | Just String
x <- String -> String -> Maybe String
forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix String
"." String
x, Just String
x <- String -> String -> Maybe String
forall a. Eq a => [a] -> [a] -> Maybe [a]
stripSuffix String
"." String
x = BStr0 -> BStr0 -> Bool
forall a. Eq a => a -> a -> Bool
(==) (String -> BStr0
BS.pack String
x)
                   | Just String
x <- String -> String -> Maybe String
forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix String
"." String
x = BStr0 -> BStr0 -> Bool
BS.isPrefixOf (BStr0 -> BStr0 -> Bool) -> BStr0 -> BStr0 -> Bool
forall a b. (a -> b) -> a -> b
$ String -> BStr0
BS.pack String
x
                   | Bool
otherwise = let y :: BStr0
y = String -> BStr0
BS.pack String
x; y2 :: BStr0
y2 = String -> BStr0
BS.pack (Char
'.'Char -> String -> String
forall a. a -> [a] -> [a]
:String
x)
                                 in \BStr0
v -> BStr0
y BStr0 -> BStr0 -> Bool
`BS.isPrefixOf` BStr0
v Bool -> Bool -> Bool
|| BStr0
y2 BStr0 -> BStr0 -> Bool
`BS.isInfixOf` BStr0
v

        (BStr0
packageNames, Vector (TargetId, TargetId)
packageIds) = StoreRead
-> Packages (BStr0, Vector (TargetId, TargetId))
-> (BStr0, Vector (TargetId, TargetId))
forall (t :: * -> *) a.
(Typeable (t a), Typeable a, Stored a) =>
StoreRead -> t a -> a
storeRead StoreRead
store Packages (BStr0, Vector (TargetId, TargetId))
Packages
        (BStr0
categoryNames, Jagged (TargetId, TargetId)
categoryIds) = StoreRead
-> Categories (BStr0, Jagged (TargetId, TargetId))
-> (BStr0, Jagged (TargetId, TargetId))
forall (t :: * -> *) a.
(Typeable (t a), Typeable a, Stored a) =>
StoreRead -> t a -> a
storeRead StoreRead
store Categories (BStr0, Jagged (TargetId, TargetId))
Categories
        (BStr0
moduleNames, Vector (TargetId, TargetId)
moduleIds) = StoreRead
-> Modules (BStr0, Vector (TargetId, TargetId))
-> (BStr0, Vector (TargetId, TargetId))
forall (t :: * -> *) a.
(Typeable (t a), Typeable a, Stored a) =>
StoreRead -> t a -> a
storeRead StoreRead
store Modules (BStr0, Vector (TargetId, TargetId))
Modules


---------------------------------------------------------------------
-- TAG QUERIES

-- | Given a query produce: (refined query, is:exact, filter, enumeration)
--   You should apply the filter to other peoples results, or if you have nothing else, use the enumeration.
applyTags :: StoreRead -> [Query] -> ([Query], Bool, TargetId -> Bool, [TargetId])
applyTags :: StoreRead
-> [Query] -> ([Query], Bool, TargetId -> Bool, [TargetId])
applyTags StoreRead
store [Query]
qs = ([Query]
qs2, Bool
exact, TargetId -> Bool
filt, StoreRead -> [Query] -> [TargetId]
searchTags StoreRead
store [Query]
qs)
    where ([Query]
qs2, Bool
exact, TargetId -> Bool
filt) = StoreRead -> [Query] -> ([Query], Bool, TargetId -> Bool)
filterTags StoreRead
store [Query]
qs

filterTags :: StoreRead -> [Query] -> ([Query], Bool, TargetId -> Bool)
filterTags :: StoreRead -> [Query] -> ([Query], Bool, TargetId -> Bool)
filterTags StoreRead
ts [Query]
qs = ((Query -> Query) -> [Query] -> [Query]
forall a b. (a -> b) -> [a] -> [b]
map Query -> Query
redo [Query]
qs, Bool
exact, \TargetId
i -> ((TargetId -> Bool) -> Bool) -> [TargetId -> Bool] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all ((TargetId -> Bool) -> TargetId -> Bool
forall a b. (a -> b) -> a -> b
$ TargetId
i) [TargetId -> Bool]
fs)
    where fs :: [TargetId -> Bool]
fs = ((String, [Query]) -> TargetId -> Bool)
-> [(String, [Query])] -> [TargetId -> Bool]
forall a b. (a -> b) -> [a] -> [b]
map (StoreRead -> [Query] -> TargetId -> Bool
filterTags2 StoreRead
ts ([Query] -> TargetId -> Bool)
-> ((String, [Query]) -> [Query])
-> (String, [Query])
-> TargetId
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, [Query]) -> [Query]
forall a b. (a, b) -> b
snd) ([(String, [Query])] -> [TargetId -> Bool])
-> [(String, [Query])] -> [TargetId -> Bool]
forall a b. (a -> b) -> a -> b
$ [(String, Query)] -> [(String, [Query])]
forall k v. Ord k => [(k, v)] -> [(k, [v])]
groupSort ([(String, Query)] -> [(String, [Query])])
-> [(String, Query)] -> [(String, [Query])]
forall a b. (a -> b) -> a -> b
$ (Query -> (String, Query)) -> [Query] -> [(String, Query)]
forall a b. (a -> b) -> [a] -> [b]
map (Query -> String
scopeCategory (Query -> String) -> (Query -> Query) -> Query -> (String, Query)
forall a b c. (a -> b) -> (a -> c) -> a -> (b, c)
&&& Query -> Query
forall a. a -> a
id) ([Query] -> [(String, Query)]) -> [Query] -> [(String, Query)]
forall a b. (a -> b) -> a -> b
$ (Query -> Bool) -> [Query] -> [Query]
forall a. (a -> Bool) -> [a] -> [a]
filter Query -> Bool
isQueryScope [Query]
qs
          exact :: Bool
exact = Tag -> Maybe Tag
forall a. a -> Maybe a
Just Tag
IsExact Maybe Tag -> [Maybe Tag] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String -> String -> Maybe Tag
parseTag String
a String
b | QueryScope Bool
True String
a String
b <- [Query]
qs]
          redo :: Query -> Query
redo (QueryScope Bool
sense String
cat String
val)
              | Just (String
k,String
v) <- (Tag -> (String, String)) -> Maybe Tag -> Maybe (String, String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Tag -> (String, String)
showTag (Tag -> (String, String))
-> (Tag -> Tag) -> Tag -> (String, String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Tag, Maybe [(TargetId, TargetId)]) -> Tag
forall a b. (a, b) -> a
fst ((Tag, Maybe [(TargetId, TargetId)]) -> Tag)
-> (Tag -> (Tag, Maybe [(TargetId, TargetId)])) -> Tag -> Tag
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StoreRead -> Tag -> (Tag, Maybe [(TargetId, TargetId)])
resolveTag StoreRead
ts) (Maybe Tag -> Maybe (String, String))
-> Maybe Tag -> Maybe (String, String)
forall a b. (a -> b) -> a -> b
$ String -> String -> Maybe Tag
parseTag String
cat String
val = Bool -> String -> String -> Query
QueryScope Bool
sense String
k String
v
              | Bool
otherwise = String -> Query
QueryNone (String -> Query) -> String -> Query
forall a b. (a -> b) -> a -> b
$ [Char
'-' | Bool -> Bool
not Bool
sense] String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
cat String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
val
          redo Query
q = Query
q


filterTags2 :: StoreRead -> [Query] -> TargetId -> Bool
filterTags2 StoreRead
ts [Query]
qs = \TargetId
i -> Bool -> Bool
not (TargetId -> Bool
negq TargetId
i) Bool -> Bool -> Bool
&& (Bool
noPosRestrict Bool -> Bool -> Bool
|| TargetId -> Bool
posq TargetId
i)
    where (TargetId -> Bool
posq,TargetId -> Bool
negq) = ([(TargetId, TargetId)] -> TargetId -> Bool)
-> ([(TargetId, TargetId)], [(TargetId, TargetId)])
-> (TargetId -> Bool, TargetId -> Bool)
forall a b. (a -> b) -> (a, a) -> (b, b)
both [(TargetId, TargetId)] -> TargetId -> Bool
forall a. Ix a => [(a, a)] -> a -> Bool
inRanges ([(TargetId, TargetId)]
pos,[(TargetId, TargetId)]
neg)
          ([(TargetId, TargetId)]
pos, [(TargetId, TargetId)]
neg) = ([(Bool, [(TargetId, TargetId)])] -> [(TargetId, TargetId)])
-> ([(Bool, [(TargetId, TargetId)])],
    [(Bool, [(TargetId, TargetId)])])
-> ([(TargetId, TargetId)], [(TargetId, TargetId)])
forall a b. (a -> b) -> (a, a) -> (b, b)
both (((Bool, [(TargetId, TargetId)]) -> [(TargetId, TargetId)])
-> [(Bool, [(TargetId, TargetId)])] -> [(TargetId, TargetId)]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Bool, [(TargetId, TargetId)]) -> [(TargetId, TargetId)]
forall a b. (a, b) -> b
snd) (([(Bool, [(TargetId, TargetId)])],
  [(Bool, [(TargetId, TargetId)])])
 -> ([(TargetId, TargetId)], [(TargetId, TargetId)]))
-> ([(Bool, [(TargetId, TargetId)])],
    [(Bool, [(TargetId, TargetId)])])
-> ([(TargetId, TargetId)], [(TargetId, TargetId)])
forall a b. (a -> b) -> a -> b
$ ((Bool, [(TargetId, TargetId)]) -> Bool)
-> [(Bool, [(TargetId, TargetId)])]
-> ([(Bool, [(TargetId, TargetId)])],
    [(Bool, [(TargetId, TargetId)])])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition (Bool, [(TargetId, TargetId)]) -> Bool
forall a b. (a, b) -> a
fst [(Bool, [(TargetId, TargetId)])]
xs
          xs :: [(Bool, [(TargetId, TargetId)])]
xs = [Maybe (Bool, [(TargetId, TargetId)])]
-> [(Bool, [(TargetId, TargetId)])]
forall a. [Maybe a] -> [a]
catMaybes [Maybe (Bool, [(TargetId, TargetId)])]
restrictions
          noPosRestrict :: Bool
noPosRestrict = (Maybe (Bool, [(TargetId, TargetId)]) -> Bool)
-> [Maybe (Bool, [(TargetId, TargetId)])] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Maybe (Bool, [(TargetId, TargetId)]) -> Bool
forall b. Maybe (Bool, b) -> Bool
pred [Maybe (Bool, [(TargetId, TargetId)])]
restrictions
          restrictions :: [Maybe (Bool, [(TargetId, TargetId)])]
restrictions = (Query -> Maybe (Bool, [(TargetId, TargetId)]))
-> [Query] -> [Maybe (Bool, [(TargetId, TargetId)])]
forall a b. (a -> b) -> [a] -> [b]
map Query -> Maybe (Bool, [(TargetId, TargetId)])
getRestriction [Query]
qs
          pred :: Maybe (Bool, b) -> Bool
pred Maybe (Bool, b)
Nothing = Bool
True
          pred (Just (Bool
sense, b
_)) = Bool -> Bool
not Bool
sense
          getRestriction :: Query -> Maybe (Bool,[(TargetId, TargetId)])
          getRestriction :: Query -> Maybe (Bool, [(TargetId, TargetId)])
getRestriction (QueryScope Bool
sense String
cat String
val) = do
            Tag
tag <- String -> String -> Maybe Tag
parseTag String
cat String
val
            [(TargetId, TargetId)]
ranges <- (Tag, Maybe [(TargetId, TargetId)]) -> Maybe [(TargetId, TargetId)]
forall a b. (a, b) -> b
snd ((Tag, Maybe [(TargetId, TargetId)])
 -> Maybe [(TargetId, TargetId)])
-> (Tag, Maybe [(TargetId, TargetId)])
-> Maybe [(TargetId, TargetId)]
forall a b. (a -> b) -> a -> b
$ StoreRead -> Tag -> (Tag, Maybe [(TargetId, TargetId)])
resolveTag StoreRead
ts Tag
tag
            (Bool, [(TargetId, TargetId)])
-> Maybe (Bool, [(TargetId, TargetId)])
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool
sense, [(TargetId, TargetId)]
ranges)


-- | Given a search which has no type or string in it, run the query on the tag bits.
--   Using for things like IsModule, EqCategory etc.
searchTags :: StoreRead -> [Query] -> [TargetId]
searchTags :: StoreRead -> [Query] -> [TargetId]
searchTags StoreRead
ts [Query]
qs
    | [TargetId]
x:[[TargetId]]
xs <- [((TargetId, TargetId) -> TargetId)
-> [(TargetId, TargetId)] -> [TargetId]
forall a b. (a -> b) -> [a] -> [b]
map (TargetId, TargetId) -> TargetId
forall a b. (a, b) -> a
fst ([(TargetId, TargetId)] -> [TargetId])
-> [(TargetId, TargetId)] -> [TargetId]
forall a b. (a -> b) -> a -> b
$ [(TargetId, TargetId)]
-> (Tag -> [(TargetId, TargetId)])
-> Maybe Tag
-> [(TargetId, TargetId)]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] ([(TargetId, TargetId)]
-> Maybe [(TargetId, TargetId)] -> [(TargetId, TargetId)]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [(TargetId, TargetId)] -> [(TargetId, TargetId)])
-> (Tag -> Maybe [(TargetId, TargetId)])
-> Tag
-> [(TargetId, TargetId)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Tag, Maybe [(TargetId, TargetId)]) -> Maybe [(TargetId, TargetId)]
forall a b. (a, b) -> b
snd ((Tag, Maybe [(TargetId, TargetId)])
 -> Maybe [(TargetId, TargetId)])
-> (Tag -> (Tag, Maybe [(TargetId, TargetId)]))
-> Tag
-> Maybe [(TargetId, TargetId)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StoreRead -> Tag -> (Tag, Maybe [(TargetId, TargetId)])
resolveTag StoreRead
ts) (Maybe Tag -> [(TargetId, TargetId)])
-> Maybe Tag -> [(TargetId, TargetId)]
forall a b. (a -> b) -> a -> b
$ String -> String -> Maybe Tag
parseTag String
cat String
val | QueryScope Bool
True String
cat String
val <- [Query]
qs]
    = if [[TargetId]] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[TargetId]]
xs then [TargetId]
x else (TargetId -> Bool) -> [TargetId] -> [TargetId]
forall a. (a -> Bool) -> [a] -> [a]
filter (TargetId -> Set TargetId -> Bool
forall a. Ord a => a -> Set a -> Bool
`Set.member` (Set TargetId -> Set TargetId -> Set TargetId)
-> [Set TargetId] -> Set TargetId
forall a. (a -> a -> a) -> [a] -> a
foldl1' Set TargetId -> Set TargetId -> Set TargetId
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection (([TargetId] -> Set TargetId) -> [[TargetId]] -> [Set TargetId]
forall a b. (a -> b) -> [a] -> [b]
map [TargetId] -> Set TargetId
forall a. Ord a => [a] -> Set a
Set.fromList [[TargetId]]
xs)) [TargetId]
x
searchTags StoreRead
ts [Query]
_ = [TargetId]
-> ([(TargetId, TargetId)] -> [TargetId])
-> Maybe [(TargetId, TargetId)]
-> [TargetId]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (((TargetId, TargetId) -> TargetId)
-> [(TargetId, TargetId)] -> [TargetId]
forall a b. (a -> b) -> [a] -> [b]
map (TargetId, TargetId) -> TargetId
forall a b. (a, b) -> a
fst) (Maybe [(TargetId, TargetId)] -> [TargetId])
-> Maybe [(TargetId, TargetId)] -> [TargetId]
forall a b. (a -> b) -> a -> b
$ (Tag, Maybe [(TargetId, TargetId)]) -> Maybe [(TargetId, TargetId)]
forall a b. (a, b) -> b
snd ((Tag, Maybe [(TargetId, TargetId)])
 -> Maybe [(TargetId, TargetId)])
-> (Tag, Maybe [(TargetId, TargetId)])
-> Maybe [(TargetId, TargetId)]
forall a b. (a -> b) -> a -> b
$ StoreRead -> Tag -> (Tag, Maybe [(TargetId, TargetId)])
resolveTag StoreRead
ts Tag
IsPackage