import Char
import List
import IO
+import System.Environment
+import System.Console.GetOpt
+import System.Exit
-- search for definitions of things
main :: IO ()
main = do
- filenames <- getArgs
+ progName <- getProgName
+ args <- getArgs
+ let usageString = "Usage: " ++ progName ++ " [OPTION...] [files...]"
+ let (modes, filenames, errs) = getOpt Permute options args
+ if errs /= [] || elem Help modes || filenames == []
+ then do
+ putStr $ unlines errs
+ putStr $ usageInfo usageString options
+ exitWith (ExitFailure 1)
+ else return ()
+ let mode = getMode modes
filedata <- mapM findthings filenames
- ctagsfile <- openFile "tags" WriteMode
- etagsfile <- openFile "TAGS" WriteMode
- writectagsfile ctagsfile filedata
- writeetagsfile etagsfile filedata
- hClose ctagsfile
- hClose etagsfile
-
+ if mode == BothTags || mode == CTags
+ then do
+ ctagsfile <- openFile "tags" WriteMode
+ writectagsfile ctagsfile filedata
+ hClose ctagsfile
+ else return ()
+ if mode == BothTags || mode == ETags
+ then do
+ etagsfile <- openFile "TAGS" WriteMode
+ writeetagsfile etagsfile filedata
+ hClose etagsfile
+ else return ()
+
+-- | getMode takes a list of modes and extract the mode with the
+-- highest precedence. These are as follows: Both, CTags, ETags
+-- The default case is Both.
+getMode :: [Mode] -> Mode
+getMode [] = BothTags
+getMode [x] = x
+getMode (x:xs) = max x (getMode xs)
+
+
+data Mode = ETags | CTags | BothTags | Help deriving (Ord, Eq, Show)
+
+options :: [OptDescr Mode]
+options = [ Option "c" ["ctags"]
+ (NoArg CTags) "generate CTAGS file (ctags)"
+ , Option "e" ["etags"]
+ (NoArg ETags) "generate ETAGS file (etags)"
+ , Option "b" ["both"]
+ (NoArg BothTags) ("generate both CTAGS and ETAGS")
+ , Option "h" ["help"] (NoArg Help) "This help"
+ ]
+
type FileName = String
type ThingName = String
findthings :: FileName -> IO FileData
findthings filename = do
text <- readFile filename
+ evaluate text -- forces evaluation of text
+ -- too many files were being opened otherwise since
+ -- readFile is lazy
let aslines = lines text
let wordlines = map words aslines
let noslcoms = map stripslcomments wordlines
aslines [0 ..]
let nocoms = stripblockcomments tokens
return $ FileData filename $ findstuff nocoms
+ where evaluate [] = return ()
+ evaluate (c:cs) = c `seq` evaluate cs
-- Create tokens from words, by recording their line number
-- and which token they are through that line