packages feed

htags (empty) → 1.0

raw patch · 5 files changed

+176/−0 lines, 5 filesdep +basedep +directorydep +filepathsetup-changed

Dependencies added: base, directory, filepath, haskell-src, mtl

Files

+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ TODO view
@@ -0,0 +1,7 @@+TODO: In order of importance
+- Allow it to work with cabal files?
+- Allow it to parse module names for tagging.
+- Give an option to work with search strings (like exuberant C tags)
+- Allow it to work with qualified modules local to a file? (Check out the info
+  on extended syntax)
+- Get a haskell extended parser to work with.
+ htags.cabal view
@@ -0,0 +1,22 @@+Author:         David Sankel+Maintainer:     david@sankelsoftware.com+Name:           htags+Version:        1.0+Cabal-Version:  >= 1.2+License:        BSD3+Category:       Development, Source-tools, Utils+Copyright:      (c) 2008 by David Sankel+Synopsis:       A Haskell98 parsing tags program similar to ctags.+Description:+  htags is a tag file generator to enable extra functionality in editors like+  vim. It expands upon 'hasktags' by using a full Haskell 98 parser and options+  for recursion.+  .+  © 2008 by David Sankel; BSD3 license.+Build-Type:     Simple+extra-source-files: readme.txt TODO++Executable htags+  Build-Depends:  base, filepath, directory, mtl, haskell-src+  Main-Is:        htags.hs+  Hs-Source-Dirs: src
+ readme.txt view
@@ -0,0 +1,1 @@+Test.hs is the latest version and it is working, just like the older Working.hs
+ src/htags.hs view
@@ -0,0 +1,143 @@+{-# OPTIONS_GHC -Wall #-}+module Main(main) where+import Language.Haskell.Syntax+import Language.Haskell.Parser+import Control.Applicative+import System.Environment+import Tag+import GenTags+import Data.Maybe+import System.Console.GetOpt+import Control.Monad.Error+import System.Directory+import System.FilePath+import Control.Arrow( first, second )++--+-- Options datatype+--+data Options = Options { optRecurse :: Bool+                       , optShowHelp :: Bool+                       }+  deriving Show++defaultOptions ::  Options+defaultOptions = Options False False++setRecurse :: Bool -> Options -> Options+setRecurse b o = o { optRecurse = b }++showHelp :: Options -> Options+showHelp o = o { optShowHelp = True }++--+-- Special Yes/No Option+--++ynb :: (Monad m) => String -> m Bool+ynb "yes" = return True+ynb "no" = return False+ynb _ = error "Invalid (yes|no) thing"+++yesNoArg :: (Monad m) => (Bool -> a -> b) -> Bool -> ArgDescr (a -> m b)+yesNoArg z def = OptArg f "yes|no"+  where+    f = maybe (return . z def) (\a opt -> ynb a >>= return . flip z opt)++--+-- Our options list+--++options ::  [OptDescr (Options -> Either String Options)]+options = [ Option "R" ["recurse"] (yesNoArg setRecurse True)+                "Recurse into directories supplied on command line [no]."+          , Option "" ["help"] (NoArg (fmap return showHelp))+                "Print this option summary."+          ]++parseOpts ::  [String] -> -- command line arguments+              Either +                 String -- Error message+                 ( Options   -- Options+                 , [String] ) -- List of files+parseOpts s = errM >> optsM >>= return . flip (,) nonopts+  where (args, nonopts, errors) = getOpt Permute options s+        optsM = foldM (flip ($)) defaultOptions args+        errM = sequence_ (fmap error errors)+ +prgName :: String+prgName = "htags"++outputUsage ::  IO ()+outputUsage = putStr (usageInfo prgName options)++--+-- File Path utilities+--+getLeavesL :: [String] -> IO [String]+getLeavesL = fmap concat . mapM getLeaves++-- Like getDirectoryContents, but returns relative paths+childPaths ::  FilePath -> IO [FilePath]+childPaths s = do contents <- getDirectoryContents s+                  return (fmap (combine s) (filter (flip notElem [".",".."]) contents))+         +getLeaves :: String -> IO [String]+getLeaves s = do isDir <- doesDirectoryExist s+                 if isDir then childPaths s >>= getLeavesL+                          else (pure.pure) s+                      +-- Given a list of directories and files, returns a list of haskell source+-- files optionally recursing.+getHsFiles :: Bool -> [String] -> IO [String]+getHsFiles False files = return (filterHs files)+getHsFiles True files = fmap filterHs (getLeavesL files)++filterHs :: [String] -> [String]+filterHs = filter isHaskellFile++isHaskellFile :: String -> Bool+isHaskellFile = flip elem haskellExtensions . takeExtension++haskellExtensions ::  [String]+haskellExtensions = [".hs", ".lhs"]++run :: Options -> [String] -> IO ()+run os files = do when (optShowHelp os) outputUsage+                  fs <- getHsFiles (optRecurse os) files+                  (errors, tags) <- fmap pullout (mapM yar fs)+                  mapM_ (putStrLn . (++) "Parse Error: " . show) errors+                  writeFile "tags" (tagsToTagfile (concat tags))+  where+    yar ::  String -> IO (Either (SrcLoc, String) [Tag])+    yar = (fmap.fmap.fmap) modToTags parseFile++main ::  IO ()+main = fmap parseOpts getArgs >>= either print (uncurry run)++--+-- Utility Functions+--++parseFile :: String -> IO (Either (SrcLoc, String) HsModule)+parseFile = (fmap.fmap) prToEither pf+  where+    pf :: String -> IO (ParseResult HsModule)+    pf = liftA2 fmap (parseModuleWithMode . ParseMode) readFile+    -- Convert ParseResult to an Either+    prToEither :: ParseResult HsModule -> Either (SrcLoc, String) HsModule+    prToEither s = case s of ParseFailed loc str -> Left (loc,str)+                             ParseOk m           -> Right m++pullout :: [Either a b] -> ([a], [b])+pullout [] = ([], [])+pullout (Left a:z) = first (a:) (pullout z)+pullout (Right a:z) = second (a:) (pullout z)++-- TODO: In order of importance+-- - Allow it to work with cabal files?+-- - Allow it to parse module names for tagging.+-- - Make it work with search strings (like exuberant C tags)+-- - Allow it to work with qualified modules local to a file? (Check out the info on extended syntax)+-- - Allow it to take many command line arguments for names.