music-preludes 1.6 → 1.6.1
raw patch · 14 files changed
+464/−200 lines, 14 filesdep +containersdep +filepathdep +music-preludesdep ~basenew-component:exe:music2lynew-component:exe:music2midinew-component:exe:music2musicxmlnew-component:exe:music2pdfnew-component:exe:music2pngnew-component:exe:music2svg
Dependencies added: containers, filepath, music-preludes, optparse-applicative, split, tasty, tasty-golden, temporary, unix
Dependency ranges changed: base
Files
- music-preludes.cabal +100/−55
- src/Music/Prelude/Basic.hs +1/−1
- src/Music/Prelude/CmdLine.hs +146/−0
- src/Music/Prelude/Instances.hs +29/−110
- src/Music/Prelude/Piano.hs +10/−11
- src/Music/Prelude/Standard.hs +12/−12
- src/Music/Prelude/StringQuartet.hs +10/−11
- tests/tests.hs +90/−0
- tools/music2ly.hs +8/−0
- tools/music2midi.hs +8/−0
- tools/music2musicxml.hs +8/−0
- tools/music2pdf.hs +14/−0
- tools/music2png.hs +14/−0
- tools/music2svg.hs +14/−0
music-preludes.cabal view
@@ -1,62 +1,107 @@ -name: music-preludes-version: 1.6-cabal-version: >= 1.10-author: Hans Hoglund-maintainer: Hans Hoglund-license: BSD3-license-file: COPYING-synopsis: Some useful preludes for the Music Suite.-category: Music-tested-with: GHC-build-type: Simple+name: music-preludes+version: 1.6.1+author: Hans Hoglund+maintainer: Hans Hoglund+license: BSD3+license-file: COPYING+synopsis: Some useful preludes for the Music Suite.+category: Music+tested-with: GHC+build-type: Simple+cabal-version: >= 1.10 -description: +description: Some useful preludes for the Music Suite.-+ . This library is part of the Music Suite, see <http://music-suite.github.io>. source-repository head- type: git- location: git://github.com/music-suite/music-preludes.git- -library - build-depends: - base >= 4 && < 5,- lens,- vector-space,- vector-space-points,- lilypond == 1.6,- musicxml2 == 1.6,- process,- semigroups,- data-default,- monadplus,- reverse-apply,- music-score == 1.6,- music-pitch == 1.6,- music-dynamics == 1.6,- music-parts == 1.6,- music-pitch-literal == 1.6,- music-dynamics-literal == 1.6- hs-source-dirs: src- default-language: Haskell2010- exposed-modules:- Music.Prelude.Basic- Music.Prelude.Standard- Music.Prelude.Piano- Music.Prelude.StringQuartet- Music.Prelude.Instances+ type: git+ location: git://github.com/music-suite/music-preludes.git --- test-suite properties--- type: exitcode-stdio-1.0--- main-is: properties.hs--- hs-source-dirs: tests--- default-language: Haskell2010--- ghc-options: -w -threaded -rtsopts -with-rtsopts=-N--- build-depends:--- HUnit >= 1.2,--- QuickCheck >= 1.2 && < 1.3,--- test-framework >= 0.6,--- test-framework-th >= 0.2,--- test-framework-quickcheck >= 0.3+library+ build-depends: base >= 4 && < 5,+ lens,+ split,+ unix,+ containers,+ vector-space,+ vector-space-points,+ lilypond == 1.6,+ musicxml2 == 1.6,+ process,+ filepath >= 1.3 && < 2,+ temporary >= 1.1 && < 2,+ optparse-applicative >= 0.8 && < 1,+ semigroups,+ data-default,+ monadplus,+ reverse-apply,+ music-score == 1.6,+ music-pitch == 1.6,+ music-dynamics == 1.6,+ music-parts == 1.6,+ music-pitch-literal == 1.6,+ music-dynamics-literal == 1.6+ exposed-modules: Music.Prelude.Basic+ Music.Prelude.Standard+ Music.Prelude.Piano+ Music.Prelude.StringQuartet+ Music.Prelude.CmdLine+ Music.Prelude.Instances+ hs-source-dirs: src+ default-language: Haskell2010++executable "music2ly"+ build-depends: base,+ music-preludes+ main-is: music2ly.hs+ hs-source-dirs: tools+ default-language: Haskell2010++executable "music2pdf"+ build-depends: base,+ music-preludes+ main-is: music2pdf.hs+ hs-source-dirs: tools+ default-language: Haskell2010++executable "music2png"+ build-depends: base,+ music-preludes+ main-is: music2png.hs+ hs-source-dirs: tools+ default-language: Haskell2010++executable "music2svg"+ build-depends: base,+ music-preludes+ main-is: music2svg.hs+ hs-source-dirs: tools+ default-language: Haskell2010++executable "music2musicxml"+ build-depends: base,+ music-preludes+ main-is: music2musicxml.hs+ hs-source-dirs: tools+ default-language: Haskell2010++executable "music2midi"+ build-depends: base,+ music-preludes+ main-is: music2midi.hs+ hs-source-dirs: tools+ default-language: Haskell2010++test-suite "regression"+ build-depends: base >= 4 && < 5,+ tasty >= 0.8 && < 1,+ tasty-golden >= 2.2 && < 3,+ process+ type: exitcode-stdio-1.0+ main-is: tests.hs+ hs-source-dirs: tests+ default-language: Haskell2010+
src/Music/Prelude/Basic.hs view
@@ -47,8 +47,8 @@ import qualified Music.Pitch import Music.Score hiding (Pitch) +import Control.Lens.Operators hiding ((<.>), (<|), (|>)) import Control.Monad.Plus-import Control.Lens.Operators hiding ((|>), (<|), (<.>)) import Music.Prelude.Instances ()
+ src/Music/Prelude/CmdLine.hs view
@@ -0,0 +1,146 @@++module Music.Prelude.CmdLine (+ converterMain,+ translateFileAndRunLilypond,+ translateFile,+ versionString+) where++import Data.Version (showVersion)+import Data.Monoid+import Options.Applicative+-- import Paths_music_preludes (version)+import Data.Char+import Data.List (intercalate)+import Data.List.Split+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Maybe+import Prelude hiding (readFile, writeFile)+-- import System.Console.GetOpt+import System.Environment+import System.Exit+import System.FilePath+import System.IO+import System.IO.Temp+import qualified System.Posix.Env as PE+import System.Process++-- TODO Can not link due to haskell/cabal#1759+versionString :: String+versionString = "1.6"+-- versionString = showVersion version++data Options = Options {+ prelude :: Maybe String,+ outFile :: Maybe FilePath,+ inFile :: FilePath+ } deriving (Show)++converterOptions :: Parser Options+converterOptions = Options+ <$> (optional $ strOption $ mconcat [long "prelude", metavar "<name>"])+ <*> (optional $ strOption $ mconcat [short 'o', long "output", metavar "<file>"])+ <*> (argument str $ metavar "<input>")++runConverter :: String -> String -> Options -> IO ()+runConverter func ext (Options prelude outFile inFile) =+ translateFile func ext prelude (Just inFile) outFile++converterMain :: String -> String -> String -> IO ()+converterMain func ext pgmName = execParser opts >>= runConverter func ext+ where + opts = info + (helper <*> converterOptions) + (fullDesc <> header (pgmName ++ "-" ++ versionString))+++translateFileAndRunLilypond :: String -> Maybe String -> Maybe FilePath -> IO ()+translateFileAndRunLilypond format preludeName' inFile' = do+ let inFile = fromMaybe "test.music" inFile'+ let preludeName = fromMaybe "basic" preludeName'+ let lyFile = takeBaseName inFile ++ ".ly"++ translateFile "writeLilypond" "ly" (Just preludeName) (Just inFile) (Just lyFile)+ rawSystem "lilypond" ["--" ++ format, "-o", takeBaseName inFile, lyFile]+ runCommand $ "rm -f " ++ takeBaseName inFile ++ "-*.tex " ++ takeBaseName inFile ++ "-*.texi " ++ takeBaseName inFile ++ "-*.count " ++ takeBaseName inFile ++ "-*.eps " ++ takeBaseName inFile ++ "-*.pdf " ++ takeBaseName inFile ++ ".eps"+ return ()++translateFile :: String -> String -> Maybe String -> Maybe FilePath -> Maybe FilePath -> IO ()+translateFile translationFunction outSuffix preludeName' inFile' outFile' = do+ let inFile = fromMaybe "test.music" inFile'+ let preludeName = fromMaybe "basic" preludeName'+ let outFile = fromMaybe (+ takeDirectory inFile ++ "/" + ++ takeBaseName inFile + ++ "." ++ outSuffix) + outFile'++ let prelude = "Music.Prelude." ++ toCamel preludeName+ let scoreType = "Score " ++ toCamel preludeName ++ "Note"+ let main = translationFunction+ score <- readFile inFile+ newScore <- return $ expand templ (Map.fromList [+ ("prelude" , prelude),+ ("main" , main),+ ("scoreType" , scoreType),+ ("score" , score),+ ("outFile" , outFile)+ ])++ withSystemTempDirectory "music-suite." $ \tmpDir -> do+ let tmpFile = tmpDir ++ "/" ++ takeFileName inFile+ putStrLn $ "Converting music..."+ writeFile tmpFile newScore+ withMusicSuiteInScope $ do+ putStrLn $ "Writing '" ++ outFile ++ "'..."+ rawSystem "runhaskell" [tmpFile]++ return ()+ where+ templ = "module Main where { import $(prelude); main = $(main) \"$(outFile)\" ( $(score) :: $(scoreType) ) }"+++type Template = String++-- |+-- Simple templating system.+--+-- >>> expand "me : $(name)" (Map.fromList [("name","Hans")])+-- "me : Hans"+--+expand :: Template -> Map String String -> String+expand t vs = (composed $ fmap (expander vs) $ Map.keys $ vs) t+ where+ expander vs k = replace ("$(" ++ k ++ ")") (fromJust $ Map.lookup k vs)++composed :: [a -> a] -> a -> a+composed = foldr (.) id+++replace :: Eq a => [a] -> [a] -> [a] -> [a]+replace old new = intercalate new . splitOn old++toCamel [] = []+toCamel (x:xs) = toUpper x : xs++-- | Temporarily modfiy an environment variable (POSIX only).+--+-- @+-- withEnv MYVAR (\oldValue -> newValue) $ do+-- ...+-- @+--+withEnv :: String -> (Maybe String -> String) -> IO a -> IO ()+withEnv n f k = do+ x <- PE.getEnv n+ PE.setEnv n (f x) True+ k+ case x of+ Nothing -> PE.unsetEnv n+ Just x2 -> PE.setEnv n x2 True++-- TODO if no music-util, use ""+withMusicSuiteInScope k = do+ packagePath <- readProcess "music-util" ["package-path"] ""+ withEnv "GHC_PACKAGE_PATH" (const packagePath) k
src/Music/Prelude/Instances.hs view
@@ -1,13 +1,12 @@ -{-# LANGUAGE- GeneralizedNewtypeDeriving,- StandaloneDeriving,- MultiParamTypeClasses,- DeriveDataTypeable,- TypeFamilies, - FlexibleInstances,- UndecidableInstances,- ViewPatterns #-} +{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE ViewPatterns #-} ------------------------------------------------------------------------------------ -- |@@ -25,28 +24,28 @@ module Music.Prelude.Instances () where -import Data.Default-import Data.Typeable-import Data.AffineSpace.Point+import Data.AffineSpace.Point+import Data.Default+import Data.Typeable -import Music.Pitch-import Music.Dynamics-import Music.Parts-import Music.Score hiding (Pitch, Interval, Fifths, Note)+import Music.Dynamics+import Music.Parts+import Music.Pitch+import Music.Score hiding (Fifths, Interval, Note, Pitch) -import qualified Music.Score as Score-import qualified Music.Lilypond as Lilypond-import qualified Music.MusicXml.Simple as Xml+import qualified Music.Lilypond as Lilypond+import qualified Music.MusicXml.Simple as Xml+import qualified Music.Score as Score deriving instance Typeable Music.Parts.Part type instance Music.Score.Part BasicPart = BasicPart instance HasPart BasicPart where- getPart = id- modifyPart = id+ getPart = id+ modifyPart = id -- FIXME-instance Delayable Pitch +instance Delayable Pitch instance Stretchable Pitch type instance Score.Pitch Pitch = Pitch @@ -60,109 +59,29 @@ endTie = id instance HasMidi Semitones where- getMidi a = getMidi $ (60 + fromIntegral a :: Integer)+ getMidi a = getMidi $ (fromIntegral a :: Integer) instance HasMidi Pitch where getMidi p = getMidi $ semitones (p .-. c) instance HasMusicXml Pitch where- getMusicXml (realToFrac -> d) = (`Xml.note` d) . snd3 Just . spellPitch- getMusicXmlChord (realToFrac -> d) = (`Xml.chord` (realToFrac d)) . fmap (snd3 Just . spellPitch)+ getMusicXml (realToFrac -> d) = (`Xml.note` d) . snd3 Just . spellPitch 4+ getMusicXmlChord (realToFrac -> d) = (`Xml.chord` (realToFrac d)) . fmap (snd3 Just . spellPitch 4) instance HasLilypond Pitch where- getLilypond d = (^*realToFrac (d*4)) . Lilypond.note . pitchLilypond . Lilypond.Pitch . spellPitch . (.+^ perfect octave)- getLilypondChord d = (^*realToFrac (d*4)) . Lilypond.chord . fmap (pitchLilypond . Lilypond.Pitch . spellPitch . (.+^ perfect octave))+ getLilypond d = (^*realToFrac (d*4)) . Lilypond.note . pitchLilypond . Lilypond.Pitch . spellPitch 5+ getLilypondChord d = (^*realToFrac (d*4)) . Lilypond.chord . fmap (pitchLilypond . Lilypond.Pitch . spellPitch 5) -- TODO move snd3 f (a, b, c) = (a, f b, c) pitchLilypond a = Lilypond.NotePitch a Nothing -spellPitch :: (Enum p, Num a, Num o) => Pitch -> (p, a, o)-spellPitch p = (pitchName, pitchAccidental, octave)+spellPitch :: (Enum p, Num a, Num o) => Octaves -> Pitch -> (p, a, o)+spellPitch referenceOctave p = (pitchName, pitchAccidental, octave) where pitchName = toEnum $ fromEnum $ name p pitchAccidental = fromIntegral $ accidental p- octave = fromIntegral $ (+ 4) $ octaves (p .-. c)--instance Alterable a => Alterable (Score a) where- sharpen = fmap sharpen- flatten = fmap flatten--instance Alterable a => Alterable (ChordT a) where- sharpen = fmap sharpen- flatten = fmap flatten--instance Alterable a => Alterable (DynamicT a) where- sharpen = fmap sharpen- flatten = fmap flatten--instance Alterable a => Alterable (SlideT a) where- sharpen = fmap sharpen- flatten = fmap flatten--instance Alterable a => Alterable (TieT a) where- sharpen = fmap sharpen- flatten = fmap flatten--instance Alterable a => Alterable (HarmonicT a) where- sharpen = fmap sharpen- flatten = fmap flatten--instance Alterable a => Alterable (ArticulationT a) where- sharpen = fmap sharpen- flatten = fmap flatten--instance Alterable a => Alterable (TextT a) where- sharpen = fmap sharpen- flatten = fmap flatten--instance Alterable a => Alterable (TremoloT a) where- sharpen = fmap sharpen- flatten = fmap flatten--instance Alterable a => Alterable (PartT n a) where- sharpen = fmap sharpen- flatten = fmap flatten--instance Augmentable a => Augmentable (Score a) where- augment = fmap augment- diminish = fmap diminish--instance Augmentable a => Augmentable (ChordT a) where- augment = fmap augment- diminish = fmap diminish--instance Augmentable a => Augmentable (DynamicT a) where- augment = fmap augment- diminish = fmap diminish--instance Augmentable a => Augmentable (SlideT a) where- augment = fmap augment- diminish = fmap diminish--instance Augmentable a => Augmentable (TieT a) where- augment = fmap augment- diminish = fmap diminish--instance Augmentable a => Augmentable (HarmonicT a) where- augment = fmap augment- diminish = fmap diminish--instance Augmentable a => Augmentable (ArticulationT a) where- augment = fmap augment- diminish = fmap diminish--instance Augmentable a => Augmentable (TextT a) where- augment = fmap augment- diminish = fmap diminish--instance Augmentable a => Augmentable (TremoloT a) where- augment = fmap augment- diminish = fmap diminish--instance Augmentable a => Augmentable (PartT n a) where- augment = fmap augment- diminish = fmap diminish+ octave = fromIntegral $ (+ referenceOctave) $ octaves (p .-. c) instance HasMidiProgram BasicPart where getMidiChannel _ = 0
src/Music/Prelude/Piano.hs view
@@ -1,7 +1,6 @@ -{-# LANGUAGE- GeneralizedNewtypeDeriving,- DeriveDataTypeable #-} +{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-} ------------------------------------------------------------------------------------ -- |@@ -24,14 +23,14 @@ asScore ) where -import Music.Pitch-import Music.Score hiding (Pitch, Interval, Note)-import Music.Dynamics.Literal --TODO-import Data.Typeable-import Data.AffineSpace.Point-import qualified Music.Score as Score-import qualified Music.Lilypond as Lilypond-import qualified Music.MusicXml.Simple as Xml+import Data.AffineSpace.Point+import Data.Typeable+import Music.Dynamics.Literal+import qualified Music.Lilypond as Lilypond+import qualified Music.MusicXml.Simple as Xml+import Music.Pitch+import Music.Score hiding (Interval, Note, Pitch)+import qualified Music.Score as Score asScore :: Score Note -> Score Note asScore = id
src/Music/Prelude/Standard.hs view
@@ -1,8 +1,7 @@ -{-# LANGUAGE- GeneralizedNewtypeDeriving,- DeriveDataTypeable,- TypeFamilies #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeFamilies #-} ------------------------------------------------------------------------------------ -- |@@ -33,15 +32,16 @@ openAndPlay ) where -import Data.Default-import Data.Typeable+import Data.Default+import Data.Typeable -import Music.Pitch-import Music.Dynamics-import Music.Parts-import Music.Score hiding (Pitch, Interval, Fifths, Note, Part, pitch)+import Music.Dynamics+import Music.Parts+import Music.Pitch+import Music.Score hiding (Fifths, Interval, Note, Part,+ Pitch, pitch) -import Music.Prelude.Instances ()+import Music.Prelude.Instances () asNote :: Note -> Note asNote = id@@ -57,7 +57,7 @@ -- newtype BasicPart = BasicPart { getBasicPart :: Integer } -- deriving (Eq, Ord, Num, Integral, Real, Enum, Typeable)--- +-- -- instance Default BasicPart where def = BasicPart 0 -- instance Show BasicPart where -- show _ = ""
src/Music/Prelude/StringQuartet.hs view
@@ -1,7 +1,6 @@ -{-# LANGUAGE- GeneralizedNewtypeDeriving,- DeriveDataTypeable #-} +{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-} ------------------------------------------------------------------------------------ -- |@@ -23,14 +22,14 @@ asScore ) where -import Music.Pitch-import Music.Score hiding (Pitch, Interval, Note)-import Music.Dynamics.Literal --TODO-import Data.Typeable-import Data.AffineSpace.Point-import qualified Music.Score as Score-import qualified Music.Lilypond as Lilypond-import qualified Music.MusicXml.Simple as Xml+import Data.AffineSpace.Point+import Data.Typeable+import Music.Dynamics.Literal+import qualified Music.Lilypond as Lilypond+import qualified Music.MusicXml.Simple as Xml+import Music.Pitch+import Music.Score hiding (Interval, Note, Pitch)+import qualified Music.Score as Score asScore :: Score Note -> Score Note asScore = id
+ tests/tests.hs view
@@ -0,0 +1,90 @@++module Main where++import Test.Tasty+import Test.Tasty.Golden+import System.Process++main = defaultMain $ testGroup "All tests" [sanity, golden]++testMusicFile name = testGroup name [+ testMusicFileAs "mid" name,+ testMusicFileAs "xml" name,+ testMusicFileAs "ly" name+ ]++converter ext = case ext of+ "mid" -> "music2midi"+ "xml" -> "music2musicxml"+ "ly" -> "music2ly"++testMusicFileAs ext name =+ goldenVsFile + (name ++ "." ++ ext)+ ("tests/golden/" ++ name ++ "." ++ ext)+ ("tests/current/" ++ name ++ "." ++ ext)+ ((system $ converter ext ++" -o tests/current/"++name++"."++ext++" tests/"++name++".music") + >> return ())++{-+ This test will always fail if the test files have been edited.++ If you have edited one or more test files and DEFINITELY intend to make + your changes permanent, please assure that you are in a clean working+ directory (except for your edits), and then run:++ $ make generate+ + You should commit all the resulting files along with your edits.+-}+sanity = testGroup "Sanity checks" [+ testMusicFilesCheckSum,+ testGenratedFilesChecksum+ ]++testMusicFilesCheckSum =+ goldenVsFile+ "Original file checksums"+ "tests/originals_ref.sha"+ "tests/originals_check.sha"+ (system "shasum tests/*.music | shasum > tests/originals_check.sha" >> return ())++testGenratedFilesChecksum =+ goldenVsFile+ "Generated file checksums"+ "tests/generated_ref.sha"+ "tests/generated_check.sha"+ (system "shasum tests/golden/* | shasum > tests/generated_check.sha" >> return ())++golden = testGroup "Regression tests" [+ testMusicFile "articulation_all_accents",+ testMusicFile "articulation_all_separations",+ testMusicFile "articulation_legato",+ testMusicFile "articulation_portato",+ testMusicFile "articulation_staccato",+ testMusicFile "dynamics_constant",+ testMusicFile "melody_chords",+ testMusicFile "meta_annotations",+ testMusicFile "meta_clef1",+ testMusicFile "meta_composer",+ testMusicFile "meta_time_signature",+ testMusicFile "misc_counterpoint",+ testMusicFile "octaves",+ testMusicFile "overlay_chords",+ testMusicFile "overlay_voices",+ testMusicFile "pitch_inv",+ testMusicFile "sharpen",+ testMusicFile "simple_figure",+ testMusicFile "simple_start_later",+ testMusicFile "single_note",+ testMusicFile "special_gliss",+ testMusicFile "special_harmonics",+ testMusicFile "special_text",+ testMusicFile "special_tremolo",+ testMusicFile "stretch_single_note1",+ testMusicFile "stretch_single_note2",+ testMusicFile "stretch_single_note3",+ testMusicFile "times",+ testMusicFile "track_single",+ testMusicFile "voice_single"+ ]
+ tools/music2ly.hs view
@@ -0,0 +1,8 @@++module Main where++import Music.Prelude.CmdLine+import System.Environment++main :: IO ()+main = getProgName >>= converterMain "writeLilypond" "ly"
+ tools/music2midi.hs view
@@ -0,0 +1,8 @@++module Main where++import Music.Prelude.CmdLine+import System.Environment++main :: IO ()+main = getProgName >>= converterMain "writeMidi" "mid"
+ tools/music2musicxml.hs view
@@ -0,0 +1,8 @@++module Main where++import Music.Prelude.CmdLine+import System.Environment++main :: IO ()+main = getProgName >>= converterMain "writeMusicXml" "xml"
+ tools/music2pdf.hs view
@@ -0,0 +1,14 @@++module Main where++import Music.Prelude.CmdLine+import System.Environment++-- TODO+main = do+ args <- getArgs+ main2 args++main2 args = do+ [inFile] <- return args+ translateFileAndRunLilypond "pdf" (Just "basic") (Just inFile)
+ tools/music2png.hs view
@@ -0,0 +1,14 @@++module Main where++import Music.Prelude.CmdLine+import System.Environment++-- TODO+main = do+ args <- getArgs+ main2 args++main2 args = do+ [inFile] <- return args+ translateFileAndRunLilypond "png" (Just "basic") (Just inFile)
+ tools/music2svg.hs view
@@ -0,0 +1,14 @@++module Main where++import Music.Prelude.CmdLine+import System.Environment++-- TODO+main = do+ args <- getArgs+ main2 args++main2 args = do+ [inFile] <- return args+ translateFileAndRunLilypond "svg" (Just "basic") (Just inFile)