2019-09-26 21:45:14 +00:00
|
|
|
{-# LANGUAGE DuplicateRecordFields, OverloadedLists #-}
|
|
|
|
{-# OPTIONS_GHC -Wall #-}
|
|
|
|
module Rubyhs (main) where
|
|
|
|
|
2019-09-27 16:32:01 +00:00
|
|
|
import Control.Monad.Fail (MonadFail)
|
|
|
|
import Data.Aeson (eitherDecode, encode)
|
2019-09-26 21:45:14 +00:00
|
|
|
import Data.ByteString.Lazy (ByteString)
|
2019-09-27 16:32:01 +00:00
|
|
|
import Data.Foldable (traverse_)
|
|
|
|
import Data.Language.Ruby (Block)
|
|
|
|
import Frelude
|
|
|
|
import System.Process (readProcess)
|
2019-09-26 21:45:14 +00:00
|
|
|
import qualified Data.ByteString.Lazy.Char8 as ByteString
|
2019-10-11 09:08:36 +00:00
|
|
|
import Rubyhs.References (references)
|
2019-10-14 19:46:02 +00:00
|
|
|
import Options.Applicative (Parser)
|
|
|
|
import qualified Options.Applicative as Options
|
|
|
|
import System.IO.Temp (withSystemTempFile)
|
|
|
|
import System.IO (hFlush)
|
2019-09-26 21:45:14 +00:00
|
|
|
|
|
|
|
main :: IO ()
|
2019-10-14 19:46:02 +00:00
|
|
|
main = do
|
|
|
|
Command{targets, printAST} <- getCommand
|
|
|
|
blocks <- decodeInput @Block targets
|
|
|
|
if printAST
|
|
|
|
then traverse_ @[] putEncoded blocks
|
|
|
|
else traverse_ (putEncoded . references) blocks
|
2019-09-26 21:45:14 +00:00
|
|
|
|
2019-10-14 19:46:02 +00:00
|
|
|
-- | Decode from files and mappends the stuff from stdin.
|
|
|
|
decodeInput :: FromJSON a => [FilePath] -> IO [a]
|
|
|
|
decodeInput = \case
|
|
|
|
[] -> ByteString.getContents >>= fmap pure . decode
|
|
|
|
ps -> traverse decodeFile ps
|
|
|
|
|
|
|
|
putEncoded :: ToJSON a => a -> IO ()
|
|
|
|
putEncoded = ByteString.putStrLn . encode
|
|
|
|
|
|
|
|
decodeFile :: FromJSON a => FilePath -> IO a
|
|
|
|
decodeFile = runRubyParseFile >=> decodeFail . ByteString.pack
|
|
|
|
|
|
|
|
decode :: FromJSON a => ByteString -> IO a
|
|
|
|
decode = runRubyParse >=> decodeFail . ByteString.pack
|
|
|
|
|
|
|
|
data Command = Command
|
|
|
|
{ targets :: [FilePath]
|
|
|
|
, printAST :: Bool
|
|
|
|
}
|
|
|
|
|
|
|
|
command :: Parser Command
|
|
|
|
command = Command <$> targets <*> printAST
|
|
|
|
where
|
|
|
|
targets = many (Options.argument Options.str (Options.metavar "TARGET"))
|
|
|
|
printAST = Options.switch
|
|
|
|
$ Options.long "quiet"
|
|
|
|
<> Options.short 'q'
|
|
|
|
<> Options.help "Whether to be quiet"
|
|
|
|
|
|
|
|
getCommand :: IO Command
|
|
|
|
getCommand = Options.execParser opts
|
|
|
|
where
|
|
|
|
opts = Options.info (Options.helper <*> command)
|
|
|
|
( Options.fullDesc
|
|
|
|
<> Options.progDesc "Print a greeting for TARGET"
|
|
|
|
<> Options.header "hello - a test for optparse-applicative" )
|
2019-09-26 21:45:14 +00:00
|
|
|
|
|
|
|
decodeFail :: MonadFail m => FromJSON a => ByteString -> m a
|
|
|
|
decodeFail s = case eitherDecode s of
|
2019-10-11 09:08:36 +00:00
|
|
|
Left err -> Frelude.fail err
|
2019-09-26 21:45:14 +00:00
|
|
|
Right a -> pure a
|
|
|
|
|
2019-10-14 19:46:02 +00:00
|
|
|
runRubyParseFile :: FilePath -> IO String
|
|
|
|
runRubyParseFile p = sh "ruby-parse" ["--emit-json", "--25", p]
|
|
|
|
|
|
|
|
runRubyParse :: ByteString -> IO String
|
|
|
|
runRubyParse s = withSystemTempFile "rubyhs" $ \p h -> do
|
|
|
|
ByteString.hPut h s
|
|
|
|
hFlush h
|
|
|
|
runRubyParseFile p
|
2019-09-26 21:45:14 +00:00
|
|
|
|
|
|
|
sh :: String -> [String] -> IO String
|
|
|
|
sh cmd args = readProcess cmd args mempty
|