module Unison.Util.SyntaxText where

import Unison.HashQualified (HashQualified)
import Unison.Name (Name)
import Unison.Pattern (SeqOp)
import Unison.Prelude
import Unison.ReferentPrime (Referent')
import Unison.Util.AnnotatedText (AnnotatedText (..), annotate, segment)

type SyntaxText' r = AnnotatedText (Element r)

-- The elements of the Unison grammar, for syntax highlighting purposes
data Element r
  = NumericLiteral
  | TextLiteral
  | BytesLiteral
  | CharLiteral
  | BooleanLiteral
  | Blank
  | Var
  | TypeReference r
  | TermReference (Referent' r)
  | Op SeqOp
  | AbilityBraces
  | -- let|handle|in|where|match|with|cases|->|if|then|else|and|or
    ControlKeyword
  | -- forall|->
    TypeOperator
  | BindingEquals
  | TypeAscriptionColon
  | -- type|ability
    DataTypeKeyword
  | DataTypeParams
  | Unit
  | -- unique
    DataTypeModifier
  | -- `use Foo bar` is keyword, prefix, suffix
    UseKeyword
  | UsePrefix
  | UseSuffix
  | HashQualifier (HashQualified Name)
  | DelayForceChar
  | -- ? , ` [ ] @ |
    -- Currently not all commas in the pretty-print output are marked up as DelimiterChar - we miss
    -- out characters emitted by Pretty.hs helpers like Pretty.commas.
    DelimiterChar
  | -- ! '
    Parenthesis
  | LinkKeyword -- `typeLink` and `termLink`
  -- [: :] @[]
  | DocDelimiter
  | -- the 'include' in @[include], etc
    DocKeyword
  deriving (Element r -> Element r -> Bool
(Element r -> Element r -> Bool)
-> (Element r -> Element r -> Bool) -> Eq (Element r)
forall r. Eq r => Element r -> Element r -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall r. Eq r => Element r -> Element r -> Bool
== :: Element r -> Element r -> Bool
$c/= :: forall r. Eq r => Element r -> Element r -> Bool
/= :: Element r -> Element r -> Bool
Eq, Eq (Element r)
Eq (Element r) =>
(Element r -> Element r -> Ordering)
-> (Element r -> Element r -> Bool)
-> (Element r -> Element r -> Bool)
-> (Element r -> Element r -> Bool)
-> (Element r -> Element r -> Bool)
-> (Element r -> Element r -> Element r)
-> (Element r -> Element r -> Element r)
-> Ord (Element r)
Element r -> Element r -> Bool
Element r -> Element r -> Ordering
Element r -> Element r -> Element r
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall r. Ord r => Eq (Element r)
forall r. Ord r => Element r -> Element r -> Bool
forall r. Ord r => Element r -> Element r -> Ordering
forall r. Ord r => Element r -> Element r -> Element r
$ccompare :: forall r. Ord r => Element r -> Element r -> Ordering
compare :: Element r -> Element r -> Ordering
$c< :: forall r. Ord r => Element r -> Element r -> Bool
< :: Element r -> Element r -> Bool
$c<= :: forall r. Ord r => Element r -> Element r -> Bool
<= :: Element r -> Element r -> Bool
$c> :: forall r. Ord r => Element r -> Element r -> Bool
> :: Element r -> Element r -> Bool
$c>= :: forall r. Ord r => Element r -> Element r -> Bool
>= :: Element r -> Element r -> Bool
$cmax :: forall r. Ord r => Element r -> Element r -> Element r
max :: Element r -> Element r -> Element r
$cmin :: forall r. Ord r => Element r -> Element r -> Element r
min :: Element r -> Element r -> Element r
Ord, Int -> Element r -> ShowS
[Element r] -> ShowS
Element r -> String
(Int -> Element r -> ShowS)
-> (Element r -> String)
-> ([Element r] -> ShowS)
-> Show (Element r)
forall r. Show r => Int -> Element r -> ShowS
forall r. Show r => [Element r] -> ShowS
forall r. Show r => Element r -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall r. Show r => Int -> Element r -> ShowS
showsPrec :: Int -> Element r -> ShowS
$cshow :: forall r. Show r => Element r -> String
show :: Element r -> String
$cshowList :: forall r. Show r => [Element r] -> ShowS
showList :: [Element r] -> ShowS
Show, (forall a b. (a -> b) -> Element a -> Element b)
-> (forall a b. a -> Element b -> Element a) -> Functor Element
forall a b. a -> Element b -> Element a
forall a b. (a -> b) -> Element a -> Element b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b. (a -> b) -> Element a -> Element b
fmap :: forall a b. (a -> b) -> Element a -> Element b
$c<$ :: forall a b. a -> Element b -> Element a
<$ :: forall a b. a -> Element b -> Element a
Functor)

syntax :: Element r -> SyntaxText' r -> SyntaxText' r
syntax :: forall r. Element r -> SyntaxText' r -> SyntaxText' r
syntax = Element r -> AnnotatedText (Element r) -> AnnotatedText (Element r)
forall a. a -> AnnotatedText a -> AnnotatedText a
annotate

-- Convert a `SyntaxText` to a `String`, ignoring syntax markup
toPlain :: SyntaxText' r -> String
toPlain :: forall r. SyntaxText' r -> String
toPlain (AnnotatedText Seq (Segment (Element r))
at) = [String] -> String
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Seq String -> [String]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Seq String -> [String]) -> Seq String -> [String]
forall a b. (a -> b) -> a -> b
$ Segment (Element r) -> String
forall a. Segment a -> String
segment (Segment (Element r) -> String)
-> Seq (Segment (Element r)) -> Seq String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Seq (Segment (Element r))
at)