packages feed

erd (empty) → 0.1.0.0

raw patch · 4 files changed

+205/−0 lines, 4 filesdep +basedep +bytestringdep +containerssetup-changed

Dependencies added: base, bytestring, containers, graphviz, parsec, text

Files

+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ UNLICENSE view
@@ -0,0 +1,24 @@+This is free and unencumbered software released into the public domain.++Anyone is free to copy, modify, publish, use, compile, sell, or+distribute this software, either in source code form or as a compiled+binary, for any purpose, commercial or non-commercial, and by any+means.++In jurisdictions that recognize copyright laws, the author or authors+of this software dedicate any and all copyright interest in the+software to the public domain. We make this dedication for the benefit+of the public at large and to the detriment of our heirs and+successors. We intend this dedication to be an overt act of+relinquishment in perpetuity of all present and future rights to this+software under copyright law.++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 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.++For more information, please refer to <http://unlicense.org/>
+ erd.cabal view
@@ -0,0 +1,74 @@+-- Initial erd.cabal generated by cabal init.  For further documentation, +-- see http://haskell.org/cabal/users-guide/++name:                erd+version:             0.1.0.0+homepage:            https://github.com/BurntSushi/erd+license:             PublicDomain+license-file:        UNLICENSE+author:              Andrew Gallant+maintainer:          jamslam@gmail.com+category:            Database, Development+build-type:          Simple+cabal-version:       >=1.8+synopsis:+  An entity-relationship diagram generator from a plain text description.+description:         +  erd transforms a plain text description of a relational database schema to a +  graphical representation of that schema. It is intended that the graph make+  use of common conventions when depicting entity-relationship diagrams,+  including modeling the cardinality of relationships between entities.+  .+  A quick example that transforms an `er` file to a PDF:+  .+  > $ curl 'https://raw.github.com/BurntSushi/erd/master/examples/simple.er' > simple.er+  > $ cat simple.er+  > # Entities are declared in '[' ... ']'. All attributes after the entity header+  > # up until the end of the file (or the next entity declaration) correspond+  > # to this entity.+  > [Person]+  > *name+  > height+  > weight+  > +birth_location_id+  > +  > [Location]+  > *id+  > city+  > state+  > country+  > +  > # Each relationship must be between exactly two entities, which need not+  > # be distinct. Each entity in the relationship has exactly one of four+  > # possible cardinalities:+  > #+  > # Cardinality    Syntax+  > # 0 or 1         0+  > # exactly 1      1+  > # 0 or more      *+  > # 1 or more      ++  > Person *--1 Location+  > $ erd -i simple.er -o simple.pdf+  .+  The PDF should now contain a graph that looks like this:+  .+  <<http://burntsushi.net/stuff/erd-example-simple.png>>+  .+  See the <https://github.com/BurntSushi/erd#readme README.md> file for more +  examples and instructions on how to write ER files.++source-repository head+  type: git+  location: git://github.com/BurntSushi/erd.git++executable erd+  hs-source-dirs: src+  main-is: Main.hs+  ghc-options: -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind+  build-depends:+    base == 4.6.*+    , graphviz == 2999.16.*+    , text == 0.11.*+    , parsec == 3.1.*+    , containers == 0.5.*+    , bytestring == 0.10.*
+ src/Main.hs view
@@ -0,0 +1,105 @@+{-# LANGUAGE OverloadedStrings #-}+module Main (main) where++import Control.Monad (forM_)+import qualified Data.ByteString as SB+import Data.Maybe (fromMaybe)+import qualified Data.Text.Lazy as L+import System.Exit (exitFailure)+import System.IO (hClose, hPutStrLn, stderr)+import Text.Printf (printf)++import Data.GraphViz+import qualified Data.GraphViz.Attributes.Colors.X11 as C+import qualified Data.GraphViz.Attributes.Complete as A+import qualified Data.GraphViz.Attributes.HTML as H+import qualified Data.GraphViz.Types.Generalised as G+import Data.GraphViz.Types.Monadic++import Config+import ER+import Parse++main :: IO ()+main = do+  conf <- configIO+  er' <- uncurry loadER (cin conf)+  case er' of+    Left err -> do+      hPutStrLn stderr err+      exitFailure+    Right er -> let dotted = dotER er+                    toFile h = SB.hGetContents h >>= SB.hPut (snd $ cout conf)+                    fmt = fromMaybe Pdf (outfmt conf)+                 in graphvizWithHandle Dot dotted fmt toFile+  hClose (snd $ cin conf)+  hClose (snd $ cout conf)++-- | Converts an entire ER-diagram from an ER file into a GraphViz graph.+dotER :: ER -> G.DotGraph L.Text+dotER er = graph' $ do+  graphAttrs (graphTitle $ title er)+  graphAttrs [A.RankDir A.FromLeft]+  nodeAttrs [shape PlainText] -- recommended for HTML labels+  edgeAttrs [ A.Color [A.toWC $ A.toColor C.Gray50] -- easier to read labels+            , A.MinLen 2 -- give some breathing room+            , A.Style [A.SItem A.Dashed []] -- easier to read labels, maybe?+            ]+  forM_ (entities er) $ \e ->+    node (name e) [toLabel (htmlEntity e)]+  forM_ (rels er) $ \r -> do+    let opts = roptions r+    let rlab = A.HtmlLabel . H.Text . htmlFont opts . L.pack . show+    let (l1, l2) = (A.TailLabel $ rlab $ card1 r, A.HeadLabel $ rlab $ card2 r)+    let label = A.Label $ A.HtmlLabel $ H.Text $ withLabelFmt " %s " opts []+    edge (entity1 r) (entity2 r) [label, l1, l2]++-- | Converts a single entity to an HTML label.+htmlEntity :: Entity -> H.Label+htmlEntity e = H.Table H.HTable+                 { H.tableFontAttrs = Just $ optionsTo optToFont $ eoptions e+                 , H.tableAttrs = optionsTo optToHtml (eoptions e)+                 , H.tableRows = rows+                 }+  where rows = headerRow : map htmlAttr (attribs e)+        headerRow = H.Cells [H.LabelCell [] $ H.Text text]+        text = withLabelFmt " [%s]" (hoptions e) $ bold hname+        hname = htmlFont (hoptions e) (name e)+        bold s = [H.Format H.Bold s]++-- | Converts a single attribute to an HTML table row.+htmlAttr :: ER.Attribute -> H.Row+htmlAttr a = H.Cells [cell]+  where cell = H.LabelCell cellAttrs (H.Text $ withLabelFmt " [%s]" opts name)+        name = fkfmt $ pkfmt $ htmlFont opts (field a)+        pkfmt s = if pk a then [H.Format H.Underline s] else s+        fkfmt s = if fk a then [H.Format H.Italics s] else s+        cellAttrs = H.Align H.HLeft : optionsTo optToHtml opts+        opts = aoptions a++-- | Formats HTML text with a label. The format string given should be+-- in `Data.Text.printf` style. (Only font options are used from the options+-- given.)+withLabelFmt :: String -> Options -> H.Text -> H.Text+withLabelFmt fmt opts s =+  case optionsTo optToLabel opts of+    (x:_) -> s ++ htmlFont opts (L.pack $ printf fmt $ L.unpack x)+    _ -> s++-- | Formats an arbitrary string with the options given (using only font+-- attributes).+htmlFont :: Options -> L.Text -> H.Text+htmlFont opts s = [H.Font (optionsTo optToFont opts) [H.Str s]]++-- | Extracts and formats a graph title from the options given.+-- The options should be title options from an ER value.+-- If a title does not exist, an empty list is returned and `graphAttrs attrs`+-- should be a no-op.+graphTitle :: Options -> [A.Attribute]+graphTitle topts =+  let glabel = optionsTo optToLabel topts+  in if null glabel then [] else+       [ A.LabelJust A.JLeft+       , A.LabelLoc A.VTop+       , A.Label $ A.HtmlLabel $ H.Text $ htmlFont topts (head glabel)+       ]