From f9dfc24a1f063bc2aafdef31ae118261d3faa72a Mon Sep 17 00:00:00 2001 From: Decio Ferreira Date: Fri, 18 Oct 2024 18:12:38 +0100 Subject: [PATCH] removed FIXME and TODOs #12 #13 --- bin/index.js | 37 ++++++++++++++---- src/Builder/Http.elm | 11 +++--- src/Compiler/Reporting/Error.elm | 4 +- src/Data/IO.elm | 37 +++++++++++------- src/Terminal/Main.elm | 67 ++++++++++++++++++++++++-------- src/Terminal/Publish.elm | 6 +-- src/Utils/Main.elm | 33 +++++++++++++--- 7 files changed, 142 insertions(+), 53 deletions(-) diff --git a/bin/index.js b/bin/index.js index 0113807b6..cbc6ea1c3 100755 --- a/bin/index.js +++ b/bin/index.js @@ -4,6 +4,7 @@ const fs = require("fs"); const child_process = require("child_process"); const readline = require("readline"); const os = require("os"); +const http = require("http"); const https = require("https"); const resolve = require("path").resolve; const AdmZip = require("adm-zip"); @@ -20,6 +21,7 @@ let nextCounter = 0; const ioRefs = {}; const mVars = {}; const lockedFiles = {}; +const processes = {}; const download = function (index, method, url) { const req = https.request(url, { method: method }, (res) => { @@ -137,8 +139,10 @@ const io = { this.send({ index, value: null }); }, - httpFetch: function (index, method, url) { - const req = https.request(url, { method: method }, (res) => { + httpFetch: function (index, method, urlStr, headers) { + const url = new URL(urlStr); + const client = url.protocol == "https:" ? https : http; + const req = client.request(url, { method, headers }, (res) => { let data = []; res.on("data", (chunk) => { data.push(chunk); @@ -300,17 +304,34 @@ const io = { }); }, procWithCreateProcess: function (index, createProcess) { - // FIXME needs review, only trying to implement the minimum for repl functionality const file = tmp.fileSync(); const reader = fs.createReadStream(file.name); - reader.on("data", function (_chunk) { - child_process.spawn(createProcess.cmdspec.cmd, [file.name], { - stdio: "inherit", - }); + reader.on("open", (fd) => { + nextCounter += 1; + processes[nextCounter] = child_process.spawn( + createProcess.cmdspec.cmd, + createProcess.cmdspec.args, + { + stdio: [ + createProcess.stdin, + createProcess.stdout, + createProcess.stderr, + ], + } + ); + + this.send({ index, value: { stdin: file.fd, ph: nextCounter } }); }); - this.send({ index, value: file.fd }); + reader.on("data", (chunk) => { + processes[nextCounter].stdin.end(chunk); + }); + }, + procWaitForProcess: function (index, ph) { + processes[ph].on("exit", (code) => { + this.send({ index, value: code }); + }); }, hClose: function (index, fd) { fs.close(fd); diff --git a/src/Builder/Http.elm b/src/Builder/Http.elm index d5c59b689..c90940b9d 100644 --- a/src/Builder/Http.elm +++ b/src/Builder/Http.elm @@ -89,8 +89,8 @@ urlEncodeVars params = -- FETCH -type Header - = Header +type alias Header = + ( String, String ) get : Manager -> String -> List Header -> (Error -> e) -> (String -> IO (Result e a)) -> IO (Result e a) @@ -144,14 +144,14 @@ fetch methodVerb manager url headers onError onSuccess = "POST" ) url + (addDefaultHeaders headers) ) |> IO.bind onSuccess addDefaultHeaders : List Header -> List Header addDefaultHeaders headers = - -- ( hUserAgent, userAgent ) :: ( hAcceptEncoding, "gzip" ) :: headers - todo "addDefaultHeaders" + ( "User-Agent", userAgent ) :: ( "Accept-Encoding", "gzip" ) :: headers userAgent : String @@ -161,8 +161,7 @@ userAgent = accept : String -> Header accept mime = - -- ( hAccept, mime ) - todo "accept" + ( "Accept", mime ) diff --git a/src/Compiler/Reporting/Error.elm b/src/Compiler/Reporting/Error.elm index 147135ee7..11a922ba0 100644 --- a/src/Compiler/Reporting/Error.elm +++ b/src/Compiler/Reporting/Error.elm @@ -30,6 +30,7 @@ import Compiler.Reporting.Report as Report import Json.Decode as Decode import Json.Encode as Encode import Time +import Utils.Main as Utils @@ -153,8 +154,7 @@ moduleToDoc root { absolutePath, source, error } = toReports (Code.toSource source) error relativePath = - -- FP.makeRelative root absolutePath - String.dropLeft (String.length root) absolutePath + Utils.fpMakeRelative root absolutePath in D.vcat <| List.map (reportToDoc relativePath) (NE.toList reports) diff --git a/src/Data/IO.elm b/src/Data/IO.elm index 7ee083e4f..d342a2ec6 100644 --- a/src/Data/IO.elm +++ b/src/Data/IO.elm @@ -31,7 +31,6 @@ module Data.IO exposing , hIsTerminalDevice , hPutStr , hPutStrLn - , hSetEncoding , ioRefDecoder , ioRefEncoder , liftIO @@ -111,7 +110,7 @@ type Effect | EnvGetArgs | BinaryDecodeFileOrFail String | Read String - | HttpFetch String String + | HttpFetch String String (List ( String, String )) | DirGetAppUserDataDirectory String | DirGetCurrentDirectory | DirGetModificationTime String @@ -130,6 +129,7 @@ type Effect | WithFile String IOMode | StateGet | ProcWithCreateProcess CreateProcess + | ProcWaitForProcess Int | NoOp @@ -157,7 +157,7 @@ type StdStream type ProcessHandle - = ProcessHandle + = ProcessHandle Int procProc : String -> List String -> CreateProcess @@ -171,13 +171,30 @@ procProc cmd args = procWithCreateProcess : CreateProcess -> (Maybe Handle -> Maybe Handle -> Maybe Handle -> ProcessHandle -> IO ExitCode) -> IO ExitCode procWithCreateProcess createProcess f = - make Decode.int (ProcWithCreateProcess createProcess) - |> bind (\fd -> f (Just (Handle fd)) Nothing Nothing ProcessHandle) + make + (Decode.map2 Tuple.pair + (Decode.maybe (Decode.field "stdin" Decode.int)) + (Decode.field "ph" Decode.int) + ) + (ProcWithCreateProcess createProcess) + |> bind + (\( stdinHandle, ph ) -> + f (Maybe.map Handle stdinHandle) Nothing Nothing (ProcessHandle ph) + ) procWaitForProcess : ProcessHandle -> IO ExitCode -procWaitForProcess _ = - pure ExitSuccess +procWaitForProcess (ProcessHandle ph) = + make Decode.int (ProcWaitForProcess ph) + |> fmap + (\exitCode -> + case exitCode of + 0 -> + ExitSuccess + + int -> + ExitFailure int + ) @@ -638,12 +655,6 @@ exitFailure = exitWith (ExitFailure 1) -hSetEncoding : Handle -> TextEncoding -> IO () -hSetEncoding _ _ = - -- TODO review this - pure () - - withFile : String -> IOMode -> (Handle -> IO a) -> IO a withFile path mode callback = make (Decode.map Handle Decode.int) (WithFile path mode) diff --git a/src/Terminal/Main.elm b/src/Terminal/Main.elm index cfc730e29..9047edecc 100644 --- a/src/Terminal/Main.elm +++ b/src/Terminal/Main.elm @@ -274,13 +274,19 @@ effectToCmd index portOut effect = ] } - IO.HttpFetch method url -> + IO.HttpFetch method url headers -> portOut { index = index , value = Encode.object [ ( "fn", Encode.string "httpFetch" ) - , ( "args", Encode.list Encode.string [ method, url ] ) + , ( "args" + , Encode.list identity + [ Encode.string method + , Encode.string url + , Encode.object (List.map (Tuple.mapSecond Encode.string) headers) + ] + ) ] } @@ -493,28 +499,47 @@ effectToCmd index portOut effect = , ( "args", Encode.list Encode.string args ) ] ) - , ( "std_in" + , ( "stdin" , case createProcess.std_in of IO.Inherit -> - Encode.object - [ ( "type", Encode.string "Inherit" ) - ] + Encode.string "inherit" IO.UseHandle (IO.Handle handle) -> - Encode.object - [ ( "type", Encode.string "UseHandle" ) - , ( "handle", Encode.int handle ) - ] + Encode.int handle IO.CreatePipe -> - Encode.object - [ ( "type", Encode.string "CreatePipe" ) - ] + Encode.string "pipe" IO.NoStream -> - Encode.object - [ ( "type", Encode.string "NoStream" ) - ] + Encode.string "ignore" + ) + , ( "stdout" + , case createProcess.std_out of + IO.Inherit -> + Encode.string "inherit" + + IO.UseHandle (IO.Handle handle) -> + Encode.int handle + + IO.CreatePipe -> + Encode.string "pipe" + + IO.NoStream -> + Encode.string "ignore" + ) + , ( "stderr" + , case createProcess.std_err of + IO.Inherit -> + Encode.string "inherit" + + IO.UseHandle (IO.Handle handle) -> + Encode.int handle + + IO.CreatePipe -> + Encode.string "pipe" + + IO.NoStream -> + Encode.string "ignore" ) ] ] @@ -522,6 +547,16 @@ effectToCmd index portOut effect = ] } + IO.ProcWaitForProcess ph -> + portOut + { index = index + , value = + Encode.object + [ ( "fn", Encode.string "procWaitForProcess" ) + , ( "args", Encode.list Encode.int [ ph ] ) + ] + } + IO.NoOp -> Task.succeed Encode.null |> Task.perform (Msg index) diff --git a/src/Terminal/Publish.elm b/src/Terminal/Publish.elm index c80aa169b..7ac09f5a9 100644 --- a/src/Terminal/Publish.elm +++ b/src/Terminal/Publish.elm @@ -630,7 +630,7 @@ reportCustomCheck waiting success failure work = message ++ String.repeat (String.length waiting - String.length message) " " in Task.eio identity - (putFlush (D.plus (D.fromChars " ") (D.plus waitingMark (D.fromChars waiting))) + (putFlush (D.append (D.fromChars " ") waitingMark |> D.plus (D.fromChars waiting)) |> IO.bind (\_ -> work @@ -639,10 +639,10 @@ reportCustomCheck waiting success failure work = putFlush (case result of Ok a -> - D.append (D.fromChars "\u{000D} ") (D.plus goodMark (D.fromChars (padded (success a) ++ "\n"))) + D.append (D.fromChars "\u{000D} ") goodMark |> D.plus (D.fromChars (padded (success a) ++ "\n")) Err _ -> - D.append (D.fromChars "\u{000D} ") (D.plus badMark (D.fromChars (padded failure ++ "\n\n"))) + D.append (D.fromChars "\u{000D} ") badMark |> D.plus (D.fromChars (padded failure ++ "\n\n")) ) |> IO.fmap (\_ -> result) ) diff --git a/src/Utils/Main.elm b/src/Utils/Main.elm index 480698df3..b2a99d04a 100644 --- a/src/Utils/Main.elm +++ b/src/Utils/Main.elm @@ -600,8 +600,27 @@ zipWithM f xs ys = listGroupBy : (a -> a -> Bool) -> List a -> List (List a) -listGroupBy _ _ = - todo "listGroupBy" +listGroupBy p list = + case list of + [] -> + [] + + x :: xs -> + xs + |> List.foldl + (\current ( previous, ys, acc ) -> + if p previous current then + ( current, current :: ys, acc ) + + else + ( current, [ current ], ys :: acc ) + ) + ( x, [ x ], [] ) + |> (\( _, ys, acc ) -> + ys :: acc + ) + |> List.map List.reverse + |> List.reverse listMaximum : (a -> a -> Order) -> List a -> a @@ -741,9 +760,13 @@ fpJoinPath paths = String.join "/" paths -fpMakeRelative : String -> String -> String -fpMakeRelative _ = - todo "fpMakeRelative" +fpMakeRelative : FilePath -> FilePath -> FilePath +fpMakeRelative root path = + if String.startsWith path root then + String.dropLeft (String.length root) path + + else + path fpAddTrailingPathSeparator : FilePath -> FilePath