packages feed

phoityne-vscode-0.0.14.0: app/Phoityne/VSCode/IO/Control.hs

{-# LANGUAGE GADTs               #-}
{-# LANGUAGE LambdaCase          #-}
{-# LANGUAGE MultiWayIf          #-}
{-# LANGUAGE BinaryLiterals      #-}
{-# LANGUAGE TemplateHaskell     #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DeriveDataTypeable  #-}

module Phoityne.VSCode.IO.Control where

import Phoityne.VSCode.Constant
import Phoityne.VSCode.Utility
import qualified Phoityne.VSCode.Argument as A
import qualified Phoityne.VSCode.IO.Core as GUI
import qualified Data.ByteString.Lazy as BSL

import System.IO
import Control.Concurrent
import Text.Parsec
import qualified Data.ConfigFile as C
import qualified System.Log.Logger as L

-- |
-- 
run :: A.ArgData
    -> C.ConfigParser
    -> IO Int
run _ _ = do

  hSetBuffering stdin NoBuffering
  hSetEncoding  stdin utf8

  hSetBuffering stdout NoBuffering
  hSetEncoding  stdout utf8

  mvarDat <- newMVar GUI.defaultDebugContextData {GUI.responseHandlerDebugContextData = sendResponse}

  wait mvarDat

  return 1

-- |
--
-- 
wait :: MVar GUI.DebugContextData -> IO ()
wait mvarDat = go BSL.empty
  where
    go buf = BSL.hGet stdin 1 >>= withC buf
    
    withC buf c
      | c == BSL.empty = unexpectedEOF
      | otherwise      = withBuf $ BSL.append buf c
    
    withBuf buf = case parse parser "readContentLength" (lbs2str buf) of
        Left _    -> go buf
        Right len -> BSL.hGet stdin len >>= withCnt buf

    withCnt buf cnt
      | cnt == BSL.empty = unexpectedEOF
      | otherwise        = do
        GUI.handleRequest mvarDat buf cnt
        wait mvarDat

    parser = do
      string "Content-Length: "
      len <- manyTill digit (string _TWO_CRLF)
      return . read $ len

    unexpectedEOF = do
      L.criticalM _LOG_NAME "unexpected EOF on stdin."
      return ()



-- |
--
sendResponse :: BSL.ByteString -> IO ()
sendResponse str = do
  BSL.hPut stdout $ BSL.append "Content-Length: " $ str2lbs $ show (BSL.length str)
  BSL.hPut stdout $ str2lbs _TWO_CRLF
  BSL.hPut stdout str
  hFlush stdout