yi-0.5.2: Yi/Tag.hs
-- | A module for CTags integration
module Yi.Tag
(
lookupTag,
importTagTable,
hintTags,
completeTag,
Tag,
TagTable(..)
)
where
{- Standard Library Module Imports -}
import Data.Maybe (mapMaybe)
import Data.List (isPrefixOf)
import System.FilePath (takeFileName, takeDirectory, FilePath, (</>))
import System.FriendlyPath
import Data.Map (Map, fromList, lookup, keys)
import qualified Data.Trie as Trie
type Tag = String
data TagTable = TagTable { tagFileName :: FilePath
-- ^ local name of the tag file
-- TODO: reload if this file is changed
, tagBaseDir :: FilePath
-- ^ path to the tag file directory
-- tags are relative to this path
, tagFileMap :: Map Tag (FilePath, Int)
-- ^ map from tags to files
, tagTrie :: Trie.Trie
-- ^ trie to speed up tag hinting
}
-- | Find the location of a tag using the tag table.
-- Returns a full path and line number
lookupTag :: Tag -> TagTable -> Maybe (FilePath, Int)
lookupTag tag tagTable = do
(file, line) <- Data.Map.lookup tag $ tagFileMap tagTable
return $ (tagBaseDir tagTable </> file, line)
-- | Super simple parsing CTag format 1 parsing algorithm
-- TODO: support search patterns in addition to lineno
readCTags :: String -> Map Tag (FilePath, Int)
readCTags =
fromList . mapMaybe (parseTagLine . words) . lines
where parseTagLine [tag, tagfile, lineno] =
-- remove ctag control lines
if "!_TAG_" `isPrefixOf` tag then Nothing
else Just (tag, (tagfile, read lineno))
parseTagLine _ = Nothing
-- | Read in a tag file from the system
importTagTable :: FilePath -> IO TagTable
importTagTable filename = do
friendlyName <- expandTilda filename
tagStr <- readFile friendlyName
let ctags = readCTags tagStr
return $ TagTable { tagFileName = takeFileName filename,
tagBaseDir = takeDirectory filename,
tagFileMap = ctags,
tagTrie = Trie.fromList $ keys ctags
}
-- | Gives all the possible expanded tags that could match a given @prefix@
hintTags :: TagTable -> String -> [String]
hintTags tags prefix = map (prefix ++) $ Trie.possibleSuffixes prefix $ tagTrie tags
-- | Extends the string to the longest certain length
completeTag :: TagTable -> String -> String
completeTag tags prefix = prefix ++ (Trie.certainSuffix prefix $ tagTrie tags)