diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
new file mode 100644
index 0000000..3dcd6c5
--- /dev/null
+++ b/.github/workflows/dotnet.yml
@@ -0,0 +1,26 @@
+# This workflow will build a .NET project
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
+
+name: .NET
+
+on:
+ push:
+ branches: [ "dev" ]
+ pull_request:
+ branches: [ "dev" ]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: 7.0.x
+ - name: Build
+ run: dotnet fsi build.fsx -- -- build
+ - name: Test
+ run: dotnet fsi build.fsx -- -- test
diff --git a/.travis.yml b/.travis.yml
index d534405..d42c1ba 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,16 +1,13 @@
language: csharp
mono: latest
-dotnet: 2.1.300
+dotnet: 7.0.202
env: VER=$(if [[ "${TRAVIS_TAG:0:1}" == "v" ]]; then echo ${TRAVIS_TAG:1}.${TRAVIS_BUILD_NUMBER}; else echo 1.0.0.${TRAVIS_BUILD_NUMBER}; fi;)
-install:
- - dotnet restore build.proj
script:
- - export FrameworkPathOverride=$(dirname $(which mono))/../lib/mono/4.5-api/
- - dotnet fake run build.fsx -- build test -ll Diag
+ - dotnet fsi build.fsx -- -- build test -ll Diag
deploy:
- provider: script
- script: dotnet fake run build.fsx -- pack push -ll Diag
+ script: dotnet fsi build.fsx -- -- pack push -ll Diag
skip_cleanup: true
on:
tags: true
- condition: "${TRAVIS_TAG:0:1} = v"
+ condition: "${TRAVIS_TAG:0:1} = v"
\ No newline at end of file
diff --git a/build.cmd b/build.cmd
index 3986414..4d1719c 100644
--- a/build.cmd
+++ b/build.cmd
@@ -1,3 +1,2 @@
@echo off
-dotnet restore build.proj
-dotnet fake run build.fsx -- build
\ No newline at end of file
+dotnet fsi build.fsx -- -- build
\ No newline at end of file
diff --git a/build.fsx b/build.fsx
index 0e27744..5e7b77a 100644
--- a/build.fsx
+++ b/build.fsx
@@ -1,14 +1,9 @@
-#r "paket:
- nuget Xake ~> 1.1 prerelease //"
-
-#if !FAKE
-#load ".fake/build.fsx/intellisense.fsx"
-#endif
+#r "nuget: Xake, 2.0.0"
open Xake
open Xake.Tasks
-let frameworks = ["netstandard2.0"; "net46"]
+let frameworks = ["netstandard2.0" (*; "net46" *)]
let libtargets =
[ for t in frameworks do
for e in ["dll"; "xml"]
@@ -33,23 +28,19 @@ let getVersion () = recipe {
let makePackageName = sprintf "Xake.%s.nupkg"
-let dotnet arglist = recipe {
- do! shell {
+let dotnet arglist =
+ shell {
cmd "dotnet"
args arglist
failonerror
- } |> Recipe.Ignore
-}
+ } |> Ignore
do xakeScript {
filelog "build.log" Verbosity.Diag
// consolelog Verbosity.Normal
rules [
- "main" => recipe {
- do! need ["build"]
- do! need ["test"]
- }
+ "main" <<< ["build"; "test"]
"build" <== libtargets
"clean" => rm {dir "out"}
@@ -59,37 +50,34 @@ do xakeScript {
let! where =
getVar("FILTER")
- |> Recipe.map (function |Some clause -> ["--filter"; sprintf "Name~\"%s\"" clause] | None -> [])
+ |> map (function |Some clause -> ["--filter"; $"Name~\"{clause}\""] | None -> [])
// in case of travis only run tests for standard runtime, eventually will add more
- let! limitFwk = getEnv("TRAVIS") |> Recipe.map (function | Some _ -> ["-f:netcoreapp2.0"] | _ -> [])
-
+ let! limitFwk = getEnv("TRAVIS") |> map (function | Some _ -> ["-f:netcoreapp2.0"] | _ -> [])
do! dotnet <| ["test"; "src/tests"; "-c"; "Release"] @ where @ limitFwk
}
libtargets *..> recipe {
- let! allFiles
- = getFiles <| fileset {
- basedir "src/core"
- includes "Xake.fsproj"
- includes "**/*.fs"
- }
+ let! allFiles = getFiles <| fileset {
+ basedir "src/core"
+ includes "Xake.fsproj"
+ includes "**/*.fs"
+ }
do! needFiles allFiles
let! version = getVersion()
for framework in frameworks do
- do! dotnet
- [
- "build"
- "src/core"
- "/p:Version=" + version
- "--configuration"; "Release"
- "--framework"; framework
- "--output"; "../../out/" + framework
- "/p:DocumentationFile=Xake.xml"
- ]
+ do! dotnet [
+ "build"
+ "src/core"
+ "/p:Version=" + version
+ "--configuration"; "Release"
+ "--framework"; framework
+ "--output"; "./out/" + framework
+ "/p:DocumentationFile=Xake.xml"
+ ]
}
]
@@ -102,14 +90,13 @@ do xakeScript {
"out/Xake.(ver:*).nupkg" ..> recipe {
let! ver = getRuleMatch("ver")
- do! dotnet
- [
- "pack"; "src/core"
- "-c"; "Release"
- "/p:Version=" + ver
- "--output"; "../../out/"
- "/p:DocumentationFile=Xake.xml"
- ]
+ do! dotnet [
+ "pack"; "src/core"
+ "-c"; "Release"
+ $"/p:Version={ver}"
+ "--output"; "out/"
+ "/p:DocumentationFile=Xake.xml"
+ ]
}
// push need pack to be explicitly called in advance
@@ -117,13 +104,12 @@ do xakeScript {
let! version = getVersion()
let! nuget_key = getEnv("NUGET_KEY")
- do! dotnet
- [
- "nuget"; "push"
- "out" > makePackageName version
- "--source"; "https://www.nuget.org/api/v2/package"
- "--api-key"; nuget_key |> Option.defaultValue ""
- ]
+ do! dotnet [
+ "nuget"; "push"
+ "out" > makePackageName version
+ "--source"; "https://www.nuget.org/api/v2/package"
+ "--api-key"; nuget_key |> Option.defaultValue ""
+ ]
}
]
}
diff --git a/build.fsx.lock b/build.fsx.lock
deleted file mode 100644
index 5497458..0000000
--- a/build.fsx.lock
+++ /dev/null
@@ -1,7 +0,0 @@
-STORAGE: NONE
-RESTRICTION: == netstandard2.0
-NUGET
- remote: https://api.nuget.org/v3/index.json
- FSharp.Core (4.3.4)
- Xake (1.1.0.413-alpha)
- FSharp.Core (>= 4.3.4)
diff --git a/build.proj b/build.proj
deleted file mode 100644
index 5483b72..0000000
--- a/build.proj
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
- netstandard2.0
-
-
-
-
-
-
diff --git a/build.sh b/build.sh
index f19bb05..359a510 100755
--- a/build.sh
+++ b/build.sh
@@ -1,3 +1,2 @@
#!/bin/bash
-dotnet restore build.proj
-dotnet fake run build.fsx -- build
\ No newline at end of file
+dotnet fsi build.fsx -- --
\ No newline at end of file
diff --git a/docs/overview.md b/docs/overview.md
index 9abff59..339cdce 100644
--- a/docs/overview.md
+++ b/docs/overview.md
@@ -37,7 +37,7 @@ Xake script is just an F# script with some flavors.
The most simple, but structured script looks as follows:
```fsharp
-#r @".tools/Xake.Core.dll" // (1)
+#r "nuget: Xake, 1.1.4.427-beta" // (1)
open Xake // (2)
@@ -154,6 +154,7 @@ There're several forms of rules including:
* `rule ( => )` - creates a phony rule (the rule that does not create a file)
* `rule ( <== [targets])` - creates a phony rule which demands specified targets
+* `rule ( <<< [targets])` - the same as above, but the targets are requested one by one (non-parallel excution)
* `rule ( ..> )` - rule for single file or group of files matching the specified wildcards pattern. The file and an optional matching groups can be accessed via getTargetFile and getRuleMatch methods
* `rule ( ..?> )` - allows to use function instead of file name or wildcards
diff --git a/docs/todo.md b/docs/todo.md
index 68def05..f1cb4f5 100644
--- a/docs/todo.md
+++ b/docs/todo.md
@@ -2,13 +2,10 @@
* change the first page to a tutorial with script and usage examples
- * switch development to mono under windows
* idea: xake script as a task. Override/inherit variables. How to change variable on the fly is the original question. (we have got it out of the box, need more info)
- * accept filemasks in 'need' parameters (WHY I added it here?, the use case is very unclear)
* detect changes in build script (internal changes), e.g. new target added that was not in .xake database
* dependencies tracking mode: automatically rebuild when dependency is changed, execute triggers allowing to start/stop the processes which lock/hold artifacts
* in-memory artifact (string or stream). Say in Gulp file is processed in-memory
- * can the rules be abstract over artifacts
### Refactorings
@@ -25,10 +22,12 @@
* `rule "Viewer" -> fun folder -> action {need [folder <\\> "bin" <\\> folder <.> "exe"]...}`
* Filelist is not handy as it requires to cast all the time
* FileInfo is not good for the same reason: poorly composable and does not cover Directory well
-* wildcards phony actions
## Done (top is recent)
+ * wildcards phony actions
+ * support tasks in line with recipes and asyncs
+
* rules should accept #seq not just the list
* <<< for running tasks one by one. Current one runs in parallel only.
* complete copyFiles method
diff --git a/global.json b/global.json
new file mode 100644
index 0000000..23e9da9
--- /dev/null
+++ b/global.json
@@ -0,0 +1,6 @@
+{
+ "sdk": {
+ "rollForward": "major",
+ "version": "7.0.0"
+ }
+}
\ No newline at end of file
diff --git a/readme.md b/readme.md
index be9cbd1..438b360 100644
--- a/readme.md
+++ b/readme.md
@@ -7,9 +7,8 @@ Xake is a build utility that uses the full power of the F# programming language.
The simple script looks like:
```fsharp
-#r "paket:
- nuget Xake ~> 1.1 prerelease
- nuget Xake.Dotnet ~> 1.1 prerelease //"
+#r "nuget: Xake, 2.0.0"
+#r "nuget: Xake.Dotnet, 1.1.4.7-beta"
open Xake
open Xake.Dotnet
@@ -25,7 +24,9 @@ do xakeScript {
This script compiles helloworld assembly from helloworld.cs file.
-To run this script:
+## Getting started
+
+Make sure dotnet SDK 7.0+ is installed.
1. Clone the project:
@@ -36,8 +37,7 @@ To run this script:
```
cd samples
- dotnet restore dotnet-fake.csproj
- dotnet fake run gettingstarted.fsx
+ dotnet fsi gettingstarted.fsx
```
## Further reading
@@ -51,12 +51,28 @@ To run this script:
Once you cloned the repository you are ready to compile and test the binaries:
```
-dotnet restore build.proj
-dotnet fake run build.fsx -- build test
+dotnet fsi build.fsx -- -- build test
```
... or use `build.cmd` (`build.sh`) in the root folder
+## Getting started for Mono on Linux/OSX
+
+> This is untested and mono nowadays is poorly explored territory for me.
+
+Make sure mono with F# is installed and root certificates are imported:
+
+```
+sudo apt-get install mono-complete
+sudo mozroots --import --sync
+```
+
+TBD
+
+## Documentation
+
+See [documentation](docs/overview.md) for more details.
+
## References
* [documentation](https://github.com/xakebuild/Xake/wiki)
diff --git a/samples/book/intro.fsx b/samples/book/intro.fsx
index 6bd4156..8c06c72 100644
--- a/samples/book/intro.fsx
+++ b/samples/book/intro.fsx
@@ -1,6 +1,6 @@
-#r "paket:
- nuget Xake ~> 1.1 prerelease
- nuget Xake.Dotnet ~> 1.1 prerelease //" // (1)
+#r "nuget: Xake, 1.1.4.427-beta"
+#r "nuget: Xake.Dotnet, 1.1.4.7-beta" (1)
+
open Xake // (2)
open Xake.Dotnet // (2.1)
diff --git a/samples/catch_errors.fsx b/samples/catch_errors.fsx
index 22f83ab..4f266a3 100644
--- a/samples/catch_errors.fsx
+++ b/samples/catch_errors.fsx
@@ -1,5 +1,4 @@
-#r "paket: nuget Xake ~> 1.1 prerelease //"
-
+#r "nuget: Xake, 2.0.0"
open Xake
do xakeScript {
diff --git a/samples/features.fsx b/samples/features.fsx
index b474bde..289249f 100644
--- a/samples/features.fsx
+++ b/samples/features.fsx
@@ -1,10 +1,5 @@
-#r "paket:
- nuget Xake ~> 1.1 prerelease
- nuget Xake.Dotnet ~> 1.1 prerelease //"
-
-#if !FAKE
-#load ".fake/features.fsx/intellisense.fsx"
-#endif
+#r "nuget: Xake, 2.0.0"
+#r "nuget: Xake.Dotnet, 1.1.4.7-beta"
// This a sample Xake script to show off some features.
//
diff --git a/samples/gettingstarted.fsx b/samples/gettingstarted.fsx
index 4a25411..6ac0bd5 100644
--- a/samples/gettingstarted.fsx
+++ b/samples/gettingstarted.fsx
@@ -1,6 +1,5 @@
-#r "paket:
- nuget Xake ~> 1.1 prerelease
- nuget Xake.Dotnet ~> 1.1 prerelease //"
+#r "nuget: Xake, 2.0.0"
+#r "nuget: Xake.Dotnet, 1.1.4.7-beta"
open Xake
open Xake.Dotnet
diff --git a/samples/rmdir.fsx b/samples/rmdir.fsx
index 938760c..439d819 100644
--- a/samples/rmdir.fsx
+++ b/samples/rmdir.fsx
@@ -1,4 +1,4 @@
-#r "paket: nuget Xake ~> 1.1 prerelease //"
+#r "nuget: Xake, 1.1.4.427-beta"
open Xake
open Xake.Tasks
diff --git a/src/core/Database.fs b/src/core/Database.fs
index d36dca3..1e45c6b 100644
--- a/src/core/Database.fs
+++ b/src/core/Database.fs
@@ -59,7 +59,7 @@ module Storage =
| FileDep _ -> 1
| EnvVar _ -> 2
| Var _ -> 3
- | AlwaysRerun _ -> 4
+ | AlwaysRerun -> 4
| GetFiles _ -> 5)
[| wrap (ArtifactDep, fun (ArtifactDep f | OtherwiseFail f) -> f) target
wrap (FileDep, fun (FileDep(f, ts) | OtherwiseFail (f, ts)) -> (f, ts)) (pair file date)
diff --git a/src/core/DependencyAnalysis.fs b/src/core/DependencyAnalysis.fs
index 2f747b6..efc152e 100644
--- a/src/core/DependencyAnalysis.fs
+++ b/src/core/DependencyAnalysis.fs
@@ -25,7 +25,8 @@ let getExecTime ctx target =
|> Option.fold (fun _ r -> r.Steps |> List.sumBy (fun s -> s.OwnTime)) 0
/// Gets single dependency state and reason of a change.
-let getDepState getVar getFileList (getChangedDeps: Target -> ChangeReason list) = function
+let getDepState getVar getFileList (getChangedDeps: Target -> ChangeReason list) x =
+ match x with
| FileDep (a:File, wrtime) when not((File.exists a) && abs((File.getLastWriteTime a - wrtime).TotalMilliseconds) < TimeCompareToleranceMs) ->
let dbgInfo = File.exists a |> function
| false -> "file does not exists"
diff --git a/src/core/ExecCore.fs b/src/core/ExecCore.fs
index 2e50fe8..f83132d 100644
--- a/src/core/ExecCore.fs
+++ b/src/core/ExecCore.fs
@@ -5,11 +5,6 @@ module internal ExecCore =
open System.Text.RegularExpressions
open DependencyAnalysis
- /// Default options
- []
- let XakeOptions = ExecOptions.Default
-
- open WorkerPool
open Storage
/// Writes the message with formatting to a log
@@ -74,9 +69,12 @@ module internal ExecCore =
let targets = patterns |> List.map (generateName >> (>) projectRoot >> File.make >> FileTarget)
rule, groups, targets)
- |PhonyRule (name,_), PhonyAction phony when phony = name ->
- // writeLog Verbose "Found phony pattern '%s'" name
- Some (rule, [], [target])
+ |PhonyRule (pattern,_), PhonyAction phony ->
+ // printfn $"Phony rule {phony}, pattern {pattern}"
+ // Some (rule, [], [target])
+ phony
+ |> Path.matchGroups pattern ""
+ |> Option.map (fun groups -> rule,groups,[target])
| _ -> None
@@ -187,7 +185,10 @@ module internal ExecCore =
/// phony actions are detected by their name so if there's "clean" phony and file "clean" in `need` list if will choose first
let makeTarget ctx name =
let (Rules rules) = ctx.Rules
- let isPhonyRule nm = function |PhonyRule (n,_) when n = nm -> true | _ -> false
+ let isPhonyRule nm = function
+ |PhonyRule (pattern,_) ->
+ nm |> Path.matchGroups pattern "" |> Option.isSome
+ | _ -> false
in
match rules |> List.exists (isPhonyRule name) with
| true -> PhonyAction name
@@ -206,21 +207,21 @@ module internal ExecCore =
let rec showDepStatus ii reasons =
reasons |> function
- | ChangeReason.Other reason ->
+ | Other reason ->
print "%sReason: %s" (indent ii) reason
- | ChangeReason.Depends t ->
+ | Depends t ->
print "%sDepends '%s' - changed target" (indent ii) t.ShortName
- | ChangeReason.DependsMissingTarget t ->
+ | DependsMissingTarget t ->
print "%sDepends on '%s' - missing target" (indent ii) t.ShortName
- | ChangeReason.FilesChanged (file:: rest) ->
+ | FilesChanged (file:: rest) ->
print "%sFile is changed '%s' %s" (indent ii) file (if List.isEmpty rest then "" else sprintf " and %d more file(s)" <| List.length rest)
| reasons ->
do print "%sSome reason %A" (indent ii) reasons
()
let rec displayNestedDeps ii =
function
- | ChangeReason.DependsMissingTarget t
- | ChangeReason.Depends t ->
+ | DependsMissingTarget t
+ | Depends t ->
showTargetStatus ii t
| _ -> ()
and showTargetStatus ii target =
@@ -276,10 +277,10 @@ module internal ExecCore =
getDeps >>
function
| [] -> false, ""
- | ChangeReason.Other reason::_ -> true, reason
- | ChangeReason.Depends t ::_ -> true, "Depends on target " + t.ShortName
- | ChangeReason.DependsMissingTarget t ::_ -> true, sprintf "Depends on target %s (missing)" t.ShortName
- | ChangeReason.FilesChanged (file::_) ::_ -> true, "File(s) changed " + file
+ | Other reason::_ -> true, reason
+ | Depends t ::_ -> true, "Depends on target " + t.ShortName
+ | DependsMissingTarget t ::_ -> true, sprintf "Depends on target %s (missing)" t.ShortName
+ | FilesChanged (file::_) ::_ -> true, "File(s) changed " + file
| reasons -> true, sprintf "Some reason %A" reasons
>>
function
@@ -310,17 +311,25 @@ module internal ExecCore =
/// Executes the build script
let runScript options rules =
let logger = CombineLogger (ConsoleLogger options.ConLogLevel) options.CustomLogger
-
let logger =
match options.FileLog, options.FileLogLevel with
| null,_ | "",_
- | _,Verbosity.Silent -> logger
+ | _, Silent -> logger
| logFileName,level -> CombineLogger logger (FileLogger logFileName level)
let (throttler, pool) = WorkerPool.create logger options.Threads
-
let db = Storage.openDb (options.ProjectRoot > options.DbFileName) logger
+ let finalize () =
+ db.PostAndReply Storage.CloseWait
+ FlushLogs()
+
+ System.Console.CancelKeyPress
+ |> Event.add (fun _ ->
+ logger.Log Error "Build interrupted by user"
+ finalize()
+ exit 1)
+
let ctx = {
Ordinal = 0
TaskPool = pool; Throttler = throttler
@@ -363,8 +372,7 @@ module internal ExecCore =
ctx.Logger.Log Message "\n\n\tBuild failed after running for %A\n" (System.DateTime.Now - start)
exit 2
finally
- db.PostAndReply Storage.CloseWait
- Logging.FlushLogs()
+ finalize()
/// "need" implementation
let need targets =
diff --git a/src/core/ExecTypes.fs b/src/core/ExecTypes.fs
index 5f87557..7f4c0ae 100644
--- a/src/core/ExecTypes.fs
+++ b/src/core/ExecTypes.fs
@@ -44,30 +44,28 @@ type ExecOptions = {
/// Dump dependencies only
Progress: bool
-} with
-static member Default =
- {
- ProjectRoot = System.IO.Directory.GetCurrentDirectory()
- Threads = System.Environment.ProcessorCount
- ConLogLevel = Normal
-
- CustomLogger = CustomLogger (fun _ -> false) ignore
- FileLog = "build.log"
- FileLogLevel = Chatty
- Targets = []
- FailOnError = false
- Vars = List.Empty
- IgnoreCommandLine = false
- Nologo = false
- DbFileName = ".xake"
- DryRun = false
- DumpDeps = false
- Progress = true
+} with static member Default = {
+ ProjectRoot = System.IO.Directory.GetCurrentDirectory()
+ Threads = System.Environment.ProcessorCount
+ ConLogLevel = Normal
+
+ CustomLogger = CustomLogger (fun _ -> false) ignore
+ FileLog = "build.log"
+ FileLogLevel = Chatty
+ Targets = []
+ FailOnError = false
+ Vars = List.Empty
+ IgnoreCommandLine = false
+ Nologo = false
+ DbFileName = ".xake"
+ DryRun = false
+ DumpDeps = false
+ Progress = true
}
end
-type internal ExecStatus = | Succeed | Skipped | JustFile
-type private TaskPool = Agent>
+type ExecStatus = | Succeed | Skipped | JustFile
+type TaskPool = Agent>
/// Script execution context
type ExecContext = {
diff --git a/src/core/Fileset.fs b/src/core/Fileset.fs
index 9d481ba..d6ae187 100644
--- a/src/core/Fileset.fs
+++ b/src/core/Fileset.fs
@@ -249,7 +249,7 @@ module Fileset =
Fileset (opts, pts @ [includes |> Path.parse |> Includes])
/// Adds excludes pattern to a fileset.
- static member (--) (Fileset (opts,pts), excludes) =
+ static member (--) (Fileset (opts,pts), excludes): Fileset =
Fileset (opts, pts @ [excludes |> Path.parse |> Excludes])
end
diff --git a/src/core/Logging.fs b/src/core/Logging.fs
index a8124df..61fa35b 100644
--- a/src/core/Logging.fs
+++ b/src/core/Logging.fs
@@ -124,9 +124,10 @@ module private ConsoleSink =
let rec loop (progressMessage) =
let wipeProgressMessage () =
let len = progressMessage |> Option.fold (fun _ -> String.length) 0
- // printfn "cleft: %A len: %d" Console.CursorLeft len
- match len - Console.CursorLeft with
- | e when e > 0 -> System.Console.Write (String.replicate e " ")
+ Console.Out.Flush()
+ let cursorLeft = Console.CursorLeft
+ len - cursorLeft |> function
+ | e when e > 0 -> Console.Write (String.replicate e " ")
| _ -> ()
let renderProgress = function
| Some (outputString: string) ->
@@ -141,9 +142,9 @@ module private ConsoleSink =
Console.Write (sprintf "\r[%s] " level)
Console.ForegroundColor <- textColor
- System.Console.Write txt
+ Console.Write txt
wipeProgressMessage()
- System.Console.WriteLine()
+ Console.WriteLine()
async {
let! msg = mbox.Receive()
@@ -152,16 +153,9 @@ module private ConsoleSink =
match level |> levelToColor with
| Some colors ->
// in case of CRLF in the string make sure we washed out the progress message
- let rec writeLines = function
- | [] -> fun _ -> ()
- | (txt: string)::tail ->
- function
- | true ->
- renderLineWithInfo colors (LevelToString level) txt
- do writeLines tail false
- | false -> System.Console.WriteLine txt; do writeLines tail false
-
- writeLines (text.Split('\n') |> List.ofArray) true
+ text.Split('\n') |> Seq.iteri (function
+ | 0 -> renderLineWithInfo colors (LevelToString level)
+ | _ -> System.Console.WriteLine)
renderProgress progressMessage
| _ -> ()
@@ -181,7 +175,8 @@ module private ConsoleSink =
| Flush ch ->
wipeProgressMessage()
- Console.Write "\r"
+ do! Console.Out.FlushAsync() |> Async.AwaitTask
+
ch.Reply ()
return! loop None
@@ -206,9 +201,7 @@ let private ConsoleLoggerBase (write: Level -> string -> unit) maxLevel =
/// Simplistic console logger.
let DumbConsoleLogger =
- ConsoleLoggerBase (
- fun level -> (LevelToString level) |> sprintf "[%s] %s" >> System.Console.WriteLine
- )
+ ConsoleLoggerBase (fun l -> l |> LevelToString |> sprintf "[%s] %s" >> System.Console.WriteLine)
/// Console logger with colors highlighting
let ConsoleLogger =
@@ -217,7 +210,7 @@ let ConsoleLogger =
/// Ensures all logs finished pending output.
let FlushLogs () =
try
- ConsoleSink.po.PostAndReply (ConsoleSink.Flush, 200) |> ignore
+ ConsoleSink.po.PostAndTryAsyncReply (ConsoleSink.Flush, 200) |> Async.RunSynchronously |> ignore
with _ -> ()
/// Draws a progress bar to console log.
@@ -233,9 +226,7 @@ let WriteConsoleProgress =
let CombineLogger (log1 : ILogger) (log2 : ILogger) =
{ new ILogger with
member __.Log level (fmt : Printf.StringFormat<'a, unit>) : 'a =
- let write s =
- log1.Log level "%s" s
- log2.Log level "%s" s
+ let write s = log1.Log level "%s" s; log2.Log level "%s" s
Printf.kprintf write fmt }
///
@@ -254,11 +245,11 @@ let PrefixLogger (prefix:string) (log : ILogger) =
///
///
let parseVerbosity = function
- | "Silent" -> Verbosity.Silent
- | "Quiet" -> Verbosity.Quiet
- | "Normal" -> Verbosity.Normal
- | "Loud" -> Verbosity.Loud
- | "Chatty" -> Verbosity.Chatty
- | "Diag" -> Verbosity.Diag
+ | "Silent" -> Silent
+ | "Quiet" -> Quiet
+ | "Normal" -> Normal
+ | "Loud" -> Loud
+ | "Chatty" -> Chatty
+ | "Diag" -> Diag
| s ->
failwithf "invalid verbosity: %s. Expected one of %s" s "Silent | Quiet | Normal | Loud | Chatty | Diag"
diff --git a/src/core/Pickler.fs b/src/core/Pickler.fs
index c6560d8..701c22a 100644
--- a/src/core/Pickler.fs
+++ b/src/core/Pickler.fs
@@ -84,7 +84,7 @@ module Pickler =
///
let option pu =
alt
- (function | None _ -> 0 | Some _ -> 1)
+ (function | None -> 0 | Some _ -> 1)
[|
wrap ((fun () -> None), ignore) unit
wrap (Some, Option.get) pu
diff --git a/src/core/Program.fs b/src/core/Program.fs
index 887d0bc..a9ebf89 100644
--- a/src/core/Program.fs
+++ b/src/core/Program.fs
@@ -21,7 +21,7 @@ module internal ParseArgs = begin
| "-h" | "/h" | "--help" | "/help" | "/?" | "-?" ->
printf """
Usage:
- fsi