Dis is dumb Change-Id: If09300eedff7227ed452dcec7a8e80c7ffb24757 Reviewed-on: https://cl.tvl.fyi/c/depot/+/3231 Tested-by: BuildkiteCI Reviewed-by: Profpatsch <mail@profpatsch.de>
		
			
				
	
	
		
			72 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			Haskell
		
	
	
	
	
	
			
		
		
	
	
			72 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			Haskell
		
	
	
	
	
	
{-# LANGUAGE LambdaCase #-}
 | 
						|
{-# LANGUAGE OverloadedStrings #-}
 | 
						|
{-# LANGUAGE MultiWayIf #-}
 | 
						|
{-# LANGUAGE ScopedTypeVariables #-}
 | 
						|
import qualified Text.HTML.TagSoup as Tag
 | 
						|
import qualified Data.Text as Text
 | 
						|
import Data.Text (Text)
 | 
						|
import qualified Data.List as List
 | 
						|
import Data.Maybe
 | 
						|
import Text.Nicify
 | 
						|
import qualified Text.Read as Read
 | 
						|
import Numeric.Natural
 | 
						|
import Data.Either
 | 
						|
import qualified Data.ByteString as ByteString
 | 
						|
import qualified Data.Text.Encoding
 | 
						|
 | 
						|
parseNat :: Text.Text -> Maybe Natural
 | 
						|
parseNat = Read.readMaybe . Text.unpack
 | 
						|
 | 
						|
printNice :: Show a => a -> IO ()
 | 
						|
printNice = putStrLn . nicify . show
 | 
						|
 | 
						|
type Tag = Tag.Tag Text.Text
 | 
						|
 | 
						|
main = do
 | 
						|
  reverseHtml <- readStdinUtf8
 | 
						|
  printNice $ List.sortOn snd $ packagesAndReverseDeps reverseHtml
 | 
						|
 | 
						|
  where
 | 
						|
    readStdinUtf8 = Data.Text.Encoding.decodeUtf8 <$> ByteString.getContents
 | 
						|
 | 
						|
-- | reads the table provided by https://packdeps.haskellers.com/reverse
 | 
						|
-- figuring out all sections (starting with the link to the package name),
 | 
						|
-- then figuring out the name of the package and the first column,
 | 
						|
-- which is the number of reverse dependencies of the package
 | 
						|
packagesAndReverseDeps reverseHtml = do
 | 
						|
  let tags = Tag.parseTags reverseHtml
 | 
						|
  let sections =  Tag.partitions (isJust . reverseLink) tags
 | 
						|
  let sectionNames = map (fromJust . reverseLink . head) sections
 | 
						|
  mapMaybe
 | 
						|
    (\(name :: Text.Text, sect) -> do
 | 
						|
        reverseDeps <- firstNaturalNumber sect
 | 
						|
        pure (sectionPackageName name sect, reverseDeps) :: Maybe (Text.Text, Natural))
 | 
						|
    $ zip sectionNames sections
 | 
						|
 | 
						|
 | 
						|
  where
 | 
						|
    reverseLink = \case
 | 
						|
      Tag.TagOpen "a" attrs -> mapFind attrReverseLink attrs
 | 
						|
      _ -> Nothing
 | 
						|
 | 
						|
    attrReverseLink = \case
 | 
						|
      ("href", lnk) -> if
 | 
						|
          | "packdeps.haskellers.com/reverse/" `Text.isInfixOf` lnk -> Just lnk
 | 
						|
          | otherwise -> Nothing
 | 
						|
      _ -> Nothing
 | 
						|
 | 
						|
    sectionPackageName :: Text -> [Tag] -> Text
 | 
						|
    sectionPackageName sectionName = \case
 | 
						|
      (_: Tag.TagText name : _) -> name
 | 
						|
      (_: el : _) -> sectionName
 | 
						|
      xs -> sectionName
 | 
						|
 | 
						|
 | 
						|
    firstNaturalNumber :: [Tag] -> Maybe Natural
 | 
						|
    firstNaturalNumber =
 | 
						|
      mapFind (\case
 | 
						|
        Tag.TagText t -> parseNat t
 | 
						|
        _ -> Nothing)
 | 
						|
 | 
						|
    mapFind :: (a -> Maybe b) -> [a] -> Maybe b
 | 
						|
    mapFind f xs = fromJust . f <$> List.find (isJust . f) xs
 |