Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

init commit

  • Loading branch information...
commit 774697da11f2d5caf479d57fd2814d0d3715474c 0 parents
@lilydjwg authored
12 .gitignore
@@ -0,0 +1,12 @@
+*.hi
+acpi_handler/main
+cat/cat
+expand/expand
+fcitx-switch-quote/fcitx-switch-quote
+lib/Text/Lrc
+nl/nl
+packagestat/packagestat
+packagestat/packagestat_lazy
+packagestat/pkgs
+routespeed/routespeed
+sendmail/sendmail
7 acpi_handler/Makefile
@@ -0,0 +1,7 @@
+.PHONY: all clean
+
+all:
+ ghc -O2 main -i../lib
+
+clean:
+ -rm *.o *.hi
66 acpi_handler/main.hs
@@ -0,0 +1,66 @@
+module Main where
+
+import Control.Monad (when)
+import List (isPrefixOf)
+import System.Cmd (rawSystem)
+import System.Environment (getArgs)
+import System.Exit
+import System.Posix.Env (putEnv)
+import System.Process (readProcessWithExitCode)
+
+import Text.String (isSpace, stripl)
+
+main :: IO ()
+main = do
+ args <- getArgs
+ when (length args < 1) exitFailure
+ let funcargs = tail args
+ case head args of
+ "button/zoom" -> touchpadSwitch funcargs
+ _ -> logger $ "ACPI group/action undefined: " ++ show args
+
+logger :: String -> IO ()
+logger = putStrLn
+
+data TouchpadState = On | Off deriving (Eq, Show)
+
+touchpadSwitch :: [String] -> IO ()
+touchpadSwitch args = do
+ setupDisplay
+ mbstate <- touchpadGetstate
+ case mbstate of
+ Nothing -> return ()
+ Just status -> touchpadSetstate $ touchpadNegate status
+
+touchpadGetstate :: IO (Maybe TouchpadState)
+touchpadGetstate = do
+ (status, info, err) <- readProcessWithExitCode "sudo" ["-u", "lilydjwg", "synclient"] ""
+ if status /= ExitSuccess
+ then return Nothing
+ else return $ touchpadGetstateFromString info
+
+touchpadSetstate :: TouchpadState -> IO ()
+touchpadSetstate state = rawSystem "sudo" ["-u", "lilydjwg", "synclient",
+ "TouchpadOff=" ++ touchpadToOutside state] >> return ()
+
+touchpadGetstateFromString :: String -> Maybe TouchpadState
+touchpadGetstateFromString s =
+ if length line == 1
+ then case last $ head line of
+ '0' -> Just On
+ '1' -> Just Off
+ otherwise -> Nothing
+ else Nothing
+ where line = filter (isPrefixOf "TouchpadOff") $ map stripl $ lines s
+
+touchpadNegate :: TouchpadState -> TouchpadState
+touchpadNegate On = Off
+touchpadNegate Off = On
+
+touchpadToOutside :: TouchpadState -> String
+touchpadToOutside On = "0"
+touchpadToOutside Off = "1"
+
+setupDisplay :: IO ()
+setupDisplay = putEnv $ "DISPLAY=:0"
+
27 cat/cat.hs
@@ -0,0 +1,27 @@
+import System.Environment
+import System.IO
+import Control.Monad
+import qualified Data.ByteString.Lazy.Char8 as BS
+import Data.List
+
+main = do
+ diamond >>= mapM BS.putStr
+
+diamond :: IO ([BS.ByteString])
+diamond = do
+ args <- getArgs
+ let filenames = fst $ getFileArgs args
+ if null filenames then
+ BS.getContents >>= return . (:[])
+ else
+ forM filenames (\f -> case f of
+ "-" -> BS.getContents
+ otherwise -> BS.readFile f)
+
+isFileName :: String -> Bool
+isFileName "-" = True
+isFileName ('-':_) = False
+isFileName _ = True
+
+getFileArgs :: [String] -> ([String], [String])
+getFileArgs = partition isFileName
35 cat/cat.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python3
+# vim:fileencoding=utf-8
+
+import sys
+
+def catafile(fp):
+ for l in fp:
+ sys.stdout.write(l)
+
+def getFileArgs():
+ filenames = []
+ args = []
+ for arg in sys.argv[1:]:
+ if arg == '-':
+ l = filenames
+ elif arg.startswith('-'):
+ l = args
+ else:
+ l = filenames
+ l.append(arg)
+ return filenames, args
+
+def main():
+ fns = getFileArgs()[0]
+ if fns:
+ for f in fns:
+ if f == '-':
+ catafile(sys.stdin)
+ else:
+ catafile(open(f))
+ else:
+ catafile(sys.stdin)
+
+if __name__ == '__main__':
+ main()
8 expand/expand.hs
@@ -0,0 +1,8 @@
+filterIO :: (String -> String) -> IO ()
+filterIO f = interact $ unlines . map f . lines
+
+expand :: String -> String
+expand s = let (word:times:[]) = words s
+ in unwords $ replicate (read times) word
+
+main = filterIO expand
18 fcitx-switch-quote/fcitx-switch-quote.hs
@@ -0,0 +1,18 @@
+import Control.Applicative ((<$>))
+import System.Cmd (rawSystem)
+import System.Directory (getHomeDirectory)
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
+
+import Text.String (trChar)
+
+main = do
+ file <- getFile
+ TIO.readFile file >>= (TIO.writeFile file) . (T.map (trChar "“”‘’『』「」" "『』「」“”‘’"))
+ reloadFcitx
+
+getFile :: IO FilePath
+getFile = (++ "/.config/fcitx/data/punc.mb.zh_CN") <$> getHomeDirectory
+
+reloadFcitx :: IO ()
+reloadFcitx = rawSystem "fcitx-remote" ["fcitx-remote", "-r"] >> return ()
11 fcitx-switch-quote/fcitx-switch-quote.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python3
+# vim:fileencoding=utf-8
+
+import os
+
+m = str.maketrans('“”‘’『』「」', '『』「」“”‘’')
+file = os.path.expanduser("~/.config/fcitx/data/punc.mb.zh_CN")
+
+c = open(file).read().translate(m)
+open(file, 'w').write(c)
+os.execvp('fcitx-remote', ['fcitx-remote', '-r'])
26 lib/Math/Number.hs
@@ -0,0 +1,26 @@
+module Math.Number (
+ nrWidth,
+ filesize,
+) where
+
+import Text.Printf (printf)
+
+nrWidth :: Integral a => a -> a
+nrWidth = ceiling . (logBase 10) . fromIntegral
+
+filesize :: (Integral a, Show a) => a -> String
+filesize n =
+ if level /= 0
+ then printf "%.1f%ciB" m unit
+ else show n ++ "B"
+ where (m, level) = liftUnit (fromIntegral n) 0
+ unit = units !! (level-1)
+
+liftUnit :: Double -> Int -> (Double, Int)
+liftUnit n u =
+ if n > 1100 && u < maxLevel
+ then liftUnit (n/1024) (u+1)
+ else (n, u)
+ where maxLevel = length units
+
+units = "KMGTP"
14 lib/Sys/Path.hs
@@ -0,0 +1,14 @@
+module Sys.Path (
+ expandUser,
+) where
+
+import Control.Applicative ((<$>))
+import System.Directory (getHomeDirectory)
+import System.Posix.User (homeDirectory, getUserEntryForName, UserEntry(..))
+
+expandUser :: FilePath -> IO FilePath
+expandUser "~" = getHomeDirectory
+expandUser ('~':'/':p) = fmap (++ "/" ++ p) getHomeDirectory
+expandUser ('~':up) = let (u, p) = break (== '/') up
+ in fmap (++ tail p) (homeDirectory <$> getUserEntryForName u)
+expandUser p = return p
12 lib/Sys/Time.hs
@@ -0,0 +1,12 @@
+module Sys.Time (
+ timeit,
+) where
+
+import CPUTime (getCPUTime)
+
+timeit :: IO () -> IO Integer
+timeit action = do
+ a <- getCPUTime
+ action
+ b <- getCPUTime
+ return $ b - a
6 lib/Text/Lines.hs
@@ -0,0 +1,6 @@
+module Text.Lines (
+ getIndent,
+) where
+
+getIndent :: [String] -> Int
+getIndent = minimum . (map (length . (takeWhile (==' '))))
100 lib/Text/Lrc.hs
@@ -0,0 +1,100 @@
+module Text.Lrc (
+ parseLrc,
+ addTime,
+ lrcAddOffset,
+ Lrc(..),
+ LrcLine(..),
+) where
+
+import Data.Char (isDigit)
+import Data.Functor ((<$>))
+import Data.List (sort)
+import Data.Maybe (isJust, fromJust)
+import Text.ParserCombinators.Parsec
+
+import Text.String (parseInt)
+
+data Lrc = Lrc {
+ title :: Maybe String,
+ artist :: Maybe String,
+ album :: Maybe String,
+ by :: Maybe String,
+ metadata :: [(String, String)],
+ lyrics :: [LrcLine]
+}
+
+data LrcLine = LrcLine {
+ time :: Int,
+ line :: String
+} deriving (Eq, Show, Ord)
+
+parseLrc = parse lrcParser
+
+lrcParser :: GenParser Char st Lrc
+lrcParser = do
+ metadata <- many $ try lrcMeta
+ ly <- concat <$> many lrcLine
+ return Lrc {
+ title = lookup "ti" metadata,
+ artist = lookup "ar" metadata,
+ album = lookup "al" metadata,
+ by = lookup "by" metadata,
+ metadata = metadata,
+ lyrics = sort ly
+ }
+
+lrcMeta :: GenParser Char st (String, String)
+lrcMeta = do
+ char '['
+ key <- many $ noneOf ":"
+ char ':'
+ val <- many $ noneOf "]"
+ char ']'
+ eol
+ return (key, val)
+
+lrcLine :: GenParser Char st [LrcLine]
+lrcLine = do
+ times <- many1 lrcTime
+ line <- many $ noneOf "\r\n"
+ optional eol
+ return $ map (\t -> LrcLine {
+ time = t,
+ line = line
+ }) times
+
+lrcTime :: GenParser Char st Int
+lrcTime = do
+ char '['
+ minutes <- readInt
+ char ':'
+ second <- readInt
+ centisec <- option 0 $ char '.' >> readInt
+ char ']'
+ return $ 60 * 100 * minutes + 100 * second + centisec
+ where readInt = read <$> many digit
+
+eol :: GenParser Char st String
+eol = try (string "\n\r")
+ <|> try (string "\r\n")
+ <|> string "\n"
+ <|> string "\r"
+ <?> "end of line"
+
+lrcAddOffset :: Lrc -> Lrc
+lrcAddOffset l = l { lyrics = ly', metadata = meta' }
+ where ly = lyrics l
+ meta = metadata l
+ offset = lookup "offset" meta >>= parseInt
+ ly' = case offset of
+ Just t -> addTime (fromInteger t `div` 10) ly
+ otherwise -> ly
+ meta' = filter notOffset meta
+ notOffset = (/= "offset") . fst
+
+addTime :: Int -> [LrcLine] -> [LrcLine]
+addTime t = map $ \l -> l { time = (t + time l) }
+
+main = getContents >>= \lrcfile -> case parse lrcParser "<stdin>" lrcfile of
+ Left err -> print err >> error "Failed."
+ Right lrc -> mapM_ print $ lyrics $ lrcAddOffset lrc
29 lib/Text/String.hs
@@ -0,0 +1,29 @@
+module Text.String (
+ isSpace,
+ stripl,
+ parseInt,
+ tr,
+ trChar,
+) where
+
+import Data.List (elemIndex)
+
+isSpace :: Char -> Bool
+isSpace = (`elem` " \t\n\r\v")
+
+stripl :: String -> String
+stripl = dropWhile isSpace
+
+parseInt :: String -> Maybe Integer
+parseInt s = case reads s of
+ [(int, "")] -> Just int
+ otherwise -> Nothing
+
+tr :: [Char] -> [Char] -> String -> String
+tr from to = map (trChar from to)
+
+trChar :: [Char] -> [Char] -> Char -> Char
+trChar from to ch = case i of
+ Just i -> to !! i
+ _ -> ch
+ where i = elemIndex ch from
17 nl/nl.hs
@@ -0,0 +1,17 @@
+import Text.Printf (printf)
+
+import Math.Number (nrWidth)
+import Text.Lines (getIndent)
+
+addNumber :: String -> String
+addNumber s = unlines $ zipWith (numberWithIndent (getIndent ls) (nrWidth $ length ls)) [1..] ls
+ where ls = lines s
+
+numberWithIndent :: Int -> Int -> Int -> String -> String
+numberWithIndent indent width nr s
+ | null s = prefix
+ | True = prefix ++ " " ++ drop indent s
+ where fmt = "%" ++ show width ++ "d."
+ prefix = replicate indent ' ' ++ printf fmt nr
+
+main = interact addNumber
36 packagestat/packagestat.hs
@@ -0,0 +1,36 @@
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
+import System.Directory (getDirectoryContents, setCurrentDirectory)
+import System.FilePath ((</>))
+import System.Process (readProcess)
+import Control.Monad
+import Control.Applicative ((<$>))
+
+isArchDependent :: T.Text -> Bool
+isArchDependent = (/= anyarch) . last . (take 2) . (dropWhile (/= archstart)) . T.lines
+ where archstart = T.pack "%ARCH%"
+ anyarch = T.pack "any"
+
+filterArchDependent :: [T.Text] -> [T.Text]
+filterArchDependent = filter isArchDependent
+
+inPacman :: [T.Text] -> T.Text -> Bool
+inPacman pkgs x = x `elem` pkgs
+
+getPackageName :: T.Text -> T.Text
+getPackageName = last . (take 2) . T.lines
+
+topDir = "/var/lib/pacman/local"
+
+getPackagePaths :: IO [FilePath]
+getPackagePaths = liftM (map (topDir </>)) $ (filter ((/= '.') . head)) <$> getDirectoryContents topDir
+
+getPackageDesc :: FilePath -> IO T.Text
+getPackageDesc = TIO.readFile . (++ "/desc")
+
+allPacmanPackages :: IO [T.Text]
+allPacmanPackages = readProcess "pacman" ["-Sl"] "" >>= return . map ((!! 1) . T.split (==' ')) . T.lines . T.pack
+
+main = do
+ pkgs <- allPacmanPackages
+ getPackagePaths >>= mapM getPackageDesc >>= (mapM_ TIO.putStrLn) . (filter $ inPacman pkgs) . (map getPackageName) . (filter isArchDependent)
31 packagestat/packagestat.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+
+import os
+
+topDir = "/var/lib/pacman/local"
+
+def checkPackage(file):
+ for l in open(file):
+ l = l.rstrip()
+ if l == '%NAME%':
+ next = 'name'
+ elif l == '%ARCH%':
+ next = 'arch'
+ else:
+ if next == 'name':
+ name = l
+ elif next == 'arch':
+ return name, l != 'any'
+ next = ''
+
+def main():
+ for name in os.listdir(topDir):
+ if name.startswith('.'):
+ continue
+ file = '%s/%s/desc' % (topDir, name)
+ name, show = checkPackage(file)
+ if show:
+ print(name)
+
+if __name__ == '__main__':
+ main()
28 packagestat/packagestat_lazy.hs
@@ -0,0 +1,28 @@
+import qualified Data.Text.Lazy as T
+import qualified Data.Text.Lazy.IO as TIO
+import System.Directory (getDirectoryContents, setCurrentDirectory)
+import System.IO.Unsafe (unsafeInterleaveIO)
+import Control.Monad
+
+isArchDependent :: T.Text -> Bool
+isArchDependent = (/= anyarch) . last . (take 2) . (dropWhile (/= archstart)) . T.lines
+ where archstart = T.pack "%ARCH%"
+ anyarch = T.pack "any"
+
+filterArchDependent :: [T.Text] -> [T.Text]
+filterArchDependent = filter isArchDependent
+
+getPackageName :: T.Text -> T.Text
+getPackageName = last . (take 2) . T.lines
+
+topDir = "/var/lib/pacman/local"
+
+getPackagePaths :: IO [FilePath]
+getPackagePaths = (filter ((/= '.') . head)) `fmap` getDirectoryContents "."
+
+getPackageDesc :: FilePath -> IO T.Text
+getPackageDesc = unsafeInterleaveIO . TIO.readFile . (++ "/desc")
+
+main = do
+ setCurrentDirectory topDir
+ getPackagePaths >>= mapM getPackageDesc >>= ((mapM TIO.putStrLn) . (map getPackageName) . filterArchDependent)
52 routespeed/routespeed.hs
@@ -0,0 +1,52 @@
+import Control.Applicative ((<$>))
+import Control.Concurrent (threadDelay)
+import Data.List
+import Data.List.Split (endBy)
+import Data.Maybe
+import Data.Time (formatTime, getCurrentTime)
+import Network.Browser
+import Network.HTTP
+import Network.URI
+import System.Locale (defaultTimeLocale)
+import Text.Printf (printf)
+
+import Text.String (parseInt)
+import Math.Number (filesize)
+
+url = "http://192.168.1.1/userRpm/StatusRpm.htm"
+auth = AuthBasic "" "admin" "admin" (fromJust $ parseURI "http://192.168.1.1/")
+
+main = httpreq >>= printSpeed >> main
+
+printSpeed :: [Integer] -> IO ()
+printSpeed a = do
+ threadDelay (1 * 1000 * 1000)
+ printCurrentTime
+ getSpeed a >>= putStrLn . concat . (intersperse ", ") . (map ((++ "/s") . (printf "%8s") . filesize))
+
+getSpeed :: [Integer] -> IO [Integer]
+getSpeed a = do
+ b <- httpreq
+ let c = zipWith (-) b a
+ return c
+
+httpreq :: IO [Integer]
+httpreq = do
+ rsp <- Network.Browser.browse $ do
+ setAllowRedirects True
+ addAuthority auth
+ setOutHandler $ const (return ())
+ request $ getRequest url
+ return $ getBytes $ rspBody $ snd rsp
+
+getBytes :: String -> [Integer]
+getBytes = (take 2) . (map (fromJust.parseInt)) . (endBy ", ") . getDataLine
+
+getDataLine :: String -> String
+getDataLine = (!!1) . (dropWhile (not.(isPrefixOf "var statistList"))) . lines
+
+printCurrentTime :: IO ()
+printCurrentTime = curTime >>= putStr >> putChar ' '
+
+curTime :: IO String
+curTime = formatTime defaultTimeLocale "%H:%M:%S" <$> getCurrentTime
28 sendmail/sendmail.hs
@@ -0,0 +1,28 @@
+import System.IO
+import System.Directory (getHomeDirectory)
+import System.FilePath (joinPath, FilePath)
+import System.Posix.User (getLoginName)
+import System.Time (getClockTime)
+
+-- FIXME Important Notice: This might not be able to handle multibytes
+
+mailbox :: IO FilePath
+mailbox = do
+ home <- getHomeDirectory
+ login <- getLoginName
+ let inbox = case login of
+ "lilydjwg" -> ".Mail/inbox"
+ otherwise -> "cron.letter"
+ return $ joinPath [home, inbox]
+
+processMessage :: String -> IO ()
+processMessage mailbox = withFile mailbox AppendMode (\fd -> do
+ now <- getClockTime
+ hPutStrLn fd $ "From cron@lilyforest " ++ show now
+ hPutStrLn fd "Return-Path: <cron@lilyforest>"
+ hPutStrLn fd "Delivered-To: localhost"
+ hPutStrLn fd $ "Date: " ++ show now
+ getContents >>= hPutStr fd
+ )
+
+main = processMessage =<< mailbox
Please sign in to comment.
Something went wrong with that request. Please try again.