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
FlexibleInstances