module Guitar where import Music import Base import Tuning import Tuning.Standard import List ((\\)) import Data.Char (isAlphaNum) import System.Console.ANSI data Guitar = Guitar { tuning :: Tuning, len :: FretNo } deriving (Show) type Displayer a = (Guitar -> Square -> Maybe a) displayGuitar :: Show a => Displayer a -> Guitar -> String displayGuitar func g = unlines $ strings ++ [footer] where neck = [0 .. len g] disp f c (Just a) = c : (take 2 $ (show a \\ "\"\"") ++ " ") ++ [c] disp f c Nothing = c : (if f == 0 then " " else "--") ++ [c] header = concat [ (disp f ' ' . Just . d $ f) ++ " " | f <- neck ] where d f = if f < 10 then (' ' : show f) else show f strings = [ concat [ (disp f (d f) $ func g (s,f)) ++ "|" | f <- neck ] | s <- [1 .. length . tuning $ g] ] where d f = if f == 0 then ' ' else '-' footer = concat [ (marker ' ' $ r f) ++ " " | f <- neck ] where marker c f | f `elem` [3,5,7,9] = disp f c $ Just " *" marker c f | f == 0 = disp f c $ Just "**" marker c f | otherwise = disp f c $ Just "" r f = if f == 0 then 1 else f `rem` 12 displayPitchClass :: Displayer PitchClass displayPitchClass g sq = Just $ pitchClassAt (tuning g) sq displayPress :: Displayer String --displayPress g (c,f) = Just $ if f == 0 then " o" else " O" displayPress g (c,f) = Just $ if f < 10 then (' ' : show f) else show f displayAt :: [Square] -> Displayer a -> Displayer a displayAt ls d = \g sq -> if sq `elem` ls then d g sq else Nothing putGuitar :: Show a => Displayer a -> Guitar -> IO () putGuitar f g = putTerm . displayGuitar f $ g where putTerm (c:cs) = (if isAlphaNum c then yellow c else putChar c) >> putTerm cs putTerm [] = return () yellow c = setSGR [SetColor Foreground Dull Green] >> putChar c >> setSGR [Reset]