summaryrefslogtreecommitdiff
path: root/Omni/Bild/Meta.hs
blob: a5f722efc5e08dc94be991d45c9d52cccfe5bb7b (plain)
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE NoImplicitPrelude #-}

-- | Small module for extracting metadata from the comments of modules.
module Omni.Bild.Meta where

import Alpha
import qualified Data.Char as Char
import qualified Data.Set as Set
import qualified Data.Text as Text
import qualified Text.Regex.Applicative as Regex

-- | A third-party dependency. This gets mapped to some name in nixpkgs,
-- prefixed by package set like @haskellPackages@ or
-- @python3Packages@.
type Dep = String

-- | This is a system-level requirement, the string gets mapped to a name in
-- nixpkgs at the top level, like @pkgs.thing@.
type Sys = String

-- | A run-time dependency. This is some executable that will be placed on
-- @PATH@. This gets selected from @bild.pkgs@, so it must be exported there.
type Run = String

-- | An arbitrary compiler argument that may get added to the compilation
-- command. Should be used sparingly, and not all builds will support this.
type Arg = String

type Out = Maybe String

data Parsed = Parsed
  { pdep :: Set Dep,
    parg :: Set Arg,
    pout :: Out,
    psys :: Set Sys,
    prun :: Set Run
  }

detect :: (Ord a) => Regex.RE Char a -> [Text] -> Set a
detect m cl =
  cl
    /> Text.unpack
    /> Regex.match m
    |> catMaybes
    |> Set.fromList

-- | 'Out' is always singular, so it gets a special function
detectOut :: Regex.RE Char String -> [Text] -> Out
detectOut m cl =
  cl
    /> Text.unpack
    /> Regex.match m
    |> catMaybes
    |> head

-- | Detect all metadata
detectAll ::
  -- | The comment character(s) to match on
  [Char] ->
  -- | Lines of text to parse
  [Text] ->
  Parsed
detectAll m cl = Parsed {..}
  where
    pout = detectOut (out m) cl
    detect_ re = detect (re m) cl
    pdep = detect_ dep
    psys = detect_ sys
    parg = detect_ arg
    prun = detect_ run

dep :: [Char] -> Regex.RE Char Dep
dep comment =
  Regex.string (comment ++ " : dep ")
    *> Regex.many (Regex.psym (not <. Char.isSpace))

sys :: [Char] -> Regex.RE Char Dep
sys comment =
  Regex.string (comment ++ " : sys ")
    *> Regex.many (Regex.psym (not <. Char.isSpace))

out :: [Char] -> Regex.RE Char String
out comment =
  Regex.string (comment ++ " : out ")
    *> Regex.many (Regex.psym (/= ' '))

arg :: [Char] -> Regex.RE Char Arg
arg comment =
  Regex.string (comment ++ " : arg ")
    *> Regex.many Regex.anySym

run :: [Char] -> Regex.RE Char Run
run comment =
  Regex.string (comment ++ " : run ")
    *> Regex.many Regex.anySym