packages feed

scan (empty) → 0.1.0.0

raw patch · 4 files changed

+133/−0 lines, 4 filesdep +basedep +parsecsetup-changed

Dependencies added: base, parsec

Files

+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ doc/LICENSE view
+ scan.cabal view
@@ -0,0 +1,47 @@+cabal-version:      >= 1.6+build-type:         Simple+name:               scan+version:            0.1.0.0+license:            BSD3+license-file:       doc/LICENSE+category:           Development+author:             chr.maeder@web.de+maintainer:         chr.maeder@web.de+copyright:          Christian Maeder 2010+synopsis:           lexical style suggestions for source code+description:+  scan checks the format of your source code. It reports+  (and partly repairs if given the @-@ option):++  non-ascii characters,+  tabs or carriage returns,+  trailing white spaces,+  backslash at line end,+  unconventional comment delimiters,+  too long lines,+  too many consecutive blank lines,+  not a single blank between tokens,+  not a single final newline,+  no spaces after commas,+  spaces between parens and infix operators in sections,+  bad layout (wrt @do@ or @of@).++  It may be useful in conjunction with+  <http://community.haskell.org/~ndm/hlint/>+  to give suggestions on how to improve your source code.++  Repairing is not suited for slices (aka @$(...)@) in template haskell or if+  you like to align your code at @=@ or @->@ in the middle of a line (thus+  wanting multiple blanks). Furthermore layout may be destroyed by inserting+  or deleting blanks, but this is an indication for improving layout anyway.+  Also lines may become too long after inserting blanks.++homepage:           http://projects.haskell.org/style-scanner+stability:          experimental++executable scan+    build-depends:      base < 5, parsec < 3 || >= 3+    hs-source-dirs:     src+    main-is:            scan.hs++    ghc-options: -Wall
+ src/scan.hs view
@@ -0,0 +1,84 @@+{- |+Module      :  scan.hs+Description :  the standalone Haskell style scanner+Copyright   :  (c) Christian Maeder 2010+License     :  BSD++Maintainer  :  chr.maeder@web.de+Stability   :  experimental+Portability :  portable++the Haskell style scanner+-}++module Main where++import Control.Monad++import Data.Char+import Data.List++import System.Environment+import Text.ParserCombinators.Parsec++import Language.Haskell.Scanner++main :: IO ()+main = do+  args <- getArgs+  let (opts, files) = span (== "-") args+      b = null opts+  case files of+    [] -> putStrLn "missing file argument"+    _ -> mapM_ (process $ null opts) $ if b then files else+         take 3 files -- do not spoil more than 3 files++process :: Bool -> String -> IO ()+process b f = do+  str <- readFile f+  let nls = zip [1 ..] $ lines str+      bls = checkBlankLines f 1 nls+  when b $ mapM_ (checkLine f) nls+  when (b && not (isSuffixOf "\n" str))+    $ diag f (length nls) "missing final newline"+  when b $ mapM_ putStrLn bls+  case parse scan f str of+    Right ts -> let x = splitLines ts in+      if b then let o = showScan x in unless (null o) $ putStrLn o else+      let rstr = processScan x in+      if rstr == str then putStrLn $ "no changes in \"" ++ f ++ "\"" else do+      writeFile (f ++ ".bak") str+      writeFile f rstr+      putStrLn $ "updated \"" ++ f ++ "\" (and created .bak)"+    Left err -> fail $ show err++checkBlankLines :: FilePath -> Int -> [(Int, String)] -> [String]+checkBlankLines f c l = case l of+  [] -> if c > 0 then ["trailing blank lines"] else []+  (n, s) : r ->+    if null $ filter (not . isSpace) s then+      if c >= 2 then+        diagStr f n "too many consecutive blank lines"+        : checkBlankLines f (- 100) r+      else checkBlankLines f (c + 1) r+    else checkBlankLines f 0 r++diagStr :: FilePath -> Int -> String -> String+diagStr f n str = "\"" ++ f ++ "\" (line " ++ show n ++ ") " ++ str++diag :: FilePath -> Int -> String -> IO ()+diag f n = putStrLn . diagStr f n++checkLine :: FilePath -> (Int, String) -> IO ()+checkLine f (n, s) = do+  let r = reverse s+      rt = dropWhile isSpace r+      l = length rt+      trailBSlash = takeWhile (== '\\') rt+      badChars = filter (\ c -> not $ isAscii c && isPrint c) s+  when (l > 80) $+    diag f n $ "too long line (" ++ show l ++ " chars)"+  unless (null badChars) $+    diag f n $ "contains undesirable characters: " ++ show badChars+  unless (null trailBSlash) $+    diag f n "back slash at line end (may disturb cpp)"