File: TH.hs

package info (click to toggle)
haskell-cabal-file-th 0.2.3-8
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 88 kB
  • sloc: haskell: 48; makefile: 2
file content (65 lines) | stat: -rw-r--r-- 2,262 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}

-- | Utility functions for reading cabal file fields through template haskell.
module Distribution.PackageDescription.TH (
    -- * Template Haskell functions
    packageVariable,
    packageVariableFrom,
    -- * Cabal file data structures
    -- | The data structures for the cabal file are re-exported here for ease of use.
    PackageDescription(..),
    PackageIdentifier(..),
    Version(..)
    ) where

import Distribution.PackageDescription 
import Distribution.Package
import Distribution.Version

import Distribution.Text (Text, display)
import Distribution.Verbosity (silent)
import Distribution.PackageDescription.Parse (readPackageDescription)
import System.Directory (getCurrentDirectory, getDirectoryContents)
import Data.List (isSuffixOf)
import Language.Haskell.TH (Q, Exp, stringE, runIO)

-- | Renders the package variable specified by the function.
-- The cabal file interrogated is the first one that is found 
-- in the current working directory.
packageVariable :: Text a => (PackageDescription -> a) -> Q Exp
packageVariable = renderField currentPackageDescription

-- | Renders the package variable specified by the function, from a cabal file
-- and the given path.
packageVariableFrom :: Text a => FilePath -> (PackageDescription -> a) -> Q Exp
packageVariableFrom s = renderField $ fmap packageDescription (readPackageDescription silent s)

------
renderField :: Text b => IO a -> (a -> b) -> Q Exp
renderField pd f = runIO pd >>= stringE . display . f 

currentPackageDescription :: IO PackageDescription
currentPackageDescription = fmap packageDescription $ do
  dir <- getCurrentDirectory
  cs <- cabalFiles dir
  case cs of
    (c:_) -> readPackageDescription silent c
    [] -> error $ "Couldn't find a cabal file in the current working directory (" ++ dir ++ ")"

cabalFiles :: FilePath -> IO [FilePath]
cabalFiles dir = do
  files <- getDirectoryContents dir
  return $ filter (".cabal" `isSuffixOf`) files

{-

Smart ways of getting the cabal file:
  * Get this module name, use TH.location and loc_module. Parse each
    cabal file in the cwd and look for references to this module
    in each thing.
  

  -}