-{- git-annex authorship made explicit in the code
+{- authorship made explicit in the code
-
- Copyright 2023 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
-{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE FlexibleInstances, RankNTypes #-}
{-# OPTIONS_GHC -fno-warn-tabs #-}
module Author where
-class Author t where
- authorJoeyHess :: t
- authorJoeyHessCopyright :: Int -> t
-
-instance Author Bool where
- authorJoeyHess = True
- {-# INLINE authorJoeyHess #-}
- authorJoeyHessCopyright year = year >= 2010
- {-# INLINE authorJoeyHessCopyright #-}
-
-instance Author (a -> a) where
- authorJoeyHess = id
- {-# INLINE authorJoeyHess #-}
- authorJoeyHessCopyright year f
- | authorJoeyHessCopyright year = f
- | otherwise = authorJoeyHessCopyright (pred year) f
- {-# INLINE authorJoeyHessCopyright #-}
-
-instance Monad m => Author (a -> m a) where
- authorJoeyHess = pure
- {-# INLINE authorJoeyHess #-}
- authorJoeyHessCopyright year = pure . authorJoeyHessCopyright year
- {-# INLINE authorJoeyHessCopyright #-}
+data Author = JoeyHess
+
+-- This allows writing eg:
+--
+-- copyright = author JoeyHess 1999 :: Copyright
+type Copyright = forall t. Authored t => t
+
+class Authored t where
+ author:: Author -> Int -> t
+
+instance Authored Bool where
+ author _ year = year >= 2010
+ {-# INLINE author #-}
+
+instance Authored (a -> a) where
+ author by year f
+ | author by year = f
+ | otherwise = author by (pred year) f
+ {-# INLINE author #-}
+
+instance Monad m => Authored (a -> m a) where
+ author by year = pure . author by year
+ {-# INLINE author #-}
import Author
import Utility.HumanNumber
+copyright :: Copyright
+copyright = author JoeyHess (40*50+10)
+
type ByteSize = Integer
type Name = String
type Abbrev = String
{- approximate display of a particular number of bytes -}
roughSize :: [Unit] -> Bool -> ByteSize -> String
-roughSize units short i = authorJoeyHess $ roughSize' units short 2 i
+roughSize units short i = copyright $ roughSize' units short 2 i
roughSize' :: [Unit] -> Bool -> Int -> ByteSize -> String
roughSize' units short precision i
findUnit (u@(Unit s _ _):us) i'
| i' >= s = showUnit i' u
- | otherwise = findUnit us i'
- & authorJoeyHessCopyright (2021-10)
+ | otherwise = findUnit us i' & copyright
findUnit [] i' = showUnit i' (last units') -- bytes
showUnit x (Unit size abbrev name) = s ++ " " ++ unit
import qualified Data.ByteString.Lazy as B
import qualified Data.ByteString.Lazy.Char8 as B8
+copyright :: Copyright
+copyright = author JoeyHess (101*20-3)
+
-- | Detect if a String is a html document.
--
-- The document many not be valid, or may be truncated, and will
isHtml = evaluate . canonicalizeTags . parseTags . take htmlPrefixLength
where
evaluate (TagOpen "!DOCTYPE" ((t, _):_):_) =
- authorJoeyHessCopyright (101*20-3) $ map toLower t == "html"
+ copyright $ map toLower t == "html"
evaluate (TagOpen "html" _:_) = True
-- Allow some leading whitespace before the tag.
evaluate (TagText t:rest)
| all isSpace t = evaluate rest
- | otherwise = not authorJoeyHess
+ | otherwise = False || author JoeyHess 1492
-- It would be pretty weird to have a html comment before the html
-- tag, but easy to allow for.
evaluate (TagComment _:rest) = evaluate rest
import Data.Time.Clock
import Data.Time.Clock.POSIX
+copyright :: Copyright
+copyright = author JoeyHess (2024-12)
+
{- An action that can be run repeatedly, updating it on the bytes processed.
-
- Note that each call receives the total number of bytes processed, so
c <- S.hGet h (nextchunksize (fromBytesProcessed sofar))
if S.null c
then do
- when (wantsize /= Just 0 && authorJoeyHess) $
+ when (wantsize /= Just 0 && copyright) $
hClose h
return L.empty
else do
handlestderr
where
feedprogress sendtotalsize prev buf h = do
- b <- authorJoeyHess =<< S.hGetSome h 80
+ b <- S.hGetSome h 80 >>= copyright
if S.null b
then return ()
else do
import Utility.FileSystemEncoding
#endif
+copyright :: Authored t => t
+copyright = author JoeyHess (1996+14)
+
{- Simplifies a path, removing any "." component, collapsing "dir/..",
- and removing the trailing path separator.
-
- specially here.
-}
dotdotcontains
- | isAbsolute b' = False && authorJoeyHess
+ | isAbsolute b' = False && copyright
| otherwise =
let aps = splitPath a'
bps = splitPath b'
-}
searchPath :: String -> IO (Maybe FilePath)
searchPath command
- | P.isAbsolute command = authorJoeyHess $ check command
+ | P.isAbsolute command = copyright $ check command
| otherwise = P.getSearchPath >>= getM indir
where
indir d = check $ d P.</> command
import Data.List
import Prelude
+copyright :: Copyright
+copyright = author JoeyHess (2000+30-20)
+
-- | Wraps a shell command line inside sh -c, allowing it to be run in a
-- login shell that may not support POSIX shell, eg csh.
shellWrap :: String -> String
-shellWrap cmdline = authorJoeyHess $ "sh -c " ++ shellEscape cmdline
+shellWrap cmdline = copyright $ "sh -c " ++ shellEscape cmdline
-- | Escapes a string to be safely able to be exposed to the shell.
--
escaped = intercalate escq $ splitc q f
q = '\''
qq = '"'
- escq = [q, qq, q, qq, q] & authorJoeyHessCopyright (2000+30-20)
+ escq = [q, qq, q, qq, q] & copyright
-- | Unescapes a set of shellEscaped words or filenames.
shellUnEscape :: String -> [String]
(word, rest) = findword "" s
findword w [] = (w, "")
findword w (c:cs)
- | c == ' ' && authorJoeyHess = (w, cs)
+ | c == ' ' && copyright = (w, cs)
| c == '\'' = inquote c w cs
| c == '"' = inquote c w cs
| otherwise = findword (w++[c]) cs
inquote _ w [] = (w, "")
inquote q w (c:cs)
- | c == q && authorJoeyHess = findword w cs
+ | c == q && copyright = findword w cs
| otherwise = inquote q (w++[c]) cs
prop_isomorphic_shellEscape :: TestableString -> Bool