module EmacsServer where import SynCompInterface import Network.Socket hiding (recv,send) import Network.Socket.ByteString import Data.ByteString.Char8 import Control.Monad import Control.Exception type ComputeCandidate = String -> Bool -> {- Int -> -} IO [EmacsDataItem] emacsServer :: ComputeCandidate -> IO () emacsServer computeCand = do sock <- socket AF_INET Stream defaultProtocol setSocketOption sock ReuseAddr 1 bind sock (SockAddrInet 50000 0) listen sock 5 acceptLoop computeCand sock `finally` close sock acceptLoop :: ComputeCandidate -> Socket -> IO () acceptLoop computeCand sock = forever $ do (conn, _) <- accept sock (cursorPos, isSimple) <- getCursorPos_and_isSimple conn print (cursorPos, isSimple) (conn, _) <- accept sock str <- getSource conn print str candidateList <- computeCand str isSimple {- cursorPos -} -- What is cursorPos useful for? print (Prelude.map show candidateList) (conn, _) <- accept sock sendCandidateList conn candidateList close conn str2cursorPos_and_isSimple :: String -> (Int,Bool) str2cursorPos_and_isSimple str = let [s1,s2] = Prelude.words str in (read s1 :: Int, read s2 :: Bool) getCursorPos_and_isSimple :: Socket -> IO (Int, Bool) getCursorPos_and_isSimple conn = do str <- recv conn 64 return (str2cursorPos_and_isSimple (unpack str)) getSource :: Socket -> IO String getSource conn = do str <- recv conn 64 if Data.ByteString.Char8.length str == 0 then return (unpack str) else do aaa <- getSource conn return ((unpack str) ++ aaa) sendCandidateList :: Socket -> [EmacsDataItem] -> IO () sendCandidateList conn xs = do let f [] = "" f ((Candidate x) : xs) = "\n" ++ x ++ f xs f (LexError : xs) = "LexError" ++ f xs f ((ParseError _) : xs) = "ParseError" ++ f xs f (SuccessfullyParsed : xs) = "SuccessfullyParsed" ++ f xs let s = f xs do _ <- send conn (pack s) print s