autoexporter (empty) → 0.1.0
raw patch · 8 files changed
+199/−0 lines, 8 filesdep +autoexporterdep +basedep +directorysetup-changed
Dependencies added: autoexporter, base, directory, filepath
Files
- CHANGELOG.md +7/−0
- LICENSE.md +23/−0
- README.md +78/−0
- Setup.hs +4/−0
- autoexporter.cabal +39/−0
- executable/Main.hs +4/−0
- library/Autoexporter.hs +43/−0
- stack.yaml +1/−0
+ CHANGELOG.md view
@@ -0,0 +1,7 @@+# Change log++Autoexporter uses [Semantic Versioning][].+The change log is available through the [releases on GitHub][].++[Semantic Versioning]: http://semver.org/spec/v2.0.0.html+[releases on GitHub]: https://github.com/tfausak/autoexporter/releases
+ LICENSE.md view
@@ -0,0 +1,23 @@+[The MIT License (MIT)][]++Copyright (c) 2016 Taylor Fausak++Permission is hereby granted, free of charge, to any person obtaining a copy of+this software and associated documentation files (the "Software"), to deal in+the Software without restriction, including without limitation the rights to+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies+of the Software, and to permit persons to whom the Software is furnished to do+so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.++[The MIT License (MIT)]: https://opensource.org/licenses/MIT
+ README.md view
@@ -0,0 +1,78 @@+# [Autoexporter][]++Autoexporter automatically re-exports Haskell modules.++[![Version badge][]][version]++- [Install](#install)+- [Use](#use)++## Install++1. Install [Stack][].++2. `stack install autoexporter`++## Use++Let's say you have a module `M` that just exports some other modules. It might+look like this:++``` haskell+module M+ ( module M.A+ , module M.B+ ) where++import M.A+import M.B+```++This code is error-prone. If you add a new module, say `M.C`, you have to+remember to come back to this file and re-export it. And this code is tedious+to write. You have to list each module twice. You can do a little better, but+not much.++``` haskell+module M (module X) where+import M.A as X+import M.B as X+```++Now you don't have to write every module twice, but you still have to remember+to re-export everything. And the generated documentation for this module+doesn't include anything about the exported modules.++Autoexporter handles this for you. Instead of either of the above approaches,+simply drop this into the `M` module:++``` haskell+{-# OPTIONS_GHC -F -pgmF autoexporter #-}+```++That will generate code like the first example. A couple caveats:++- Your source files must be rooted in a directory called `library`.++ - I will happily accept patches that lift this restriction. This is good+ enough for my purposes now, but it's pretty bad in general. The hard+ part of this problem is knowing when to stop when converting a file+ path into a module name. For example, how can we reliably convert+ `/home/taylor/HSPackage/Data/Package.hs` into `Data.Package`?++- Absolutely nothing else can be in the source file. Autoexporter will blow+ up if it finds anything else.++- Only immediate children will be re-exported. If you use this in some module+ `M`, it won't pull in `M.A.B`.++- You cannot selectively leave out any modules. You also cannot selectively+ exclude any imports from any of the modules.++ - This could be allowed via `-optF`. I will happily accept patches for+ this as well.++[Autoexporter]: https://github.com/tfausak/autoexporter+[Version badge]: https://www.stackage.org/package/autoexporter/badge/nightly?label=version+[version]: https://www.stackage.org/package/autoexporter+[Stack]: http://haskellstack.org
+ Setup.hs view
@@ -0,0 +1,4 @@+import qualified Distribution.Simple++main :: IO ()+main = Distribution.Simple.defaultMain
+ autoexporter.cabal view
@@ -0,0 +1,39 @@+name: autoexporter+version: 0.1.0+cabal-version: >=1.10+build-type: Simple+license: MIT+license-file: LICENSE.md+maintainer: Taylor Fausak+synopsis: Automatically re-export modules.+description:+ Autoexporter automatically re-exports modules.+category: Utility+extra-source-files:+ CHANGELOG.md+ README.md+ stack.yaml++source-repository head+ type: git+ location: https://github.com/tfausak/autoexporter++library+ exposed-modules:+ Autoexporter+ build-depends:+ base >=4.7 && <4.9,+ directory >=1.2 && <1.3,+ filepath >=1.3 && <1.5+ default-language: Haskell2010+ hs-source-dirs: library+ ghc-options: -Wall++executable autoexporter+ main-is: Main.hs+ build-depends:+ base -any,+ autoexporter -any+ default-language: Haskell2010+ hs-source-dirs: executable+ ghc-options: -Wall
+ executable/Main.hs view
@@ -0,0 +1,4 @@+import qualified Autoexporter++main :: IO ()+main = Autoexporter.main
+ library/Autoexporter.hs view
@@ -0,0 +1,43 @@+module Autoexporter where++import qualified Data.List as List+import qualified System.Directory as Directory+import qualified System.Environment as Environment+import qualified System.FilePath as FilePath++main :: IO ()+main = do+ args <- Environment.getArgs+ case args of+ [name, inputFile, outputFile] -> do+ input <- readFile inputFile+ case input of+ "{-# OPTIONS_GHC -F -pgmF nafta #-}\n" -> do+ let moduleName = makeModuleName name++ let directory = FilePath.dropExtension inputFile+ files <- Directory.getDirectoryContents directory+ let haskellFiles = filter (\ f -> List.isSuffixOf ".hs" f || List.isSuffixOf ".lhs" f) files+ let paths = map (directory FilePath.</>) haskellFiles+ let modules = List.sort (map makeModuleName paths)+ let exports = init (unlines (map (\ x -> " module " ++ x ++ ",") modules))+ let imports = init (unlines (map ("import " ++) modules))++ let output = unlines+ [ unwords ["module", moduleName, "("]+ , exports+ , ") where"+ , ""+ , imports+ ]+ writeFile outputFile output+ _ -> error ("unexpected input: " ++ show input)+ _ -> error ("unexpected arguments: " ++ show args)+ where+ makeModuleName :: FilePath -> String+ makeModuleName name =+ let path = FilePath.dropExtension name+ parts = FilePath.splitDirectories path+ -- TODO: Figure out a better way to get the actual module name.+ rest = tail (dropWhile (/= "library") parts)+ in List.intercalate "." rest
+ stack.yaml view
@@ -0,0 +1,1 @@+resolver: lts-5.3