module Unison.Cli.Share.Ref
( ShareBranch (..),
ShareRef (..),
parseShareRef,
SearchFilter (..),
parseSearchWords,
)
where
import Data.Text qualified as Text
import Unison.Prelude
data ShareBranch
=
ShareLatest
|
ShareRelease Text
| ShareBranchNamed Text
deriving stock (ShareBranch -> ShareBranch -> Bool
(ShareBranch -> ShareBranch -> Bool)
-> (ShareBranch -> ShareBranch -> Bool) -> Eq ShareBranch
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ShareBranch -> ShareBranch -> Bool
== :: ShareBranch -> ShareBranch -> Bool
$c/= :: ShareBranch -> ShareBranch -> Bool
/= :: ShareBranch -> ShareBranch -> Bool
Eq, Int -> ShareBranch -> ShowS
[ShareBranch] -> ShowS
ShareBranch -> String
(Int -> ShareBranch -> ShowS)
-> (ShareBranch -> String)
-> ([ShareBranch] -> ShowS)
-> Show ShareBranch
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ShareBranch -> ShowS
showsPrec :: Int -> ShareBranch -> ShowS
$cshow :: ShareBranch -> String
show :: ShareBranch -> String
$cshowList :: [ShareBranch] -> ShowS
showList :: [ShareBranch] -> ShowS
Show)
data ShareRef = ShareRef
{
ShareRef -> Text
handle :: Text,
ShareRef -> Text
slug :: Text,
ShareRef -> ShareBranch
branch :: ShareBranch,
ShareRef -> Maybe Text
path :: Maybe Text
}
deriving stock (ShareRef -> ShareRef -> Bool
(ShareRef -> ShareRef -> Bool)
-> (ShareRef -> ShareRef -> Bool) -> Eq ShareRef
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ShareRef -> ShareRef -> Bool
== :: ShareRef -> ShareRef -> Bool
$c/= :: ShareRef -> ShareRef -> Bool
/= :: ShareRef -> ShareRef -> Bool
Eq, Int -> ShareRef -> ShowS
[ShareRef] -> ShowS
ShareRef -> String
(Int -> ShareRef -> ShowS)
-> (ShareRef -> String) -> ([ShareRef] -> ShowS) -> Show ShareRef
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ShareRef -> ShowS
showsPrec :: Int -> ShareRef -> ShowS
$cshow :: ShareRef -> String
show :: ShareRef -> String
$cshowList :: [ShareRef] -> ShowS
showList :: [ShareRef] -> ShowS
Show)
parseShareRef :: Text -> Either Text ShareRef
parseShareRef :: Text -> Either Text ShareRef
parseShareRef Text
input = do
let (Text
projectPart, Text
pathPart) = HasCallStack => Text -> Text -> (Text, Text)
Text -> Text -> (Text, Text)
Text.breakOn Text
":" Text
input
path <-
case Text -> Text -> Maybe Text
Text.stripPrefix Text
":" Text
pathPart of
Maybe Text
Nothing -> Maybe Text -> Either Text (Maybe Text)
forall a b. b -> Either a b
Right Maybe Text
forall a. Maybe a
Nothing
Just Text
"" -> Text -> Either Text (Maybe Text)
forall a b. a -> Either a b
Left (Text
"Expected a name after the `:` in " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
input)
Just Text
p -> Maybe Text -> Either Text (Maybe Text)
forall a b. b -> Either a b
Right (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
p)
case Text.splitOn "/" projectPart of
(Text -> Text -> Maybe Text
Text.stripPrefix Text
"@" -> Just Text
handle) : Text
slug : [Text]
rest
| Bool -> Bool
not (Text -> Bool
Text.null Text
handle) Bool -> Bool -> Bool
&& Bool -> Bool
not (Text -> Bool
Text.null Text
slug) -> do
branch <-
case [Text]
rest of
[] -> ShareBranch -> Either Text ShareBranch
forall a b. b -> Either a b
Right ShareBranch
ShareLatest
[Text
"releases", Text
version] | Bool -> Bool
not (Text -> Bool
Text.null Text
version) -> ShareBranch -> Either Text ShareBranch
forall a b. b -> Either a b
Right (Text -> ShareBranch
ShareRelease Text
version)
[Text
name] | Bool -> Bool
not (Text -> Bool
Text.null Text
name) Bool -> Bool -> Bool
&& Text
name Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Text
"releases" -> ShareBranch -> Either Text ShareBranch
forall a b. b -> Either a b
Right (Text -> ShareBranch
ShareBranchNamed Text
name)
[Text]
_ -> Text -> Either Text ShareBranch
forall a b. a -> Either a b
Left (Text
"I don't understand the branch in " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
input Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
". Use @user/project/branch or @user/project/releases/1.2.3")
Right ShareRef {handle, slug, branch, path}
[Text]
_ -> Text -> Either Text ShareRef
forall a b. a -> Either a b
Left (Text
"Expected a reference like @user/project, @user/project/releases/1.2.3 or @user/project:some.name, but got " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
input)
data SearchFilter
=
FilterUser Text
|
FilterProject Text
deriving stock (SearchFilter -> SearchFilter -> Bool
(SearchFilter -> SearchFilter -> Bool)
-> (SearchFilter -> SearchFilter -> Bool) -> Eq SearchFilter
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SearchFilter -> SearchFilter -> Bool
== :: SearchFilter -> SearchFilter -> Bool
$c/= :: SearchFilter -> SearchFilter -> Bool
/= :: SearchFilter -> SearchFilter -> Bool
Eq, Int -> SearchFilter -> ShowS
[SearchFilter] -> ShowS
SearchFilter -> String
(Int -> SearchFilter -> ShowS)
-> (SearchFilter -> String)
-> ([SearchFilter] -> ShowS)
-> Show SearchFilter
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SearchFilter -> ShowS
showsPrec :: Int -> SearchFilter -> ShowS
$cshow :: SearchFilter -> String
show :: SearchFilter -> String
$cshowList :: [SearchFilter] -> ShowS
showList :: [SearchFilter] -> ShowS
Show)
parseSearchWords :: [Text] -> Either Text (Text, Maybe SearchFilter)
parseSearchWords :: [Text] -> Either Text (Text, Maybe SearchFilter)
parseSearchWords [Text]
words_ =
case [Text] -> [Text]
forall a. [a] -> [a]
reverse [Text]
words_ of
Text
target : Text
"in" : [Text]
queryBackwards
| Just Text
names <- Text -> Text -> Maybe Text
Text.stripPrefix Text
"@" Text
target -> do
filter_ <-
case HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
Text.splitOn Text
"/" Text
names of
[Text
user] | Bool -> Bool
not (Text -> Bool
Text.null Text
user) -> SearchFilter -> Either Text SearchFilter
forall a b. b -> Either a b
Right (Text -> SearchFilter
FilterUser Text
target)
[Text
user, Text
project] | Bool -> Bool
not (Text -> Bool
Text.null Text
user) Bool -> Bool -> Bool
&& Bool -> Bool
not (Text -> Bool
Text.null Text
project) -> SearchFilter -> Either Text SearchFilter
forall a b. b -> Either a b
Right (Text -> SearchFilter
FilterProject Text
target)
[Text]
_ -> Text -> Either Text SearchFilter
forall a b. a -> Either a b
Left (Text
"Expected @user or @user/project after `in`, but got " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
target)
when (null queryBackwards) (Left "Expected something to search for before `in`")
Right (Text.unwords (reverse queryBackwards), Just filter_)
[Text]
_ -> (Text, Maybe SearchFilter)
-> Either Text (Text, Maybe SearchFilter)
forall a b. b -> Either a b
Right ([Text] -> Text
Text.unwords [Text]
words_, Maybe SearchFilter
forall a. Maybe a
Nothing)