packages feed

nptools-0.2.2: git-prompt.hs

import System.Console.ANSI
import System.Exit
import HSH
import Control.Monad
import Control.Applicative
import Data.Char
import Data.Maybe

-- tell Zsh to not count the contents for the length
noLength :: String -> String
noLength = ("%{"++) . (++"%}")

color :: Color -> String
color c
  = noLength $ setSGRCode [ SetConsoleIntensity BoldIntensity
                          , SetColor Foreground Dull c]

-- I didn't found how to generate sgr0 from Sys.Console.ANSI
sgr0 :: String
sgr0 = "\SI"

blue, magenta, green, red, noColor :: String
blue     = color Blue
magenta  = color Magenta
green    = color Green
red      = color Red
noColor  = noLength $ setSGRCode [] ++ sgr0

statsInfo :: IO String
statsInfo = do
  gitstat <-  fmap lines . run $ "git status 2> /dev/null"
         -|-  egrep "(# Untracked|# Changes|# Changed but not updated:|# Your branch)"
  let f msg   = listToMaybe . map digits $ egrep msg gitstat
      digits  = reverse . takeWhile isDigit . dropWhile (not . isDigit) . reverse
      ahead   = f "# Your branch is ahead of "
      behind  = f "# Your branch is behind "
  return . concat $
    [green
    ,['!' | "# Changes to be committed:"  `elem` gitstat]
    ,['?' | "# Untracked files:"          `elem` gitstat
         || "# Changed but not updated:"  `elem` gitstat]
    ,maybe "" ((blue++":"++green++"-")++) behind
    ,maybe "" ((blue++":"++green++"+")++) ahead
    ]

isBareRepo :: IO Bool
isBareRepo = readbool =<< run "git config core.bare"
  where readbool "false\n"  = return False
        readbool "true\n"   = return True
        readbool s          = fail ("Unexpected result: " ++ show s)

cond :: a -> a -> Bool -> a
cond x y b = if b then x else y

main :: IO ()
main = do
  ref <- head . lines <$> run "git symbolic-ref HEAD 2> /dev/null"
  when (null ref) exitFailure
  stats <- catch statsInfo . const $
             ((blue++":")++) . cond (green ++ "bare") (red ++ "ERR")
               <$> isBareRepo
  putStrLn . concat $
    ["±"
    ,blue,":",magenta,drop (length "refs/heads/") ref
    ,stats
    ,noColor]