packages feed

haskell-awk 1.0 → 1.0.1

raw patch · 6 files changed

+378/−2 lines, 6 filesdep ~basedep ~haskell-src-extsdep ~network

Dependency ranges changed: base, haskell-src-exts, network

Files

haskell-awk.cabal view
@@ -1,5 +1,5 @@ Name:           haskell-awk-Version:        1.0+Version:        1.0.1 Author:         Mario Pastorelli <pastorelli.mario@gmail.com>,  Samuel Gélineau <gelisam@gmail.com> Maintainer:     Mario Pastorelli <pastorelli.mario@gmail.com>,  Samuel Gélineau <gelisam@gmail.com> Synopsis:       Transform text from the command-line using Haskell expressions.@@ -12,8 +12,9 @@ License-File:   LICENSE Build-Type:     Simple Cabal-version:  >=1.10-Extra-Source-Files: src/System/Console/Hawk.hs+Extra-Source-Files: src/System/Console/*.hs                   , src/System/Console/Hawk/*.hs+                  , src/System/Console/Hawk/Config/*.hs                   , README.md                   , tests/System/Console/Hawk/Representable/Test.hs 
+ src/System/Console/Hawk/Config/Base.hs view
@@ -0,0 +1,25 @@+--   Copyright 2013 Mario Pastorelli (pastorelli.mario@gmail.com) Samuel Gélineau (gelisam@gmail.com)+--+--   Licensed under the Apache License, Version 2.0 (the "License");+--   you may not use this file except in compliance with the License.+--   You may obtain a copy of the License at+--+--       http://www.apache.org/licenses/LICENSE-2.0+--+--   Unless required by applicable law or agreed to in writing, software+--   distributed under the License is distributed on an "AS IS" BASIS,+--   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+--   See the License for the specific language governing permissions and+--   limitations under the License.++module System.Console.Hawk.Config.Base where++import Data.ByteString.Char8+++type ExtensionName = String+type QualifiedModule = (String, Maybe String)+type Source = ByteString++defaultModuleName :: String+defaultModuleName = "System.Console.Hawk.CachedPrelude"
+ src/System/Console/Hawk/Config/Cache.hs view
@@ -0,0 +1,91 @@+--   Copyright 2013 Mario Pastorelli (pastorelli.mario@gmail.com) Samuel Gélineau (gelisam@gmail.com)+--+--   Licensed under the Apache License, Version 2.0 (the "License");+--   you may not use this file except in compliance with the License.+--   You may obtain a copy of the License at+--+--       http://www.apache.org/licenses/LICENSE-2.0+--+--   Unless required by applicable law or agreed to in writing, software+--   distributed under the License is distributed on an "AS IS" BASIS,+--   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+--   See the License for the specific language governing permissions and+--   limitations under the License.++{-# LANGUAGE OverloadedStrings #-}+module System.Console.Hawk.Config.Cache+    ( getConfigDir+    , getConfigFile+    , getCacheDir+    , getConfigInfosFile+    , getExtensionsFile+    , getModulesFile+    , getCompiledFile+    , getSourceFile+    , cacheExtensions+    , cacheModules+    , cacheSource+    )+  where++import Control.Applicative ((<$>))++import qualified Data.ByteString.Char8 as B+import qualified Language.Haskell.Interpreter as Interpreter+import System.EasyFile++import System.Console.Hawk.Config.Base+++(<//>) :: IO FilePath -- the left filepath in the IO monad+       -> FilePath -- the right filepath+       -> IO FilePath -- the filepath resulting+lpath <//> rpath = (</> rpath) <$> lpath++getConfigDir :: IO FilePath+getConfigDir = getHomeDirectory <//> ".hawk"++getConfigFile :: IO FilePath+getConfigFile = getConfigDir <//> "prelude.hs"++getCacheDir :: IO FilePath+getCacheDir = getConfigDir <//> "cache"++getConfigInfosFile :: IO FilePath+getConfigInfosFile = getCacheDir <//> "configInfos"++getModulesFile :: IO FilePath+getModulesFile = getCacheDir <//> "modules"++getExtensionsFile :: IO FilePath+getExtensionsFile = getCacheDir <//> "extensions"+++getSourceBasename :: IO String+getSourceBasename = getCacheDir <//> "cached_prelude"++getCompiledFile :: IO String+getCompiledFile = getSourceBasename++getSourceFile :: IO String+getSourceFile = (++ ".hs") <$> getSourceBasename+++cacheExtensions :: FilePath+                -> [ExtensionName]+                -> IO ()+cacheExtensions extensionsFile extensions = +  writeFile extensionsFile $ show extensions'+  where+    extensions' :: [Interpreter.Extension]+    extensions' = map read extensions++cacheModules :: FilePath+             -> [QualifiedModule]+             -> IO ()+cacheModules modulesFile modules = writeFile modulesFile $ show modules++cacheSource :: FilePath+            -> Source+            -> IO ()+cacheSource = B.writeFile
+ src/System/Console/Hawk/Config/Compile.hs view
@@ -0,0 +1,55 @@+--   Copyright 2013 Mario Pastorelli (pastorelli.mario@gmail.com) Samuel Gélineau (gelisam@gmail.com)+--+--   Licensed under the Apache License, Version 2.0 (the "License");+--   you may not use this file except in compliance with the License.+--   You may obtain a copy of the License at+--+--       http://www.apache.org/licenses/LICENSE-2.0+--+--   Unless required by applicable law or agreed to in writing, software+--   distributed under the License is distributed on an "AS IS" BASIS,+--   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+--   See the License for the specific language governing permissions and+--   limitations under the License.++{-# LANGUAGE OverloadedStrings #-}+module System.Console.Hawk.Config.Compile+    ( compile+    )+  where++import Control.Monad (when)++import System.Exit+import System.IO+import System.Process++import System.Console.Hawk.Sandbox (extraGhcArgs)+++-- compile a haskell file+-- TODO: this should return the error instead of print it and exit+compile :: FilePath -- ^ the source file+        -> FilePath -- ^ the output file+        -> FilePath -- ^ the directory used for compiler files+        -> IO ()+compile sourceFile outputFile dir = do+    let basicArgs = [ "--make"+                    , sourceFile+                    , "-i"+                    , "-ilib"+                    , "-fforce-recomp"+                    , "-v0"+                    , "-o",outputFile]+    extraArgs <- extraGhcArgs+    let args = basicArgs ++ extraArgs+    compExitCode <-+            waitForProcess =<< runProcess "ghc"+                                          args+                                          (Just dir)+                                          Nothing+                                          Nothing+                                          Nothing+                                          (Just stderr)+    when (compExitCode /= ExitSuccess) $ do+        exitFailure
+ src/System/Console/Hawk/Config/Extend.hs view
@@ -0,0 +1,115 @@+--   Copyright 2013 Mario Pastorelli (pastorelli.mario@gmail.com) Samuel Gélineau (gelisam@gmail.com)+--+--   Licensed under the Apache License, Version 2.0 (the "License");+--   you may not use this file except in compliance with the License.+--   You may obtain a copy of the License at+--+--       http://www.apache.org/licenses/LICENSE-2.0+--+--   Unless required by applicable law or agreed to in writing, software+--   distributed under the License is distributed on an "AS IS" BASIS,+--   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+--   See the License for the specific language governing permissions and+--   limitations under the License.++{-# LANGUAGE OverloadedStrings #-}+module System.Console.Hawk.Config.Extend+    ( extendModules+    , extendSource+    , getModuleName+    )+  where++import Data.ByteString.Char8 (ByteString)+import qualified Data.ByteString.Char8 as C8+import qualified Data.ByteString.Search as BSS+import Data.Char+import Data.Maybe+import Data.Monoid ((<>))+import Text.Printf++import System.Console.Hawk.Config.Base+++extendModules :: [ExtensionName]+              -> [QualifiedModule]+              -> [QualifiedModule]+extendModules extensions modules = addIfNecessary (shouldAddPrelude extensions modules)+                                                  (unqualified_prelude:)+                                                  modules+  where+    unqualified_prelude = ("Prelude", Nothing)+++-- adjust the prelude to make it loadable from hint.+extendSource :: FilePath+             -> [ExtensionName]+             -> [QualifiedModule]+             -> Source+             -> Source+extendSource configFile extensions modules = addPreludeIfMissing . addModuleIfMissing+  where+    addModuleIfMissing s = addIfNecessary (shouldAddModule s)+                                          (addModule configFile)+                                          s+    addPreludeIfMissing = addIfNecessary (shouldAddPrelude extensions modules)+                                         (addImport "Prelude" configFile)+++addIfNecessary :: Bool -> (a -> a) -> a -> a+addIfNecessary True  f x = f x+addIfNecessary False _ x = x++shouldAddModule :: Source -> Bool+shouldAddModule = (== Nothing) . parseModuleName ++shouldAddPrelude :: [ExtensionName] -> [QualifiedModule] -> Bool+shouldAddPrelude extensions _ | "NoImplicitPrelude" `elem` extensions = False+shouldAddPrelude _ modules    | "Prelude" `elem` map fst modules      = False+shouldAddPrelude _ _          | otherwise                             = True+++-- add a module to a string representing a Haskell source file+addModule :: FilePath -> Source -> Source+addModule configFile source =+    let strippedCode = C8.dropWhile isSpace source+        maybePragma = if "{-#" `C8.isPrefixOf` strippedCode+                        then let (pragma,afterPragma) = BSS.breakAfter "#-}" strippedCode+                             in (Just pragma, afterPragma)+                        else (Nothing,strippedCode)+        line :: Int -> ByteString+        line n = C8.pack $ printf "{-# LINE %d %s #-}" n $ show configFile+        moduleLine = C8.pack $ unwords ["module", defaultModuleName, "where"]+    in case maybePragma of+        (Nothing,c) -> C8.unlines [moduleLine,c]+        (Just pragma,c) -> let n = 1 + C8.length (C8.filter (=='\n') pragma)+                            in C8.unlines [line 1,pragma,moduleLine,line n,c]++-- add an import statement to a string representing a Haskell source file+addImport :: String -> FilePath -> Source -> Source+addImport moduleName configFile source =+    let (premodule,postmodule)   = BSS.breakAfter "module " source+        (prewhere,postwhere)     = BSS.breakAfter " where" postmodule+        (prenewline,postnewline) = BSS.breakAfter "\n" postwhere+        preimports = premodule <> prewhere <> prenewline+        postimports = postnewline+        line :: Int -> ByteString+        line n = C8.pack $ printf "{-# LINE %d %s #-}" n $ show configFile+        importLine = C8.pack $ unwords ["import", moduleName]+        m = 1 + C8.length (C8.filter (=='\n') preimports)+        extraLines = C8.unlines [importLine, line m]+    in preimports <> extraLines <> postimports+++-- get the module name from a file if it exists+parseModuleName :: Source -> Maybe ByteString+parseModuleName bs = case BSS.indices (C8.pack "module") bs of+                       [] -> Nothing+                       (i:_) -> Just+                              . C8.takeWhile (\c -> isAlphaNum c || c == '.')+                              . C8.dropWhile isSpace+                              . C8.drop (i + 6) $ bs++-- same, but crash if there is no module+getModuleName :: Source -> String+getModuleName = C8.unpack . fromJust . parseModuleName
+ src/System/Console/Hawk/Config/Parse.hs view
@@ -0,0 +1,89 @@+--   Copyright 2013 Mario Pastorelli (pastorelli.mario@gmail.com) Samuel Gélineau (gelisam@gmail.com)+--+--   Licensed under the Apache License, Version 2.0 (the "License");+--   you may not use this file except in compliance with the License.+--   You may obtain a copy of the License at+--+--       http://www.apache.org/licenses/LICENSE-2.0+--+--   Unless required by applicable law or agreed to in writing, software+--   distributed under the License is distributed on an "AS IS" BASIS,+--   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+--   See the License for the specific language governing permissions and+--   limitations under the License.++{-# LANGUAGE OverloadedStrings #-}+module System.Console.Hawk.Config.Parse+    ( ExtensionName+    , QualifiedModule+    , parseExtensions+    , parseModules+    , parseSource+    )+  where++import Control.Applicative ((<$>))++import qualified Data.ByteString.Char8 as C8+import Data.Maybe+import Language.Haskell.Exts ( parseFileWithExts )+import Language.Haskell.Exts.Extension ( parseExtension, Extension (..) )+import Language.Haskell.Exts.Parser+    ( getTopPragmas+    , ParseResult (..)+    )+import Language.Haskell.Exts.Syntax+import System.Exit+import Text.Printf++import System.Console.Hawk.Config.Base+++getResult :: FilePath -> ParseResult a -> IO a+getResult _ (ParseOk x) = return x+getResult sourceFile (ParseFailed srcLoc err) = do+    putStrLn $ printf "error parsing file %s:%s: %s" sourceFile (show srcLoc) err+    exitFailure+++parseExtensions :: FilePath -> IO [ExtensionName]+parseExtensions sourceFile = do+    result <- getTopPragmas <$> readFile sourceFile +    listExtensions <$> getResult sourceFile result+  where+    listExtensions :: [ModulePragma] -> [ExtensionName]+    listExtensions = map getName . concat . mapMaybe extensionNames+    +    extensionNames :: ModulePragma -> Maybe [Name]+    extensionNames (LanguagePragma _ names) = Just names+    extensionNames _                        = Nothing+    +    getName :: Name -> ExtensionName+    getName (Ident  s) = s+    getName (Symbol s) = s+++parseModules :: FilePath -> [ExtensionName] -> IO [QualifiedModule]+parseModules sourceFile extensions = do+    result <- parseFileWithExts extensions' sourceFile+    Module _ _ _ _ _ importDeclarations _ <- getResult sourceFile result+    return $ concatMap toHintModules importDeclarations+  where+    extensions' :: [Extension]+    extensions' = map parseExtension extensions+    +    toHintModules :: ImportDecl -> [QualifiedModule]+    toHintModules importDecl =+      case importDecl of+        ImportDecl _ (ModuleName mn) False _ _ Nothing _ -> [(mn,Nothing)]+        ImportDecl _ (ModuleName mn) False _ _ (Just (ModuleName s)) _ ->+                              [(mn,Nothing),(mn,Just s)]+        ImportDecl _ (ModuleName mn) True _ _ Nothing _ -> [(mn,Just mn)]+        ImportDecl _ (ModuleName mn) True _ _ (Just (ModuleName s)) _ ->+                              [(mn,Just s)]+++-- the configuration format is designed to look like a Haskell module,+-- so we just return the whole file.+parseSource :: FilePath -> IO Source+parseSource = C8.readFile