{-# LANGUAGE NamedFieldPuns #-}
module Plugin.GhcTags.Vim.Formatter
( formatTagsFile
, formatTag
, formatHeader
) where
import Data.ByteString.Builder (Builder)
import qualified Data.ByteString.Builder as BS
import Data.Char (isAscii)
import Data.Version (showVersion)
import qualified Data.Text.Encoding as Text
import Text.Printf (printf)
import Paths_ghc_tags_plugin (version)
import Plugin.GhcTags.Generate
import Plugin.GhcTags.Tag
formatTag :: Tag -> Builder
formatTag Tag { tagName, tagFile, tagAddr, tagKind, tagFields} =
(BS.byteString . Text.encodeUtf8 . getTagName $ tagName)
<> BS.charUtf8 '\t'
<> (BS.byteString . Text.encodeUtf8 . getTagFile $ tagFile)
<> BS.charUtf8 '\t'
<> either BS.intDec (BS.byteString . Text.encodeUtf8) tagAddr
<> BS.stringUtf8 ";\""
<> formatKindChar tagKind
<> foldMap ((BS.charUtf8 '\t' <>) . formatField) tagFields
<> BS.charUtf8 '\n'
where
formatKindChar :: TagKind -> Builder
formatKindChar NoKind = mempty
formatKindChar (CharKind c)
| isAscii c = BS.charUtf8 '\t' <> BS.charUtf8 c
| otherwise = BS.stringUtf8 "\tkind:" <> BS.charUtf8 c
formatKindChar (GhcKind ghcKind)
| isAscii c = BS.charUtf8 '\t' <> BS.charUtf8 c
| otherwise = BS.stringUtf8 "\tkind:" <> BS.charUtf8 c
where
c = ghcKindToChar ghcKind
formatField :: TagField -> Builder
formatField TagField { fieldName, fieldValue } =
BS.byteString (Text.encodeUtf8 fieldName)
<> BS.charUtf8 ':'
<> BS.byteString (Text.encodeUtf8 fieldValue)
formatHeader :: String -> String -> String
formatHeader header arg = printf ("!_" ++ header ++ "\t%s\t\n") arg
formatTagsFile :: [Tag] -> Builder
formatTagsFile tags =
BS.stringUtf8 (formatHeader "TAG_FILE_FORMAT" "2")
<> BS.stringUtf8 (formatHeader "TAG_FILE_SORTED" "1")
<> BS.stringUtf8 (formatHeader "TAG_FILE_ENCODING" "utf-8")
<> BS.stringUtf8 (formatHeader "TAG_PROGRAM_AUTHOR" "Marcin Szamotulski")
<> BS.stringUtf8 (formatHeader "TAG_PROGRAM_NAME" "ghc-tags-pluginn")
<> BS.stringUtf8 (formatHeader "TAG_PROGRAM_URL"
"https://hackage.haskell.org/package/ghc-tags-plugin")
<> BS.stringUtf8 (formatHeader "TAG_PROGRAM_VERSION" (showVersion version))
<> foldMap formatTag tags