cabalQuery (empty) → 0.1.0.0
raw patch · 5 files changed
+251/−0 lines, 5 filesdep +Cabaldep +MissingHdep +basesetup-changed
Dependencies added: Cabal, MissingH, base, cabal-query, containers, pretty
Files
- LICENSE +29/−0
- Setup.hs +2/−0
- cabalQuery.cabal +49/−0
- src/Distribution/Query.hs +60/−0
- tools/Main.hs +111/−0
+ LICENSE view
@@ -0,0 +1,29 @@+Copyright (c) 2015, Rogan Creswick+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++Redistributions of source code must retain the above copyright notice,+this list of conditions and the following disclaimer.++Redistributions in binary form must reproduce the above copyright+notice, this list of conditions and the following disclaimer in the+documentation and/or other materials provided with the distribution.++Neither the name of Rogan Creswick nor the names of his or her+contributors may be used to endorse or promote products derived from+this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ cabalQuery.cabal view
@@ -0,0 +1,49 @@+name: cabalQuery+version: 0.1.0.0+synopsis: A simple tool to query cabal files.+description: Command line access to the cabal package description+ files.+ .+ cabalQuery allows you to query one or more .cabal files+ for fields that may be useful in other contexts, such+ as a build system, where you may need the version number,+ lincense, authors, copyright, etc.. in a programatic way,+ but without access to the Cabal libraries.+license: BSD3+homepage: http://github.com/creswick/cabal-query+Bug-Reports: http://github.com/creswick/cabal-query/issues+license-file: LICENSE+author: Rogan Creswick+maintainer: creswick@gmail.com+copyright: 2015, Rogan Creswick+category: Development+build-type: Simple+-- extra-source-files:+cabal-version: >=1.18++source-repository head+ type: git+ location: git://github.com/creswick/cabal-query.git++library+ exposed-modules: Distribution.Query+ build-depends: base >=4.6 && <4.7,+ Cabal >= 1.22,+ pretty++ hs-source-dirs: src+ default-language: Haskell2010+ ghc-options: -Wall++executable cabalQuery+ default-language: Haskell2010+ hs-source-dirs: tools+ main-is: Main.hs++ build-depends: base >=4.6 && <4.7,+ Cabal >= 1.22,+ cabal-query,+ MissingH,+ containers++ ghc-options: -Wall
+ src/Distribution/Query.hs view
@@ -0,0 +1,60 @@+module Distribution.Query where++import Data.List+import Data.Version (showVersion)+import Distribution.Package+import Distribution.PackageDescription (GenericPackageDescription)+import qualified Distribution.PackageDescription as PD+import Distribution.PackageDescription.Parse+import Distribution.Text+import Distribution.Version++import Text.PrettyPrint (render)++loadDescr :: FilePath -> IO (Either String GenericPackageDescription)+loadDescr cabalFile = do+ content <- readFile cabalFile+ return $ case parsePackageDescription content of+ ParseFailed err -> Left (show err)+ ParseOk _ gpd -> Right gpd++numericVersion :: GenericPackageDescription -> String+numericVersion = showVersion . pkgVersion . PD.package . PD.packageDescription++name :: GenericPackageDescription -> String+name = unPackageName . pkgName . PD.package . PD.packageDescription++license :: GenericPackageDescription -> String+license = render . disp . PD.license . PD.packageDescription++copyright :: GenericPackageDescription -> String+copyright = getField PD.copyright++homepage :: GenericPackageDescription -> String+homepage = getField PD.homepage++pkgUrl :: GenericPackageDescription -> String+pkgUrl = getField PD.pkgUrl++bugReports :: GenericPackageDescription -> String+bugReports = getField PD.bugReports++category :: GenericPackageDescription -> String+category = getField PD.category++buildType :: GenericPackageDescription -> String+buildType = getField PD.buildType++dataDir :: GenericPackageDescription -> String+dataDir = getField PD.dataDir++synopsis :: GenericPackageDescription -> String+synopsis = getField PD.synopsis++description :: GenericPackageDescription -> String+description = getField PD.description++++getField :: Show a => (PD.PackageDescription -> a) -> GenericPackageDescription -> String+getField getter = show . getter . PD.packageDescription
+ tools/Main.hs view
@@ -0,0 +1,111 @@+module Main where++import System.Environment+import System.IO++import Data.Either+import Data.List (isInfixOf, intercalate)+import Data.Map (Map)+import qualified Data.Map as Map+import Data.String.Utils+import Distribution.Query+import Distribution.PackageDescription (GenericPackageDescription)++main :: IO ()+main = do+ args <- getArgs+ eCfg <- parseArgs args+ case eCfg of+ Nothing -> printHelp+ Just cfg | ["--help"] `isInfixOf` (options cfg) -> printHelp+ | otherwise -> do+ let cmds = map cmdFn $ commands cfg+ mapM_ (query cmds) (files cfg)++printHelp :: IO ()+printHelp = do+ putStrLn "Usage: cabalQuery [command] [cabalfile] [options]"+ putStrLn ""+ putStrLn "Commands, files and options can be interspersed."+ putStrLn ""+ putStrLn "Options:"+ putStrLn " --help Prints this help output."+ putStrLn " --version Nothing, yet."+ putStrLn " --numeric-version Nothing, yet."+ putStrLn ""+ putStrLn "Commands:"+ mapM_ (\cmd -> putStrLn (" " ++ (cmdName cmd) ++ "\t\t" ++ (cmdDesc cmd))) commandList++commandMap :: Map String Command+commandMap = Map.fromList $ map (\cmd -> (cmdName cmd, cmd)) commandList++commandList :: [Command]+commandList =+ [ Command "numeric-version"+ "Returns the numeric version in a machine-readable fashion." numericVersion+ , Command "version" "An alias for numeric-version" numericVersion+ , Command "name" "The package name." name+ , Command "license" "The package license." license+ , Command "copyright" "The package copyright." copyright+ , Command "homepage" "The package homepage." homepage+ , Command "pkgUrl" "The package url." pkgUrl+ , Command "bugReports" "The bug reporting url." bugReports+ , Command "synopsis" "The package synopsis." synopsis+ , Command "description" "The package description." description+ , Command "buildType" "The buildType." buildType+ , Command "dataDir" "The dataDir." dataDir+ ]++data Command = Command { cmdName :: String+ -- ^ The name of the command, as written on the command line.+ , cmdDesc :: String+ -- ^ A description of the command, for help output.+ , cmdFn :: GenericPackageDescription -> String+ -- ^ The function over a package description+ -- to get the string value of the thing we're requesting.+ }++data Config = Config { files :: [FilePath]+ -- ^ The cabal file(s) to examine. Defaults to ./*.cabal+ , commands :: [Command]+ -- ^ The things to show, from the cabal file.+ -- e.g., 'numeric-version'+ , options :: [String]+ -- ^ Any options to pass to cabalQuery, starting with "--"+ }++toCommand :: String -> Either String Command+toCommand str = case Map.lookup str commandMap of+ Nothing -> Left str+ Just cmd -> Right cmd++parseArgs :: [String] -> IO (Maybe Config)+parseArgs args = do+ let eCmds = map toCommand $ filter isCommand args+ case (lefts eCmds, rights eCmds) of+ ([] , cmds) ->+ return (Just (Config { files = filter isCabalFile args+ , options = filter isOption args+ , commands = cmds+ }))+ (errs, _) -> do+ hPutStrLn stderr "Invalid commands specified:"+ mapM_ (hPrint stderr) errs+ return Nothing++isCabalFile :: FilePath -> Bool+isCabalFile file = endswith ".cabal" file++isOption :: String -> Bool+isOption str = startswith "--" str++isCommand :: String -> Bool+isCommand str = not (isOption str || isCabalFile str)+++query :: [GenericPackageDescription -> String] -> FilePath -> IO ()+query cmds file = do+ eGpb <- loadDescr file+ case eGpb of+ Left err -> hPrint stderr err+ Right gpb -> putStrLn $ intercalate ", " (map ($ gpb) cmds)