jgm / skylighting

A Haskell syntax highlighting library with tokenizers derived from KDE syntax highlighting descriptions
189 stars 61 forks source link

Derive `Bounded` Instance for `TokenType` #168

Closed prikhi closed 1 year ago

prikhi commented 1 year ago

In one of my projects I wanted to convert my molokai vim colorscheme into a skylighting Style.

To build the tokenStyles field, I wanted to map over a list of all TokenTypes & pass them through to a function that uses case ... of:

    tokenStyles :: M.Map TokenType TokenStyle
    tokenStyles =
        M.fromList $ [(tok, tokenStyle tok) | tok <- allTokens]
    tokenStyle :: TokenType -> TokenStyle
    tokenStyle = \case
        KeywordTok ->
            bold $ color "#F92672"
        DataTypeTok ->
            color "#66D9EF"

I can't define allTokens generically, I'm stuck using discrete values for the start & end of the range:

    tokenStyles :: M.Map TokenType TokenStyle
    tokenStyles =
        M.fromList $ [(t, tokenStyle t) | SkyToken t <- [minBound .. maxBound]]

-- | Custom type for deriving "Bounded TokenType".
newtype SkyToken = SkyToken TokenType
    deriving newtype (Enum)

instance Bounded SkyToken where
    minBound = SkyToken KeywordTok
    maxBound = SkyToken NormalTok

With a derived Bounded instance for TokenType, I can drop my SkyToken newtype & ensure any newly added values to the TokenType type get pulled into my list of "all tokens".


Add Bounded to the derived instances for the TokenType type. This allows consumers to use [minBound .. maxBound] to generate a list of all token types when writing a Style.