1
1
mirror of https://github.com/github/semantic.git synced 2024-11-24 17:04:47 +03:00
semantic/app/Main.hs

70 lines
2.9 KiB
Haskell
Raw Normal View History

2015-11-18 01:44:16 +03:00
module Main where
2015-11-27 20:22:05 +03:00
import Categorizable
import Diff
2015-11-27 20:22:05 +03:00
import Interpreter
2015-12-17 00:21:49 +03:00
import qualified Parsers as P
import Syntax
2015-12-03 05:40:34 +03:00
import Range
2015-12-01 19:33:16 +03:00
import Split
2015-11-27 20:41:38 +03:00
import Term
2015-11-27 20:42:00 +03:00
import Unified
import Control.Comonad.Cofree
2015-12-07 22:34:58 +03:00
import qualified Data.ByteString.Char8 as B1
import qualified Data.ByteString.Lazy as B2
2015-12-01 19:15:13 +03:00
import Options.Applicative
import System.Directory
2015-12-03 23:10:49 +03:00
import System.FilePath
2015-12-16 08:39:07 +03:00
import qualified System.IO as IO
2015-12-18 01:19:05 +03:00
data Renderer = Unified | Split | Patch
2015-12-01 19:08:04 +03:00
2015-12-16 07:31:36 +03:00
data Argument = Argument { renderer :: Renderer, output :: Maybe FilePath, sourceA :: FilePath, sourceB :: FilePath }
2015-12-01 19:08:04 +03:00
2015-12-01 19:15:13 +03:00
arguments :: Parser Argument
arguments = Argument
2015-12-01 19:32:52 +03:00
<$> (flag Split Unified (long "unified" <> help "output a unified diff")
<|> flag Split Patch (long "patch" <> help "output a patch(1)-compatible diff")
2015-12-01 19:32:52 +03:00
<|> flag' Split (long "split" <> help "output a split diff"))
<*> (optional $ strOption (long "output" <> short 'o' <> help "output directory for split diffs, defaulting to stdout if unspecified"))
2015-12-16 07:20:33 +03:00
<*> strArgument (metavar "FILE a")
<*> strArgument (metavar "FILE b")
2015-12-01 19:15:13 +03:00
2015-11-18 01:44:16 +03:00
main :: IO ()
2015-11-20 19:36:54 +03:00
main = do
2015-12-01 19:19:40 +03:00
arguments <- execParser opts
2015-12-07 22:23:32 +03:00
let (sourceAPath, sourceBPath) = (sourceA arguments, sourceB arguments)
aContents <- readFile sourceAPath
bContents <- readFile sourceBPath
2015-12-15 22:36:25 +03:00
(aTerm, bTerm) <- let parse = (P.parserForType . takeExtension) sourceAPath in do
2015-12-09 18:36:37 +03:00
aTerm <- parse aContents
bTerm <- parse bContents
return (replaceLeavesWithWordBranches aContents aTerm, replaceLeavesWithWordBranches bContents bTerm)
2015-12-07 22:34:58 +03:00
let diff = interpret comparable aTerm bTerm in
2015-12-16 07:24:04 +03:00
case renderer arguments of
2015-12-07 22:34:58 +03:00
Unified -> do
2015-12-16 08:26:13 +03:00
rendered <- unified diff aContents bContents
B1.putStr rendered
2015-12-07 22:34:58 +03:00
Split -> do
2015-12-16 08:26:13 +03:00
rendered <- split diff aContents bContents
2015-12-16 08:43:13 +03:00
case output arguments of
Just path -> do
isDir <- doesDirectoryExist path
IO.withFile (if isDir then path </> (takeFileName sourceBPath -<.> ".html") else path) IO.WriteMode (write rendered)
2015-12-16 08:43:13 +03:00
Nothing -> B2.putStr rendered
2015-12-07 22:34:58 +03:00
where
2015-12-01 19:19:40 +03:00
opts = info (helper <*> arguments)
(fullDesc <> progDesc "Diff some things" <> header "semantic-diff - diff semantically")
write rendered h = B2.hPut h rendered
2015-11-25 00:51:53 +03:00
replaceLeavesWithWordBranches :: String -> Term String Info -> Term String Info
2015-12-14 20:37:07 +03:00
replaceLeavesWithWordBranches source term = replaceIn source 0 term
where
2015-12-15 01:22:53 +03:00
replaceIn source startIndex (info@(Info range categories) :< syntax) | substring <- substring (offsetRange (negate startIndex) range) source = info :< case syntax of
Leaf _ | ranges <- rangesAndWordsFrom (start range) substring, length ranges > 1 -> Indexed $ makeLeaf categories <$> ranges
Indexed i -> Indexed $ replaceIn substring (start range) <$> i
Fixed f -> Fixed $ replaceIn substring (start range) <$> f
Keyed k -> Keyed $ replaceIn substring (start range) <$> k
_ -> syntax
makeLeaf categories (range, substring) = Info range categories :< Leaf substring