packages feed

historian-0.0.1: historian.hs

import qualified Data.Map as M
import Data.List (group, isPrefixOf, sort)
import Text.Regex
import Text.Regex.Posix
import Data.Char (isSpace)
import Control.Arrow (second)
import Control.Applicative ((<$>), liftA2)
import System.Cmd (rawSystem)
import System.FilePath ((</>))
import System.Directory (removeFile)
import System.Environment (getArgs, getEnv)

type PatternDB = M.Map String Pattern
type Pattern = String

extractPatterns :: String -> PatternDB
extractPatterns =   --M.map makeRegex
                    M.fromListWith (\x y -> x ++ '|':y) .
                    map (second (\x -> "(" ++ x ++ ")") . splitCmd . tail) .
                    filter (">" `isPrefixOf`) .
                    lines

splitCmd :: String -> (String, String)
splitCmd = second (dropWhile isSpace) . break isSpace . dropWhile isSpace

extractInteresting :: PatternDB -> [String] -> [String]
extractInteresting db = filter (not . liftA2 (||) (`inDB` db) ("#" `isPrefixOf`))

inDB :: String -> PatternDB -> Bool
cmd `inDB` db = let (prog, args) = splitCmd cmd in
                    case M.lookup prog db of
                        Just pat -> args =~ pat
                        Nothing -> False

main = do
        homeDir <- catch (getEnv "HOME") (const . return $ ".")
        editor <- catch (getEnv "EDITOR") (const . return $ "nano")
        args <- getArgs
        let fn = case args of
                    [] -> homeDir </> "interesting_history"
                    [x] -> x

        let histfile = homeDir </> ".bash_history"
        boring <- extractPatterns <$> readFile fn
        history <- readFile $ histfile
        let interesting = map head . group . sort . extractInteresting boring . lines $ history
        boring `seq` (appendFile fn . unlines . map ("> " ++) $ interesting)
        interesting `seq` writeFile histfile "# history has been rewritten\n"
        rawSystem editor [fn]