Skip to content

Instantly share code, notes, and snippets.

@Garciat
Last active January 2, 2016 09:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Garciat/69a84718f6765dc8ff7a to your computer and use it in GitHub Desktop.
Save Garciat/69a84718f6765dc8ff7a to your computer and use it in GitHub Desktop.
pacman packages by date
import std.stdio;
import std.process;
import std.string;
import std.range;
import std.algorithm;
import std.typecons;
import core.sys.posix.time;
bool notNullOrEmpty(T)(T s)
{
return s != null || !s.empty;
}
bool notNull(T)(T s)
{
return s != null;
}
auto dict(alias kf, alias vf, T)(T items)
{
alias TK = typeof(kf(items.front));
alias TV = typeof(vf(items.front));
TV[TK] result;
foreach (item; items)
{
result[kf(item)] = vf(item);
}
return result;
}
string[string][] getPacmanPackages()
{
struct Property
{
string key, value;
}
auto parseProperty(string line)
{
auto ix = line.indexOf(':');
if (ix == -1) return null;
auto k = line[0..ix].strip;
auto v = line[ix+1..$].strip;
return new Property(k, v);
}
auto parsePackage(string lines)
{
return
lines
.splitter('\n')
.map!parseProperty
.filter!notNull
.dict!(x => x.key, x => x.value);
}
return
["pacman", "-Qi"]
.execute
.output
.splitter("\n\n")
.filter!notNullOrEmpty
.map!parsePackage
.array;
}
auto fmtDateTime(string s)
{
tm time;
strptime(s.ptr, "%a %d %b %Y %I:%M:%S %p %Z", &time);
char buf[30];
auto len = strftime(buf.ptr, buf.length, "%Y-%m-%dT%H:%M:%S%Z", &time);
auto fmt = buf[0..len].idup;
return fmt;
}
void main()
{
auto pks = getPacmanPackages();
foreach (pk; pks)
{
writeln(pk["Install Date"].fmtDateTime, ' ', pk["Name"], ' ', pk["Version"]);
}
}
module Main where
import Data.Maybe
import Data.List
import Data.List.Split
import System.Process
import Data.Time.Parse
import Data.Time.LocalTime
import Data.Time.ISO8601
import qualified Data.Text as T
----------------
coalesce :: (a -> a -> Maybe a) -> [a] -> [a]
coalesce f x =
case x of
(p:q:x') ->
case f p q of
Nothing -> p : coalesce f (q : x')
Just r -> coalesce f (r : x')
_ -> x
fromRight :: Either a b -> b
fromRight (Right x) = x
strip :: String -> String
strip = T.unpack . T.strip . T.pack
----------------
type Entry = (String, String)
type Package = [Entry]
pacmanQueryInfoRaw :: IO String
pacmanQueryInfoRaw = readProcess "pacman" ["-Qi"] []
pacmanQueryInfo :: IO [Package]
pacmanQueryInfo = parsePackageList <$> pacmanQueryInfoRaw
parsePackageList :: String -> [Package]
parsePackageList input = map parsePackage blocks
where
blocks = endBy "\n\n" input
parsePackage :: String -> Package
parsePackage input = map fromRight $ coalesce joiner entries
where
inputLines = lines input
entries = map parsePackageEntry inputLines
joiner (Right (title, value)) (Left value') = Just $ Right (title, value ++ " " ++ value')
joiner _ _ = Nothing
parsePackageEntry :: String -> Either String Entry
parsePackageEntry input =
case break (== ':') input of
(value, []) -> Left $ strip value
(title, (_:value)) -> Right (strip title, strip value)
packageEntryValue :: String -> Package -> String
packageEntryValue key = fromJust . lookup key
packageName :: Package -> String
packageName = packageEntryValue "Name"
packageVersion :: Package -> String
packageVersion = packageEntryValue "Version"
packageInstallDate :: Package -> String
packageInstallDate = formatPackageDate . packageEntryValue "Install Date"
formatPackageDate :: String -> String
formatPackageDate input = formatISO8601 $ localTimeToUTC utc time
where
Just (time, _) = strptime "%a %d %b %Y %I:%M:%S %p" input
formatPackage :: Package -> String
formatPackage package = intercalate " " [installDate, name, version]
where
name = packageName package
version = packageVersion package
installDate = packageInstallDate package
main = do { packages <- pacmanQueryInfo
; putStrLn $ unlines $ map formatPackage packages
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment