One would like to be able to find all language extensions in a given Haskell
project in order to populate the other-extensions
field of the .cabal
file
(cabal-install
uses this for dependency resolution).
To extract extensions from pragmas, we use Jacinda to handle patterns and fields, viz.
ja '~.{%/LANGUAGE\s*.*\s*#-/}{`3}' -i HS_SRC_FILE
The regex /LANGUAGE\s*.*\s*#-/
filters to lines with a LANGUAGE
pragma and the
~.
operator deduplicates.
We can run this on a whole project with fd, viz.
fd '\.(x|chs|hs|y)$' . -x ja '~.{%/LANGUAGE\s*.*\s*#-/}{`3}' -i | ja '~.$0'
Note the second invocation ja '~.$0'
to deduplicate.
We can do better.
{-#LANGUAGE DerivingVia, GeneralizedNewtypeDeriving#-}
is valid Haskell but is not handled by the above regular expression.
Jacinda has support for capture groups with ~*
. From the manpages:
~* Match, returning nth capture group
Str -> Int -> Regex -> Option Str
With this in mind:
@include'lib/string.jac'
fn findExtensions(line) :=
let
val extStr ≔ line ~* 1 /{-#\s*LANGUAGE\s*(.*)#-}/
val extList ≔ (\s.split s /,\s*/)"extStr
in extList end;
~.(λx.(intercalate'\n')"(findExtensions x)):?$0
We can invoke this on all files in a project like so:
fd '\.(x|chs|hs|y)$' . -x ja run hsExtensions.jac -i | ja '~.$0'
This will produce something like
FlexibleContexts
OverloadedStrings
DeriveAnyClass
DeriveGeneric
TupleSections
TemplateHaskell
DeriveDataTypeable
StandaloneDeriving
GeneralizedNewtypeDeriving
DeriveFunctor
FlexibleInstances
which is precisely what we need.