packages feed

imbib-1.0.0: Batch.hs

{-# LANGUAGE RecordWildCards, TupleSections  #-}

import Control.Applicative hiding ((<|>),many)
import Control.Monad
import Control.Monad.Trans
import qualified Data.ByteString.Lazy as BS
import Data.Char
import Data.List
import Data.Maybe
import Data.Tree
import Data.Traversable
import System.FilePath
import System.Process
import Text.BibTeX.Entry as Entry
import Text.BibTeX.Parse
import Data.Function
import System.Environment
import qualified Data.Map as M
import Config

import TypedBibData
import BibDB
import BibAttach
import qualified SuffixTreeCluster as SC
-- import Text.Groom
import MaybeIO

-------------------------------------------------------------------------
-- CheckDuplicates, method 1


pairs (x:xs) = map (x,) xs ++ pairs xs
pairs _ = []

checkDup bib = do
  -- mapM_ putString $  [ groom $ (map findTitle es, shared) | (es,shared) <- common ]
  putString "Possible duplicates:"
  mapM_ putString $ map (show . map findTitle) dups
  saveBib $ uniqDups ++ (bib \\ uniqDups) -- clump together the duplicates
  where
    uniqDups = nub $ concat $ dups
    trueDups es =  filter (\e -> any (not . (areRelated e)) es) es
    dups = [ es | (es0,shared) <- common, 
             let es = trueDups es0, 
             not (null es),
             sum (map length shared) >= threshold (minimum (map (length . project . findTitle) es))]
    threshold x = (9 * x) `div` 10
    -- SC.printTree $ SC.select ("", clusterTree)
    common = M.toList $ SC.commonStrings info
    clusterTree = SC.construct info
    info = [(project $ findTitle e,[e]) | e <- bib]
 
-------------------------------------------------------------------------
-- Auto-renaming of attachments

rename :: (String -> String) -> (String,String) -> MaybeIO (String,String) 
rename new (oldfname,typ) 
    | oldfname == newfname = bail
    | otherwise = do
  oex <- doesFileExist oldfname
  nex <- doesFileExist newfname
  case (oex,nex) of
    (True,False) -> do renameFile oldfname newfname
                       return (newfname,typ)
    (False,_) -> putString ("old does not exist: " ++ oldfname) >> bail
    (_,True) -> putString  ("new already exists: " ++ newfname) >> bail
    -- (_,True) -> do removeFile oldfname >> return (newfname,typ)
                        
  where newfname = new typ
        bail = return (oldfname,typ)

renamer :: Entry -> MaybeIO Entry
renamer t@Entry{..} = do 
  files <- traverse (rename (findAttachName t)) files
  return $ Entry{..}

renameAttachments bib = do 
  bib' <- traverse renamer bib
  saveBib bib'

------------------------------------------------------------------------
-- Check for orphans

check :: (String,String) -> MaybeIO () 
check (fname,typ) = do
  ex <- doesFileExist fname
  if (not ex) then putString $ "missing: " ++ fname else return ()

checker Entry{..} = mapM_ check files

getDirectoryContents' d = map (d </>) <$> getDirectoryContents d

checkAttachments bib = do
  fnames <- getDirectoryContents' "/home/bernardy/Papers"
  let attachments = [ f | e <- bib, (f,t) <- files e] 
      
  mapM_ putString (fnames \\ attachments)

----------------------------------------------------------------------
-- Merge another bibtex file

mergeIn bib fname = do
  bib2 <- uncheckedHarmless $ rightOrDie <$> loadBibliographyFrom fname
  checkDup $ bib2 ++ bib
  return ()


{-
mergeBibs bib1 bib2 = 
    where bibM1 = M.fromList [(project $ findTitle e, e) | e <- bib1]
-}          


-----------------------------------------------------------------------
-- Harvest Downloads

harvest bib = do
  contents <- getDirectoryContents' downloadsDirectory
  let oldFiles = concatMap (map snd . files) bib
      newFiles = contents \\ oldFiles 
      papers = [Entry {kind = "download", 
                       seeAlso = [],
                       authors = [],
                       files = [(fname,guessType fname BS.empty)],
                       otherFields = [("title",fname),("date","2010")]
                      } | fname <- newFiles, takeExtension fname `elem` [".pdf",".ps"]]
  saveBib $ papers ++ bib

------------------------------------------------------------------------
-- Driver

saveBib b = safely "Saving bibfile" $ saveBibliography b


go (command: ~(arg1:_)) = do 
  bib <- uncheckedHarmless $ (rightOrDie <$> loadBibliography)
  case command of
    "check" -> checkAttachments bib
    "rename" -> renameAttachments bib
    "merge" -> mergeIn bib arg1
    "harvest" -> harvest bib
    "dup" -> checkDup bib

dryRun = run True
trueRun = run False

main = do 
  args <- getArgs
  case args of
    ("dry":args) -> dryRun $ go args
    _ -> trueRun $ go args