module Main where

import Data.List
import Control.Monad
import Control.Monad.Instances
import Control.Arrow
import System (getArgs)
import System.Exit (exitWith)
import System.IO
import System.Process

runPs args = runInteractiveProcess "/bin/ps" args Nothing Nothing

main = do
	(inp,out,err,pid) <- runPs =<< getArgs
	hClose inp
	putStr . unlines . reformat . lines =<< hGetContents out
	hClose out
	hClose err
	exitWith =<< waitForProcess pid

reformat xs = map reformatLine xs
	where
		format = parseHeader (head xs)
		reformatLine =
			tabify . map trim . splitAts format

splitAts [] list = [list]
splitAts (x:xs) list = y : splitAts (map (subtract x) xs) tail
	where (y,tail) = splitAt x list

-- "  PID %CPU   COMMAND" -> [0,5,11]
parseHeader :: [Char] -> [Int]
parseHeader xs = go 0 False xs
	where
		go n True (' ':xs) = (n+1) : go (n+1) False xs
		go n False (' ':xs) = go (n+1) False xs
		go n _ (_:xs) = go (n+1) True xs
		go n _ [] = []

tabify (x:xs) = x ++ "\t" ++ (tabify xs)
tabify [] = []

trim = rtrim . ltrim

ltrim (' ':xs) = ltrim xs
ltrim xs = xs

rtrim (' ':xs)
	| rtrim xs == "" = []
	| otherwise      = ' ' : rtrim xs
rtrim (x:xs) = x : rtrim xs
rtrim [] = []
