packages feed

posplyu (empty) → 0.1.0

raw patch · 4 files changed

+185/−0 lines, 4 filesdep +X11dep +basedep +directorysetup-changed

Dependencies added: X11, base, directory, process, split, time, timerep, transformers, unix

Files

+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2018 Sergey Alirzaev++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Main.hs view
@@ -0,0 +1,124 @@+module Main where++import Control.Concurrent+import Control.Monad+import Control.Monad.IO.Class+import Control.Monad.Trans.State+import Data.List+import Data.List.Split+import Data.Maybe+import Data.Time.Clock+import Data.Time.LocalTime+import Data.Time.RFC3339+import Graphics.X11+import Graphics.X11.XScreenSaver+import System.Console.GetOpt+import System.Directory+import System.Environment+import System.Posix.Files+import System.Process++pollPeriod = 5000+sleepThreshold = 1800000++data Options = Options+	{ optEdit :: Int+	, optExpect :: Bool+	, optDatabaseFile :: FilePath+	, optList :: Bool+	} deriving Show++defaultOptions    = Options+	{ optEdit = 0+	, optExpect = False+	, optDatabaseFile = ""+	, optList = False+	}++options :: [OptDescr (Options -> Options)]+options =+	[ Option ['e'] ["edit"] (OptArg ((\a o -> o { optEdit = a }) . read . fromMaybe "10") "N") "edit the last N database entries"+	, Option ['x'] ["expect"] (NoArg (\o -> o { optExpect = True })) "print the expected sleepiness time"+	, Option ['d'] ["database-file"] (ReqArg (\a o -> o { optDatabaseFile = a}) "FILE") "use FILE as the sleep data base"+	, Option ['l'] ["list"] (NoArg (\o -> o { optList = True })) "display the database in the current timezone"+	]++parseOpts :: [String] -> IO Options+parseOpts argv =+	case getOpt Permute options argv of+		(o,[],[]  ) -> do+			home <- getAppUserDataDirectory "posplyu"+			return $ foldl (flip id) (defaultOptions { optDatabaseFile = home ++ "/database" }) o+		(_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options))+	where header = "Usage: posplyu"++main :: IO ()+main = do+	setFileCreationMask $ unionFileModes groupModes otherModes+	args <- getArgs+	opts <- parseOpts args+	when (0 < optEdit opts) $ do+		db <- readDB $ optDatabaseFile opts+		let (left, edit) = splitAt ((length db) - optEdit opts) db+		editLocal <- mapM (mapM utcToLocalZonedTime) edit+		edited <- toUser editLocal+		writeDB (optDatabaseFile opts) $ left ++ map (map zonedTimeToUTC) edited+	when (optList opts) $ do+		db <- readDB $ optDatabaseFile opts+		times <- mapM (mapM utcToLocalZonedTime) db+		putStr $ formatUser times+	when (optExpect opts) $ do+		db <- readDB $ optDatabaseFile opts+		let sleepOffset = 60 * 60 * 15+		time <- utcToLocalZonedTime $ addUTCTime sleepOffset $ last $ head $ filter (not . isNap) $ reverse db+		putStrLn $ "Sleepiness expected at " ++ (show time)+	when (not $ or [0 < optEdit opts, optExpect opts, optList opts]) $ do+		let dirname = intercalate "/" $ init $ split (dropDelims $ whenElt (== '/')) $ optDatabaseFile opts+		createDirectoryIfMissing True dirname+		d <- openDisplay ""+		flip evalStateT False $ forever $ pollIdle d $ optDatabaseFile opts+		return ()++ser :: Show a => [[a]] -> String+ser = unlines . map ((intercalate "\t") . (map show))+des :: Read a => String -> [[a]]+des = map ((map read) . (wordsBy (== '\t'))) . lines++readDB :: FilePath -> IO [[UTCTime]]+readDB dbfn = do+	f <- readFile dbfn+	return $ des f++writeDB :: FilePath -> [[UTCTime]] -> IO ()+writeDB dbfn list = writeFile dbfn $ ser list++formatUser :: [[ZonedTime]] -> String+formatUser = unlines . map ((intercalate "\t") . (map formatTimeRFC3339))++toUser :: [[ZonedTime]] -> IO [[ZonedTime]]+toUser list = do+	let tmpfn = "tmp"+	writeFile tmpfn $ formatUser list+	system $ "\"$EDITOR\" " ++ tmpfn+	fromUser <- readFile tmpfn+	removeLink tmpfn+	return $ map ((map (fromJust . parseTimeRFC3339)) . (wordsBy (== '\t'))) $ lines $ fromUser++pollIdle :: Display -> FilePath -> StateT Bool IO ()+pollIdle d dbfn = do+	t <- liftIO $ getXIdleTime d+	s1 <- get+	put $ t > sleepThreshold+	s2 <- get+	liftIO $ when (s1 /= s2) $ (forkIO $ notify dbfn s2) >> return ()+	liftIO $ threadDelay $ pollPeriod * 1000++isNap :: [UTCTime] -> Bool+isNap [a, b] = diffUTCTime b a < 60 * 60 * 3++notify :: FilePath -> Bool -> IO ()+notify dbfn status = do+	t <- getCurrentTime+	let dbline = (show t) ++ if status then "\t" else "\n"+	appendFile dbfn dbline+	putStr dbline
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ posplyu.cabal view
@@ -0,0 +1,39 @@+name:                posplyu+-- semver+version:             0.1.0+synopsis:            Sleep tracker for X11, using XScreenSaver extension and manual input.+description:         posplyu is a sleep tracker for X11, using XScreenSaver extension and manual input, motivated by http://super-memory.com/articles/sleep.htm and designed to facilitate transitioning to the free running sleep regiment while living mostly with a GNU/Linux system handy. The tool allows you to measure and somewhat predict your sleeping cycle. For now it assumes a 24h cycle with one sleep period.+category:            Tools+license:             MIT+license-file:        LICENSE+author:              Sergey Alirzaev+maintainer:          zl29ah@gmail.com+build-type:          Simple+cabal-version:       >= 1.10++Source-repository head+  type:              git+  location:          https://github.com/l29ah/posplyu.git++Source-repository this+  type:              git+  location:          https://github.com/l29ah/posplyu.git+  tag:               0.1.0+++executable posplyu+  main-is:              Main.hs+  -- other-modules:+  -- other-extensions:+  build-depends:        base >= 4.11 && < 4.13,+                        X11 >= 1.9 && < 1.10,+                        transformers >= 0.5.5.0 && < 0.6,+                        time >= 1.8.0.2 && < 1.9,+                        split >= 0.2.3.3 && < 0.3,+                        unix >= 2.7.2.2 && < 2.8,+                        process >= 1.6.3.0 && < 1.7,+                        timerep >= 2.0.0.2 && < 2.1,+                        directory >= 1.3.1.5 && < 1.4+  -- hs-source-dirs:+  default-language:     Haskell2010+  ghc-options:          -fno-warn-tabs