From 2957814f4efdc3fb1c0f2aae6d8d189321b32471 Mon Sep 17 00:00:00 2001 From: Colin Gravill Date: Tue, 17 May 2016 21:54:26 +0100 Subject: [PATCH 1/3] Proof of concept: show types Extended the nuget manager to parse more directives. Use this to toggle the showing of types on. More work needed - toggle off, refactor out of nuget --- src/IfSharp.Kernel/Evaluation.fs | 1 + src/IfSharp.Kernel/Kernel.fs | 17 +++++++++++++ src/IfSharp.Kernel/NuGetManager.fs | 41 ++++++++++++++++++++++-------- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/IfSharp.Kernel/Evaluation.fs b/src/IfSharp.Kernel/Evaluation.fs index 461d7e9..a63ad67 100644 --- a/src/IfSharp.Kernel/Evaluation.fs +++ b/src/IfSharp.Kernel/Evaluation.fs @@ -8,6 +8,7 @@ open Microsoft.FSharp.Compiler.Interactive.Shell [] module Evaluation = + let internal fsiout = ref false let internal sbOut = new StringBuilder() let internal sbErr = new StringBuilder() let internal inStream = new StringReader("") diff --git a/src/IfSharp.Kernel/Kernel.fs b/src/IfSharp.Kernel/Kernel.fs index 7ca8935..e1170ba 100644 --- a/src/IfSharp.Kernel/Kernel.fs +++ b/src/IfSharp.Kernel/Kernel.fs @@ -236,6 +236,20 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) = let results = compiler.NuGetManager.Preprocess(code) let newCode = String.Join("\n", results.FilteredLines) + if not (Seq.isEmpty results.HelpLines) then + fsiEval.EvalInteraction("#help") + let ifsharpHelp = + """ IF# notebook directives: + + #fsioutput ["on"|"off"];; Toggle output display on/off + """ + let fsiHelp = sbOut.ToString() + pyout (ifsharpHelp + fsiHelp) + sbOut.Clear() |> ignore + + if not (Seq.isEmpty results.FsiOutputLines) then + fsiout := true + // do nuget stuff for package in results.Packages do if not (String.IsNullOrWhiteSpace(package.Error)) then @@ -256,6 +270,9 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) = if not <| String.IsNullOrEmpty(newCode) then fsiEval.EvalInteraction(newCode) + + if fsiout.Value then + pyout (sbOut.ToString()) /// Handles an 'execute_request' message let executeRequest(msg : KernelMessage) (content : ExecuteRequest) = diff --git a/src/IfSharp.Kernel/NuGetManager.fs b/src/IfSharp.Kernel/NuGetManager.fs index 5777ccb..46f21c0 100644 --- a/src/IfSharp.Kernel/NuGetManager.fs +++ b/src/IfSharp.Kernel/NuGetManager.fs @@ -59,6 +59,8 @@ type CustomErrorInfo = type PreprocessResults = { OriginalLines : string[]; + HelpLines : string[]; + FsiOutputLines : string[]; NuGetLines : string[]; FilteredLines : string[]; Packages : NuGetPackage[]; @@ -89,17 +91,25 @@ type CustomInstallCommand() = module NuGetManagerInternals = - /// Separates a list of lines between into two partitions, the first list are the directive lines, second list is the other lines - let partitionLines(directive) (lines : string[]) = + type Line = + | HelpDirective + | FSIOutputDirective + | NugetDirective + | Other + + let determineLineType (idx, (line:string)) = + match line.ToLower() with + | line when line.StartsWith "#n" -> NugetDirective + | line when line.StartsWith "#help" -> HelpDirective + | line when line.StartsWith "#fsioutput" -> FSIOutputDirective + | _ -> Other + + /// Separates into map of directive types + let partitionLines(lines : string[]) = lines |> Seq.mapi (fun (idx) (line) -> (idx, line)) - |> Seq.toList - |> List.partition (fun (idx, line) -> line.StartsWith(directive)) - - /// Separates a list of lines between into two partitions, the first list are the directive lines, second list is the other lines - let partitionSource(directive) (source : string) = - let delimiters = [|"\r\n"; "\n"; "\r";|] - partitionLines directive (source.Split(delimiters, StringSplitOptions.None)) + |> Seq.groupBy determineLineType + |> Map.ofSeq /// Parses a directive line. Example: #N "Deedle" let parseDirectiveLine (prefix : string) (line : string) = @@ -246,7 +256,15 @@ type NuGetManager (executingDirectory : string) = // split the source code into lines, then get the nuget lines let lines = source.Split('\n') - let (nugetLines, otherLines) = NuGetManagerInternals.partitionLines "#N" lines + let linesSplit = NuGetManagerInternals.partitionLines lines + + let orEmpty key = let opt = Map.tryFind key linesSplit + if opt.IsSome then opt.Value else Seq.empty + + let helpLines = NuGetManagerInternals.Line.HelpDirective |> orEmpty + let fsiOutputLines = NuGetManagerInternals.Line.FSIOutputDirective |> orEmpty + let nugetLines = NuGetManagerInternals.Line.NugetDirective |> orEmpty + let otherLines = NuGetManagerInternals.Line.Other |> orEmpty // parse the nuget lines and then download the packages let nugetPackages = @@ -264,7 +282,10 @@ type NuGetManager (executingDirectory : string) = { OriginalLines = lines; + HelpLines = helpLines |> Seq.map(fun (idx, line) -> line) |> Seq.toArray; + FsiOutputLines = fsiOutputLines |> Seq.map(fun (idx, line) -> line) |> Seq.toArray; NuGetLines = nugetLines |> Seq.map(fun (idx, line) -> line) |> Seq.toArray; + FilteredLines = otherLines |> Seq.map(fun (idx, line) -> line) |> Seq.toArray; Packages = nugetPackages |> Seq.map(fun (idx, package) -> package) |> Seq.toArray; Errors = errors; From 5a7b53b5ef573ed1bb747f1647352840b66cd778 Mon Sep 17 00:00:00 2001 From: Colin Gravill Date: Wed, 1 Jun 2016 12:10:04 +0100 Subject: [PATCH 2/3] Factored out directives, allow turning off types Moved more of the directive preprocessing out of nuget manager. Can't get it all out as the manager is responsible for fetching packages down. --- src/IfSharp.Kernel/DirectivePreprocessor.fs | 27 +++++++++++ src/IfSharp.Kernel/Kernel.fs | 9 +++- src/IfSharp.Kernel/NuGetManager.fs | 50 +++++---------------- 3 files changed, 47 insertions(+), 39 deletions(-) create mode 100644 src/IfSharp.Kernel/DirectivePreprocessor.fs diff --git a/src/IfSharp.Kernel/DirectivePreprocessor.fs b/src/IfSharp.Kernel/DirectivePreprocessor.fs new file mode 100644 index 0000000..87bf5d6 --- /dev/null +++ b/src/IfSharp.Kernel/DirectivePreprocessor.fs @@ -0,0 +1,27 @@ +namespace IfSharp.Kernel + +module DirectivePreprocessor = + + type Line = + | HelpDirective + | FSIOutputDirective + | NugetDirective + | Other + + let determineLineType (idx, (line:string)) = + match line.ToLower() with + | line when line.StartsWith "#n" -> NugetDirective + | line when line.StartsWith "#help" -> HelpDirective + | line when line.StartsWith "#fsioutput" -> FSIOutputDirective + | _ -> Other + + /// Separates into map of directive types + let partitionLines(lines : string[]) = + lines + |> Seq.mapi (fun (idx) (line) -> (idx, line)) + |> Seq.groupBy determineLineType + |> Map.ofSeq + + /// Parses a directive line. Example: #N "Deedle" + let parseDirectiveLine (prefix : string) (line : string) = + line.Substring(prefix.Length + 1).Trim().Trim('"') diff --git a/src/IfSharp.Kernel/Kernel.fs b/src/IfSharp.Kernel/Kernel.fs index e1170ba..7fdcb9a 100644 --- a/src/IfSharp.Kernel/Kernel.fs +++ b/src/IfSharp.Kernel/Kernel.fs @@ -247,8 +247,15 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) = pyout (ifsharpHelp + fsiHelp) sbOut.Clear() |> ignore + //This is a persistent toggle, just respect the last one if not (Seq.isEmpty results.FsiOutputLines) then - fsiout := true + let lastFsiOutput = Seq.last results.FsiOutputLines + if lastFsiOutput.ToLower().Contains("on") then + fsiout := true + else if lastFsiOutput.ToLower().Contains("off") then + fsiout := false + else + pyout (sprintf "Unreocognised fsioutput setting: %s" lastFsiOutput) // do nuget stuff for package in results.Packages do diff --git a/src/IfSharp.Kernel/NuGetManager.fs b/src/IfSharp.Kernel/NuGetManager.fs index 46f21c0..8c85207 100644 --- a/src/IfSharp.Kernel/NuGetManager.fs +++ b/src/IfSharp.Kernel/NuGetManager.fs @@ -89,32 +89,6 @@ type CustomInstallCommand() = let semanticVersion = SemanticVersion(version) packageManager.LocalRepository.FindPackage(packageId, semanticVersion) -module NuGetManagerInternals = - - type Line = - | HelpDirective - | FSIOutputDirective - | NugetDirective - | Other - - let determineLineType (idx, (line:string)) = - match line.ToLower() with - | line when line.StartsWith "#n" -> NugetDirective - | line when line.StartsWith "#help" -> HelpDirective - | line when line.StartsWith "#fsioutput" -> FSIOutputDirective - | _ -> Other - - /// Separates into map of directive types - let partitionLines(lines : string[]) = - lines - |> Seq.mapi (fun (idx) (line) -> (idx, line)) - |> Seq.groupBy determineLineType - |> Map.ofSeq - - /// Parses a directive line. Example: #N "Deedle" - let parseDirectiveLine (prefix : string) (line : string) = - line.Substring(prefix.Length + 1).Trim().Trim('"') - /// The NuGetManager class contains methods for downloading nuget packages and such type NuGetManager (executingDirectory : string) = @@ -241,7 +215,7 @@ type NuGetManager (executingDirectory : string) = /// prerelease should be used or not. member this.ParseNugetLine (line : string) = - let contents = NuGetManagerInternals.parseDirectiveLine "#N" line + let contents = DirectivePreprocessor.parseDirectiveLine "#N" line if contents.Contains("/") then let splits = contents.Split([| '/' |]) if splits.Length > 2 then @@ -256,15 +230,15 @@ type NuGetManager (executingDirectory : string) = // split the source code into lines, then get the nuget lines let lines = source.Split('\n') - let linesSplit = NuGetManagerInternals.partitionLines lines + let linesSplit = DirectivePreprocessor.partitionLines lines let orEmpty key = let opt = Map.tryFind key linesSplit if opt.IsSome then opt.Value else Seq.empty - let helpLines = NuGetManagerInternals.Line.HelpDirective |> orEmpty - let fsiOutputLines = NuGetManagerInternals.Line.FSIOutputDirective |> orEmpty - let nugetLines = NuGetManagerInternals.Line.NugetDirective |> orEmpty - let otherLines = NuGetManagerInternals.Line.Other |> orEmpty + let helpLines = DirectivePreprocessor.Line.HelpDirective |> orEmpty + let fsiOutputLines = DirectivePreprocessor.Line.FSIOutputDirective |> orEmpty + let nugetLines = DirectivePreprocessor.Line.NugetDirective |> orEmpty + let otherLines = DirectivePreprocessor.Line.Other |> orEmpty // parse the nuget lines and then download the packages let nugetPackages = @@ -276,17 +250,17 @@ type NuGetManager (executingDirectory : string) = // gather errors let errors = nugetPackages - |> Seq.filter (fun (idx, package) -> String.IsNullOrEmpty(package.Error) = false) + |> Seq.filter (fun (_, package) -> String.IsNullOrEmpty(package.Error) = false) |> Seq.map (fun (idx, package) -> CustomErrorInfo.From("", idx, 0, idx, lines.[idx].Length, package.Error, "Error", "preprocess")) |> Seq.toArray { OriginalLines = lines; - HelpLines = helpLines |> Seq.map(fun (idx, line) -> line) |> Seq.toArray; - FsiOutputLines = fsiOutputLines |> Seq.map(fun (idx, line) -> line) |> Seq.toArray; - NuGetLines = nugetLines |> Seq.map(fun (idx, line) -> line) |> Seq.toArray; + HelpLines = helpLines |> Seq.map(fun (_, line) -> line) |> Seq.toArray; + FsiOutputLines = fsiOutputLines |> Seq.map(fun (_, line) -> line) |> Seq.toArray; + NuGetLines = nugetLines |> Seq.map(fun (_, line) -> line) |> Seq.toArray; - FilteredLines = otherLines |> Seq.map(fun (idx, line) -> line) |> Seq.toArray; - Packages = nugetPackages |> Seq.map(fun (idx, package) -> package) |> Seq.toArray; + FilteredLines = otherLines |> Seq.map(fun (_, line) -> line) |> Seq.toArray; + Packages = nugetPackages |> Seq.map(fun (_, package) -> package) |> Seq.toArray; Errors = errors; } From 2a891a88af9c9c526430f3943006002cd5690908 Mon Sep 17 00:00:00 2001 From: Colin Gravill Date: Wed, 1 Jun 2016 12:23:52 +0100 Subject: [PATCH 3/3] Project file change --- src/IfSharp.Kernel/IfSharp.Kernel.fsproj | 1 + 1 file changed, 1 insertion(+) diff --git a/src/IfSharp.Kernel/IfSharp.Kernel.fsproj b/src/IfSharp.Kernel/IfSharp.Kernel.fsproj index 7ff32fc..bdf8d7a 100644 --- a/src/IfSharp.Kernel/IfSharp.Kernel.fsproj +++ b/src/IfSharp.Kernel/IfSharp.Kernel.fsproj @@ -78,6 +78,7 @@ +