1{-# LANGUAGE PatternGuards #-}
3module Main ( main ) where
5import Cabal2Nix.Flags ( configureCabalFlags )
6import Cabal2Nix.Generate ( cabal2nix' )
7import Cabal2Nix.Hackage ( readHashedHackage, Hackage )
8import Cabal2Nix.Package
13import Control.Monad.Par.Combinator
14import Control.Monad.Par.IO
15import Control.Monad.Trans ( liftIO )
16import Data.Map.Strict ( Map )
17import qualified Data.Map.Strict as Map
20import Data.Set ( Set )
21import qualified Data.Set as Set
22import Distribution.Compiler
23import Distribution.Nixpkgs.Fetch
24import Distribution.Nixpkgs.Haskell
25import Distribution.Nixpkgs.Meta
26import Distribution.Nixpkgs.PackageMap
27import Distribution.Nixpkgs.Util.PrettyPrinting hiding ( attr, (<>) )
28import Distribution.Package
29import Distribution.PackageDescription hiding ( buildDepends, extraLibs, buildTools )
30import Distribution.PackageDescription.Configuration
31import Distribution.System
32import Distribution.Text
33import Distribution.Version
35type Nixpkgs = PackageMap -- Map String (Set [String])
36type PackageSet = Map String Version
37type PackageMultiSet = Map String (Set Version)
39type Constraint = Dependency
41resolveConstraint :: Constraint -> Hackage -> Version
42resolveConstraint c = fromMaybe (error ("constraint " ++ display c ++ " cannot be resolved in Hackage")) .
45resolveConstraint' :: Constraint -> Hackage -> Maybe Version
46resolveConstraint' (Dependency (PackageName name) vrange) hackage | Set.null vs = Nothing
47 | otherwise = Just (Set.findMax vs)
48 where vs = Set.filter (`withinRange` vrange) (Map.keysSet (hackage Map.! name))
50data Configuration = Configuration
52 -- |Target architecture. Used by 'finalizePackageDescription' to
53 -- choose appropriate flags and dependencies.
56 -- |Target compiler. Used by 'finalizePackageDescription' to choose
57 -- appropriate flags and dependencies.
58 , compilerInfo :: CompilerInfo
60 -- |Core packages found on Hackageg
61 , corePackages :: [PackageIdentifier]
63 -- |Core packages not found on Hackage.
64 , hardCorePackages :: [PackageIdentifier]
66 -- |These packages replace the latest respective version during
67 -- dependency resolution.
68 , defaultPackageOverrides :: [Constraint]
70 -- |These packages are added to the generated set, but the play no
71 -- role during dependency resolution.
72 , extraPackages :: [Constraint]
74 -- |These packages have not succeeded a build yet, so we give them an
75 -- empty meta.hydraPlatforms attribute to avoid cluttering our Hydra
76 -- output with lots of broken builds.
77 , brokenPackages :: Set PackageName
83 hackage <- readHashedHackage
84 nixpkgs <- readNixpkgPackageMap
85 let fixup = Map.delete "acme-everything" -- TODO: https://github.com/NixOS/cabal2nix/issues/164
86 . Map.delete "som" -- TODO: https://github.com/NixOS/cabal2nix/issues/164
87 . Map.delete "type" -- TODO: https://github.com/NixOS/cabal2nix/issues/163
88 . Map.delete "dictionary-sharing" -- TODO: https://github.com/NixOS/cabal2nix/issues/175
89 runParIO $ generatePackageSet defaultConfiguration (fixup hackage) nixpkgs
91generatePackageSet :: Configuration -> Hackage -> Nixpkgs -> ParIO ()
92generatePackageSet config hackage nixpkgs = do
94 corePackageSet :: PackageSet
95 corePackageSet = Map.fromList [ (name, v) | PackageIdentifier (PackageName name) v <- corePackages config ++ hardCorePackages config ]
97 latestVersionSet :: PackageSet
98 latestVersionSet = Map.map (Set.findMax . Map.keysSet) hackage
100 defaultPackageOverridesSet :: PackageSet
101 defaultPackageOverridesSet = Map.fromList [ (name, resolveConstraint c hackage) | c@(Dependency (PackageName name) _) <- defaultPackageOverrides config ]
103 generatedDefaultPackageSet :: PackageSet
104 generatedDefaultPackageSet = (defaultPackageOverridesSet `Map.union` latestVersionSet) `Map.difference` corePackageSet
106 latestCorePackageSet :: PackageSet
107 latestCorePackageSet = latestVersionSet `Map.intersection` corePackageSet
109 latestOverridePackageSet :: PackageSet
110 latestOverridePackageSet = latestVersionSet `Map.intersection` defaultPackageOverridesSet
112 extraPackageSet :: PackageMultiSet
113 extraPackageSet = Map.unionsWith Set.union
114 [ Map.singleton name (Set.singleton (resolveConstraint c hackage)) | c@(Dependency (PackageName name) _) <- extraPackages config ]
116 db :: PackageMultiSet
117 db = Map.unionsWith Set.union [ Map.map Set.singleton generatedDefaultPackageSet
118 , Map.map Set.singleton latestCorePackageSet
119 , Map.map Set.singleton latestOverridePackageSet
123 knownAttributesSet :: Set String
124 knownAttributesSet = Set.union (Map.keysSet hackage) (Map.keysSet corePackageSet)
126 resolver :: Dependency -> Bool
127 resolver (Dependency (PackageName name) vrange)
128 | Just v <- Map.lookup name corePackageSet = v `withinRange` vrange
129 | Just v <- Map.lookup name generatedDefaultPackageSet = v `withinRange` vrange
132 liftIO $ do putStrLn "/* hackage-packages.nix is an auto-generated file -- DO NOT EDIT! */"
134 putStrLn "{ pkgs, stdenv, callPackage }:"
138 pkgs <- flip parMapM (Map.toAscList db) $ \(name, vs) -> do
139 defs <- forM (Set.toAscList vs) $ \pkgversion -> do
140 srcSpec <- liftIO $ sourceFromHackage UnknownHash (name ++ "-" ++ display pkgversion)
141 let -- TODO: Include list of broken dependencies in the generated output.
142 descr = hackage Map.! name Map.! pkgversion
143 (missingDeps, _, drv') = cabal2nix resolver descr
145 haskellDependencies :: Set String
146 haskellDependencies = Set.map unDep $ mconcat [ drv'^.x.haskell | x <- [libraryDepends,executableDepends,testDepends] ]
148 systemDependencies :: Set String
149 systemDependencies = Set.map unDep $ mconcat [ drv'^.x.y | x <- [libraryDepends,executableDepends,testDepends], y <- [system,pkgconfig] ]
151 haskellOrSystemDependencies :: Set String
152 haskellOrSystemDependencies = Set.map unDep $ mconcat [ drv'^.x.tool | x <- [libraryDepends,executableDepends,testDepends] ]
154 missing :: Set String
155 missing = Set.filter (`Set.notMember` knownAttributesSet) haskellDependencies
157 buildInputs :: Map Attribute (Maybe Path)
158 buildInputs = Map.unions
159 [ Map.fromList [ (n, Nothing) | n <- Set.toList missing ]
160 , Map.fromList [ (n, resolveNixpkgsAttribute nixpkgs n) | n <- Set.toAscList systemDependencies ]
161 , Map.fromList [ (n, resolveHackageThenNixpkgsAttribute nixpkgs hackage n) | n <- Set.toAscList haskellOrSystemDependencies ]
164 systemOverrides :: Doc
165 systemOverrides = fsep (map (uncurry formatOverride) (Map.toAscList buildInputs))
167 formatOverride :: Attribute -> Maybe Path -> Doc
168 formatOverride n Nothing = space <> text n <> text " = null;" -- missing attribute
169 formatOverride n (Just []) -- Haskell package:
170 | n == name = formatOverride n Nothing -- refers to a missing system library
171 | otherwise = empty -- found by callPackage
172 formatOverride n (Just p) = (text " inherit" <+> parens (text (intercalate "." p)) <+> text n) <> semi
175 overrides = systemOverrides
177 attr | Just v <- Map.lookup name generatedDefaultPackageSet, v == pkgversion = name
178 | otherwise = name ++ '_' : [ if c == '.' then '_' else c | c <- display pkgversion ]
180 drv = drv' & src .~ srcSpec
181 & jailbreak .~ (not (null missingDeps) && (name /= "jailbreak-cabal")) -- Dependency constraints aren't fulfilled
182 & metaSection . broken .~ not (Set.null missing) -- Missing Haskell dependencies!
183 & metaSection.hydraPlatforms .~ (if PackageName name `Set.member` brokenPackages config
184 then Set.singleton "stdenv.lib.platforms.none"
185 else drv'^.metaSection.hydraPlatforms)
187 return $ nest 2 $ hang (string attr <+> equals <+> text "callPackage") 2 (parens (pPrint drv)) <+> (braces overrides <> semi)
188 return (intercalate "\n\n" (map render defs))
190 liftIO $ mapM_ (\pkg -> putStrLn pkg >> putStrLn "") pkgs
191 liftIO $ putStrLn "}"
193resolveHackageThenNixpkgsAttribute :: Nixpkgs -> Hackage -> Attribute -> Maybe Path
194resolveHackageThenNixpkgsAttribute nixpkgs hackage name
195 | Just _ <- Map.lookup name hackage = Just []
196 | p@(Just _) <- resolveNixpkgsAttribute nixpkgs name = p
197 | otherwise = Nothing
199resolveNixpkgsAttribute :: Nixpkgs -> Attribute -> Maybe Path
200resolveNixpkgsAttribute nixpkgs name
201 | name `elem` ["clang","lldb","llvm"] = Just ["self","llvmPackages"]
202 | Just paths <- Map.lookup name nixpkgs = getShortestPath (Set.toList (paths `Set.intersection` goodScopes))
203 | otherwise = Nothing
205 goodScopes :: Set Path
206 goodScopes = Set.fromList [[], ["xlibs"], ["gnome"], ["gnome3"], ["kde4"]]
208 getShortestPath :: [Path] -> Maybe Path
209 getShortestPath [] = Nothing
210 getShortestPath ps = Just ("pkgs" : minimumBy (on compare length) ps)
212cabal2nix :: (Dependency -> Bool) -> GenericPackageDescription -> ([Dependency], FlagAssignment, Derivation)
213cabal2nix resolver cabal = (missingDeps, flags, drv)
215 drv = cabal2nix' descr
217 Right (descr, flags) = finalize (if null missingDeps then resolver else const True) cabal
219 missingDeps :: [Dependency]
220 missingDeps = either id (const []) (finalize resolver cabal')
222 finalize :: (Dependency -> Bool) -> GenericPackageDescription -> Either [Dependency] (PackageDescription, FlagAssignment)
223 finalize resolver' = finalizePackageDescription
224 (configureCabalFlags (package (packageDescription cabal)))
226 (platform defaultConfiguration)
227 (compilerInfo defaultConfiguration)
228 [] -- no additional constraints
230 -- A variant of the cabal file that has all test suites enabled to ensure
231 -- that their dependencies are recognized by finalizePackageDescription.
232 cabal' :: GenericPackageDescription
233 cabal' = cabal { condTestSuites = flaggedTests }
235 flaggedTests :: [(String, CondTree ConfVar [Dependency] TestSuite)]
236 flaggedTests = map (\(n, t) -> (n, mapTreeData enableTest t)) (condTestSuites cabal)
238 enableTest :: TestSuite -> TestSuite
239 enableTest t = t { testEnabled = True }
241defaultConfiguration :: Configuration
242defaultConfiguration = Configuration
243 { platform = Platform X86_64 Linux
244 , compilerInfo = unknownCompilerInfo (CompilerId GHC (Version [7,10,2] [])) NoAbiTag
246 , defaultPackageOverrides = map (\s -> fromMaybe (error (show s ++ " is not a valid override selector")) (simpleParse s))
247 [ "errors < 2" -- the update breaks some ~40 important packages
248 , "vector < 0.11" -- breaks lens 4.12
251 , corePackages = map (\s -> fromMaybe (error (show s ++ " is not a valid core package")) (simpleParse s))
256 , "bytestring-0.10.6.0"
257 , "containers-0.5.6.2"
259 , "directory-1.2.2.0"
262 , "haskeline-0.7.2.1"
265 , "integer-gmp-1.0.0.0"
268 , "template-haskell-2.10.0.0"
271 , "transformers-0.4.2.0"
276 , hardCorePackages = map (\s -> fromMaybe (error (show s ++ " is not a valid core package")) (simpleParse s))
277 [ "bin-package-db-0.0.0.0"
282 , extraPackages = map (\s -> fromMaybe (error (show s ++ " is not a valid extra package selector")) (simpleParse s))
283 [ "aeson < 0.8" -- newer versions don't work with GHC 6.12.3
284 , "Cabal == 1.18.*" -- required for cabal-install et al on old GHC versions
285 , "Cabal == 1.20.*" -- required for cabal-install et al on old GHC versions
286 , "cabal-install == 1.18.*" -- required for ghc-mod on 7.8.x
287 , "conduit < 1.2.4.2" -- newer versions trigger non-deterministic ID bugs in GHC versions prior to 7.10.x
288 , "containers < 0.5" -- required to build alex with GHC 6.12.3
289 , "control-monad-free < 0.6" -- newer versions don't compile with anything but GHC 7.8.x
290 , "deepseq == 1.3.0.1" -- required to build Cabal with GHC 6.12.3
291 , "descriptive < 0.1" -- required for structured-haskell-mode-1.0.8
292 , "gloss < 1.9.3" -- new versions don't compile with GHC 7.8.x
293 , "haddock-api < 2.16" -- required on GHC 7.8.x
294 , "haskell-src-exts < 1.16" -- required for structured-haskell-mode-1.0.8
295 , "mtl < 2.2" -- newer versions require transformers > 0.4.x, which we cannot provide in GHC 7.8.x
296 , "mtl-prelude < 2" -- required for to build postgrest on mtl 2.1.x platforms
297 , "optparse-applicative == 0.10.*" -- required for elm-make 0.1.1 and elm-package 0.4
298 , "parallel == 3.2.0.3" -- newer versions don't work with GHC 6.12.3
299 , "primitive == 0.5.1.*" -- required to build alex with GHC 6.12.3
300 , "QuickCheck < 2" -- required by test-framework-quickcheck and its users
301 , "seqid < 0.2" -- newer versions depend on transformers 0.4.x which we cannot provide in GHC 7.8.x
302 , "seqid-streams < 0.2" -- newer versions depend on transformers 0.4.x which we cannot provide in GHC 7.8.x
303 , "split < 0.2" -- newer versions don't work with GHC 6.12.3
304 , "tar < 0.4.2.0" -- later versions don't work with GHC < 7.6.x
305 , "vector < 0.10.10" -- newer versions don't work with GHC 6.12.3
306 , "zlib < 0.6" -- newer versions break cabal-install
309 , brokenPackages = Set.fromList $ map PackageName
313 , "abstract-par-accelerate"
316 , "accelerate-arithmetic"
318 , "accelerate-fourier"
320 , "accelerate-utility"
323 , "AC-EasyRaster-GTK"
328 , "acme-numbersystem"
329 , "acme-schoenfinkel"
338 , "Adaptive-Blaisorblade"
339 , "adaptive-containers"
344 , "adobe-swatch-exchange"
346 , "adp-multi-monadiccp"
352 , "AERN-Real-Interval"
365 , "aivika-experiment-diagrams"
366 , "aivika-transformers"
385 , "android-lint-summary"
386 , "AndroidViewHierarchyImporter"
398 , "apiary-purescript"
435 , "atlassian-connect-core"
436 , "atlassian-connect-descriptor"
441 , "attoparsec-iteratee"
443 , "attoparsec-text-enumerator"
459 , "aws-cloudfront-signer"
461 , "aws-elastic-transcoder"
462 , "aws-kinesis-reshard"
465 , "aws-sdk-text-converter"
466 , "aws-sdk-xml-unordered"
469 , "azure-service-api"
476 , "bamboo-plugin-highlight"
477 , "bamboo-plugin-photo"
478 , "bamboo-theme-blueprint"
479 , "bamboo-theme-mini-html5"
492 , "bed-and-breakfast"
500 , "bidirectionalization-combined"
506 , "billeksah-services"
509 , "binary-indexed-tree"
510 , "binary-protocol-zmq"
515 , "bindings-apr-util"
530 , "bindings-libstemmer"
532 , "bindings-linux-videodev2"
533 , "bindings-mpdecimal"
545 , "BiobaseTrainingData"
572 , "blaze-html-contrib"
573 , "blaze-html-hexpat"
575 , "blaze-textual-native"
578 , "BlogLiterately-diagrams"
584 , "boolean-normal-forms"
612 , "bytestring-rematch"
617 , "cabal-constraints"
622 , "cabal-install-bundle"
623 , "cabal-install-ghc72"
624 , "cabal-install-ghc74"
641 , "call-haskell-from-anything"
651 , "casadi-bindings-control"
652 , "casadi-bindings-core"
653 , "casadi-bindings-internal"
654 , "casadi-bindings-ipopt-interface"
655 , "casadi-bindings-snopt-interface"
665 , "categorical-algebra"
673 , "CC-delcont-ref-tf"
675 , "cctools-workqueue"
677 , "ceilometer-common"
678 , "cereal-enumerator"
689 , "chalkboard-viewer"
713 , "citeproc-hs-pandoc-filter"
723 , "clash-prelude-quickcheck"
724 , "clash-systemverilog"
731 , "clckwrks-plugin-bugs"
732 , "clckwrks-plugin-ircbot"
733 , "clckwrks-plugin-media"
734 , "clckwrks-plugin-page"
735 , "clckwrks-theme-bootstrap"
736 , "clckwrks-theme-clckwrks"
737 , "clckwrks-theme-geo-bootstrap"
746 , "cloudfront-signer"
761 , "cnc-spec-compiler"
764 , "Codec-Image-DevIL"
770 , "coinbase-exchange"
776 , "collections-base-instances"
780 , "combinat-diagrams"
781 , "combinatorial-problems"
782 , "combinator-interactive"
787 , "commsec-keyexchange"
798 , "computational-algebra"
810 , "conduit-audio-lame"
811 , "conduit-audio-samplerate"
813 , "conduit-network-stream"
814 , "conduit-resumablesink"
819 , "const-math-ghc-plugin"
820 , "constrained-categories"
821 , "constructive-algebra"
830 , "control-monad-attempt"
831 , "control-monad-exception-mtl"
832 , "control-monad-failure"
833 , "control-monad-failure-mtl"
834 , "Control-Monad-MultiPass"
835 , "Control-Monad-ST2"
836 , "contstuff-monads-tf"
837 , "contstuff-transformers"
838 , "convertible-ascii"
845 , "copilot-libraries"
854 , "coroutine-iteratee"
857 , "couchdb-enumerator"
881 , "crf-chain1-constrained"
882 , "crf-chain2-generic"
887 , "crypto-cipher-benchmarks"
892 , "csound-expression"
893 , "csound-expression-opcodes"
894 , "csound-expression-typed"
924 , "darcs-buildpackage"
981 , "definitive-filesystem"
982 , "definitive-graphics"
983 , "definitive-parser"
984 , "definitive-reactive"
1007 , "diagrams-builder"
1009 , "diagrams-haddock"
1015 , "dice-entropy-conduit"
1020 , "DifferentialEvolution"
1021 , "digestive-functors-hsp"
1027 , "direct-binary-files"
1028 , "directed-cubical"
1037 , "distributed-process-async"
1038 , "distributed-process-azure"
1039 , "distributed-process-client-server"
1040 , "distributed-process-execution"
1041 , "distributed-process-extras"
1042 , "distributed-process-platform"
1043 , "distributed-process-registry"
1044 , "distributed-process-supervisor"
1045 , "distributed-process-task"
1046 , "distributed-process-tests"
1047 , "distributed-process-zookeeper"
1049 , "distribution-plot"
1052 , "DnaProteinAlignment"
1061 , "doctest-discover"
1062 , "doctest-discover-configurator"
1065 , "download-media-content"
1109 , "DysFRP-Craftwerk"
1127 , "effective-aspects"
1128 , "effective-aspects-mzv"
1133 , "eibd-client-simple"
1150 , "embeddock-example"
1163 , "equational-reasoning"
1177 , "Eternal10Seconds"
1179 , "ethereum-client-haskell"
1180 , "ethereum-merkle-patricia-db"
1187 , "every-bit-counts"
1192 , "expat-enumerator"
1194 , "explicit-sharing"
1196 , "exposed-containers"
1200 , "extended-categories"
1219 , "feldspar-compiler"
1220 , "feldspar-language"
1223 , "FermatsLastMargin"
1226 , "ffmpeg-tutorials"
1234 , "filesystem-conduit"
1235 , "filesystem-enumerator"
1236 , "Finance-Quote-Yahoo"
1237 , "Finance-Treasury"
1241 , "FirstOrderTheory"
1245 , "fixed-point-vector"
1246 , "fixed-point-vector-space"
1248 , "fixed-storable-array"
1249 , "fix-parser-simple"
1251 , "fix-symbols-gitit"
1253 , "flexiwrap-smallcheck"
1262 , "flowlocks-framework"
1266 , "foldl-incremental"
1272 , "font-opengl-basic4x6"
1295 , "free-operational"
1299 , "free-theorems-counterexamples"
1300 , "free-theorems-seq"
1301 , "free-theorems-seq-webui"
1302 , "free-theorems-webui"
1313 , "functional-arrow"
1314 , "function-combine"
1325 , "gc-monitoring-wai"
1335 , "GeneralTicTacToe"
1338 , "genericserialize"
1339 , "generic-storable"
1350 , "GeomPredicates-SSE"
1355 , "ghc-events-analyze"
1356 , "ghc-events-parallel"
1384 , "gladexml-accessor"
1403 , "google-html5-slide"
1404 , "google-mail-filters"
1413 , "GPipe-TextureLoad"
1418 , "grapefruit-examples"
1420 , "grapefruit-records"
1422 , "grapefruit-ui-gtk"
1426 , "GraphHammer-examples"
1428 , "graphics-formats-collada"
1431 , "graph-rewriting-cl"
1432 , "graph-rewriting-gl"
1433 , "graph-rewriting-lambdascope"
1434 , "graph-rewriting-layout"
1435 , "graph-rewriting-ski"
1436 , "graph-rewriting-strategies"
1437 , "graph-rewriting-trs"
1438 , "graph-rewriting-ww"
1457 , "gtk2hs-cast-glade"
1458 , "gtk2hs-cast-gnomevfs"
1460 , "gtk2hs-cast-gtkglext"
1463 , "gtk3-mac-integration"
1467 , "gtk-mac-integration"
1469 , "gtk-serialized-event"
1471 , "guess-combinator"
1477 , "hack2-handler-happstack-server"
1478 , "hack2-handler-mongrel2-http"
1479 , "hack2-handler-warp"
1480 , "hack2-interface-wai"
1488 , "hack-contrib-press"
1490 , "hack-frontend-happstack"
1491 , "hack-handler-epoll"
1492 , "hack-handler-evhttp"
1493 , "hack-handler-fastcgi"
1494 , "hack-handler-happstack"
1495 , "hack-handler-hyena"
1496 , "hack-handler-kibro"
1497 , "hack-handler-simpleserver"
1499 , "hack-middleware-cleanpath"
1500 , "hack-middleware-clientsession"
1501 , "hack-middleware-jsonp"
1511 , "hakyll-blaze-templates"
1513 , "hakyll-contrib-links"
1534 , "happs-hsp-template"
1539 , "happstack-contrib"
1542 , "happstack-facebook"
1544 , "happstack-foundation"
1546 , "happstack-helpers"
1549 , "happstack-monad-peel"
1550 , "happstack-plugins"
1557 , "happybara-webkit"
1558 , "happybara-webkit-server"
1573 , "hashable-generics"
1587 , "haskell-brainfuck"
1589 , "haskell-course-preludes"
1590 , "haskelldb-connect-hdbc"
1591 , "haskelldb-connect-hdbc-catchio-mtl"
1592 , "haskelldb-connect-hdbc-catchio-tf"
1593 , "haskelldb-connect-hdbc-catchio-transformers"
1594 , "haskelldb-connect-hdbc-lifted"
1595 , "haskelldb-dynamic"
1597 , "haskelldb-hdbc-mysql"
1598 , "haskelldb-hdbc-odbc"
1599 , "haskelldb-hdbc-postgresql"
1600 , "haskelldb-hdbc-sqlite3"
1602 , "haskelldb-hsql-mysql"
1603 , "haskelldb-hsql-odbc"
1604 , "haskelldb-hsql-postgresql"
1605 , "haskelldb-hsql-sqlite3"
1608 , "haskell-formatter"
1610 , "haskell-in-space"
1611 , "haskell-neo4j-client"
1614 , "haskell-openflow"
1615 , "haskell-pdf-presenter"
1616 , "haskell-platform-test"
1621 , "haskell-src-meta-mwotton"
1623 , "haskell-type-exts"
1634 , "haskoin-protocol"
1639 , "haskoon-httpspec"
1642 , "haskore-realtime"
1643 , "haskore-supercollider"
1644 , "haskore-synthesizer"
1680 , "hdaemonize-buildfix"
1715 , "her-lexer-parsec"
1720 , "herringbone-embed"
1728 , "hexpat-pickle-generic"
1741 , "HGamer3D-CAudio-Binding"
1742 , "HGamer3D-CEGUI-Binding"
1743 , "HGamer3D-Enet-Binding"
1744 , "HGamer3D-Graphics3D"
1746 , "HGamer3D-InputSystem"
1747 , "HGamer3D-Network"
1748 , "HGamer3D-Ogre-Binding"
1749 , "HGamer3D-OIS-Binding"
1750 , "HGamer3D-SDL2-Binding"
1751 , "HGamer3D-SFML-Binding"
1752 , "HGamer3D-WinEvent"
1767 , "hierarchical-clustering-diagrams"
1775 , "hinduce-classifier"
1776 , "hinduce-classifier-decisiontree"
1777 , "hinduce-examples"
1794 , "HLearn-datastructures"
1807 , "hmatrix-gsl-stats"
1808 , "hmatrix-quadprogpp"
1838 , "Holumbus-Distribution"
1839 , "Holumbus-MapReduce"
1840 , "Holumbus-Searchengine"
1841 , "Holumbus-Storage"
1912 , "hs-carbon-examples"
1916 , "hscurses-fish-ex"
1950 , "hsndfile-storablevector"
1952 , "hs-nombre-generator"
1961 , "hspec-experimental"
1971 , "hsqml-demo-morris"
1972 , "hsqml-demo-samples"
1982 , "HStringTemplateHelpers"
1984 , "hs-twitterarchiver"
2004 , "http-client-request-modifiers"
2005 , "http-conduit-browser"
2006 , "http-conduit-downloader"
2010 , "https-everywhere-rules"
2024 , "hunt-searchengine"
2027 , "husk-scheme-libs"
2043 , "hydrogen-cli-args"
2045 , "hydrogen-parsing"
2046 , "hydrogen-prelude"
2047 , "hydrogen-prelude-parsec"
2060 , "ide-backend-server"
2067 , "ige-mac-integration"
2074 , "ihaskell-display"
2076 , "ihaskell-juicypixels"
2080 , "ihaskell-rlangqq"
2088 , "ImperativeHaskell"
2094 , "incremental-computing"
2095 , "incremental-sat-solver"
2102 , "InfixApplicative"
2109 , "interleavableGen"
2112 , "interpolatedstring-qq"
2113 , "interpolatedstring-qq-mwotton"
2123 , "iptables-helpers"
2132 , "iteratee-compress"
2141 , "ivory-quickcheck"
2155 , "java-bridge-extras"
2176 , "JSON-Combinator-Examples"
2185 , "JuicyPixels-repa"
2186 , "JunkDB-driver-gdbm"
2191 , "kansas-lava-cores"
2192 , "kansas-lava-papilio"
2193 , "kansas-lava-shake"
2195 , "keera-hails-mvc-model-lightmodel"
2196 , "keera-hails-reactive-fs"
2205 , "kickass-torrents-dump-parser"
2212 , "koellner-phonetic"
2216 , "kure-your-boilerplate"
2220 , "labyrinth-server"
2226 , "LambdaCalculator"
2229 , "lambdacube-bullet"
2230 , "lambdacube-engine"
2231 , "lambdacube-examples"
2232 , "lambdacube-samples"
2237 , "LambdaPrettyQuote"
2245 , "language-c-comments"
2246 , "language-c-inline"
2249 , "language-java-classfile"
2253 , "language-python-colour"
2255 , "language-spelling"
2260 , "latest-npm-version"
2264 , "layout-bootstrap"
2274 , "learn-physics-examples"
2277 , "leveldb-haskell-fork"
2294 , "libsystemd-daemon"
2300 , "lighttpd-conf-qq"
2305 , "linear-algebra-cblas"
2308 , "linearscan-hoopl"
2321 , "listlike-instances"
2322 , "list-t-html-parser"
2329 , "llvm-general-quote"
2336 , "LogicGrowsOnTrees"
2337 , "LogicGrowsOnTrees-MPI"
2338 , "LogicGrowsOnTrees-network"
2339 , "LogicGrowsOnTrees-processes"
2374 , "manatee-anything"
2379 , "manatee-filemanager"
2380 , "manatee-imageviewer"
2382 , "manatee-pdfviewer"
2383 , "manatee-processmanager"
2385 , "manatee-template"
2386 , "manatee-terminal"
2395 , "markov-processes"
2397 , "marmalade-upload"
2411 , "MaybeT-monads-tf"
2412 , "MaybeT-transformers"
2426 , "meta-par-accelerate"
2434 , "microformats2-parser"
2463 , "modular-prelude-classy"
2464 , "module-management"
2469 , "monad-atom-simple"
2471 , "MonadCatchIO-mtl-foreign"
2472 , "MonadCatchIO-transformers-foreign"
2475 , "monadiccp-gecode"
2476 , "monad-interleave"
2481 , "monad-mersenne-random"
2485 , "monad-stlike-stm"
2493 , "mongrel2-handler"
2521 , "multiplate-simplified"
2522 , "multirec-alt-deriver"
2527 , "musicbrainz-email"
2542 , "mysnapsession-example"
2543 , "mysql-simple-quasi"
2544 , "mysql-simple-typed"
2547 , "nagios-plugin-ekg"
2573 , "network-anonymous-i2p"
2575 , "network-bytestring"
2576 , "network-connection"
2578 , "network-minihttp"
2581 , "network-simple-tls"
2582 , "network-topic-models"
2583 , "network-transport-amqp"
2584 , "network-websocket"
2609 , "not-gloss-examples"
2636 , "ois-input-manager"
2650 , "openexchangerates"
2657 , "openpgp-crypto-api"
2659 , "openssh-github-keys"
2670 , "order-maintenance"
2687 , "parameterized-data"
2689 , "parco-attoparsec"
2690 , "parconc-examples"
2723 , "persistent-hssqlppp"
2725 , "persistent-protobuf"
2731 , "pg-harness-server"
2748 , "pipes-cereal-plus"
2750 , "pipes-network-tls"
2751 , "pipes-p2p-examples"
2761 , "plugins-multistage"
2767 , "pointless-haskell"
2768 , "pointless-lenses"
2769 , "pointless-rewrite"
2773 , "polytypeable-utils"
2774 , "pontarius-mediaserver"
2788 , "postgresql-schema"
2789 , "postgresql-simple-typed"
2790 , "postgresql-typed"
2802 , "prelude-generalize"
2804 , "preprocess-haskell"
2810 , "PriorityChansConverger"
2812 , "ProbabilityMonads"
2817 , "process-listlike"
2818 , "process-progress"
2820 , "procrastinating-structure"
2821 , "procrastinating-variable"
2824 , "profunctor-extras"
2829 , "proj4-hs-bindings"
2832 , "prolog-graph-lib"
2837 , "protocol-buffers-descriptor-fork"
2838 , "protocol-buffers-fork"
2839 , "prove-everywhere-server"
2842 , "publicsuffixlistcreate"
2859 , "push-notify-general"
2862 , "puzzle-draw-cmdline"
2872 , "querystring-pickle"
2877 , "quickcheck-regex"
2878 , "quickcheck-relaxng"
2879 , "quickcheck-rematch"
2888 , "radium-formula-parser"
2890 , "rail-compiler-editor"
2896 , "random-access-list"
2900 , "random-hypergeometric"
2907 , "raven-haskell-scotty"
2915 , "reactive-banana-sdl"
2916 , "reactive-banana-threepenny"
2917 , "reactive-fieldtrip"
2921 , "really-simple-xml-parser"
2925 , "record-preprocessor"
2933 , "reflection-extras"
2944 , "regional-pointers"
2946 , "regions-monadsfd"
2947 , "regions-monadstf"
2969 , "representable-functors"
2970 , "representable-profunctors"
2971 , "representable-tries"
2977 , "restricted-workers"
2979 , "resumable-exceptions"
2980 , "rethinkdb-client-driver"
2991 , "ripple-federation"
3003 , "roguestar-engine"
3006 , "RollingDirectory"
3015 , "roundtrip-string"
3037 , "safer-file-handles"
3038 , "safer-file-handles-bytestring"
3039 , "safer-file-handles-text"
3047 , "salvia-websocket"
3048 , "samtools-iteratee"
3051 , "satchmo-backends"
3052 , "satchmo-examples"
3058 , "scan-vector-machine"
3063 , "scholdoc-citeproc"
3097 , "semigroups-actions"
3105 , "seqloc-datafiles"
3109 , "servant-postgresql"
3112 , "ses-html-snaplet"
3131 , "shakespeare-i18n"
3136 , "Shellac-compatline"
3137 , "Shellac-editline"
3138 , "Shellac-haskeline"
3139 , "Shellac-readline"
3151 , "simple-bluetooth"
3161 , "simple-log-syslog"
3164 , "simple-postgresql-orm"
3168 , "simple-templates"
3199 , "snaplet-actionlog"
3201 , "snaplet-environments"
3206 , "snaplet-mongodb-minimalistic"
3207 , "snaplet-mysql-simple"
3214 , "snaplet-typed-sessions"
3215 , "snaplet-wordpress"
3220 , "sndfile-enumerators"
3221 , "sneathlane-haste"
3231 , "sonic-visualiser"
3235 , "source-code-server"
3246 , "special-functors"
3248 , "speculation-transformers"
3262 , "sqlite-simple-typed"
3264 , "sql-simple-mysql"
3266 , "sql-simple-postgresql"
3267 , "sql-simple-sqlite"
3273 , "stackage-curator"
3278 , "statistics-dirichlet"
3279 , "statistics-fusion"
3284 , "stm-chunked-queues"
3288 , "storable-static-array"
3290 , "storablevector-carray"
3291 , "storablevector-streamfusion"
3292 , "Strafunski-Sdf2Haskell"
3296 , "strict-concurrency"
3299 , "structured-mongoDB"
3305 , "sunroof-compiler"
3306 , "sunroof-examples"
3308 , "supercollider-midi"
3327 , "syntax-attoparsec"
3329 , "syntax-example-json"
3334 , "syntax-trees-fork-bairyn"
3336 , "synthesizer-alsa"
3337 , "synthesizer-core"
3338 , "synthesizer-dimensional"
3339 , "synthesizer-midi"
3341 , "system-canonicalpath"
3343 , "system-random-effect"
3355 , "tamarin-prover-term"
3356 , "tamarin-prover-theory"
3357 , "tamarin-prover-utils"
3370 , "template-default"
3371 , "template-haskell-util"
3378 , "termbox-bindings"
3382 , "test-framework-doctest"
3383 , "test-framework-quickcheck"
3395 , "text-register-machine"
3397 , "text-xml-generic"
3402 , "theoremquest-client"
3428 , "timestamp-subprocess-lines"
3440 , "tokyocabinet-haskell"
3446 , "to-string-instances"
3450 , "transactional-events"
3451 , "transformers-convert"
3452 , "transformers-runnable"
3455 , "treemap-html-tools"
3465 , "tsession-happstack"
3473 , "twentefp-rosetree"
3485 , "twitter-enumerator"
3487 , "twitter-types-lens"
3496 , "type-equality-check"
3503 , "typelevel-tensor"
3508 , "type-ord-spine-cereal"
3516 , "typography-geometry"
3527 , "unbounded-delays-units"
3528 , "unboxed-containers"
3529 , "unicode-normalization"
3539 , "unix-process-conduit"
3541 , "unordered-containers-rematch"
3551 , "uri-enumerator-file"
3555 , "urldisp-happstack"
3565 , "uvector-algorithms"
3576 , "vaultaire-common"
3580 , "vector-bytestring"
3584 , "vector-functorlazy"
3585 , "vector-instances-collections"
3587 , "vector-read-instances"
3588 , "vector-space-opengl"
3600 , "visual-graphrewrite"
3615 , "wai-handler-devel"
3616 , "wai-handler-snap"
3617 , "wai-handler-webkit"
3620 , "wai-logger-prefork"
3621 , "wai-middleware-cache"
3622 , "wai-middleware-cache-redis"
3623 , "wai-middleware-catch"
3624 , "wai-middleware-consul"
3625 , "wai-middleware-etag"
3626 , "wai-middleware-headers"
3627 , "wai-middleware-hmac-client"
3628 , "wai-middleware-preprocessor"
3629 , "wai-middleware-route"
3630 , "wai-middleware-static-caching"
3633 , "wai-session-tokyocabinet"
3634 , "wai-static-cache"
3647 , "WebBits-multiplate"
3648 , "web-browser-in-haskell"
3650 , "webcrank-dispatch"
3655 , "webkit-javascriptcore"
3658 , "web-routes-quasi"
3659 , "web-routes-transformers"
3674 , "Win32-dhcp-server"
3677 , "Win32-junction-point"
3681 , "Win32-services-wrapper"
3704 , "wumpus-microprint"
3723 , "xhaskell-library"
3735 , "xml-enumerator-combinators"
3744 , "xmms2-client-glib"
3745 , "xmonad-bluetilebranch"
3746 , "xmonad-contrib-bluetilebranch"
3762 , "yahoo-web-search"
3778 , "yesod-angular-ui"
3779 , "yesod-auth-account-fork"
3780 , "yesod-auth-kerberos"
3783 , "yesod-auth-smbclient"
3786 , "yesod-continuations"
3787 , "yesod-datatables"
3789 , "yesod-eventsource"
3795 , "yesod-pagination"
3799 , "yesod-purescript"
3801 , "yesod-routes-flow"
3802 , "yesod-routes-typescript"
3805 , "yesod-session-redis"
3819 , "Yogurt-Standalone"
3842 , "zoom-cache-sndfile"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list