├── .config └── dotnet-tools.json ├── .gitattributes ├── .gitignore ├── .paket └── Paket.Restore.targets ├── .travis.yml ├── Dockerfile ├── FSharp_Jupyter_Notebooks.ipynb ├── ISSUE_TEMPLATE.md ├── IfSharp.sln ├── IfSharpNetCore.sln ├── LICENSE ├── README.md ├── RELEASE_NOTES.md ├── azure-pipelines.yml ├── build.cmd ├── build.fsx ├── build.fsx.lock ├── build.sh ├── fake.cmd ├── fake.sh ├── ifsharpsetup.iss ├── jupyter-kernel ├── kernel.js ├── logo-32x32.png ├── logo-64x64.png └── static │ └── custom │ ├── fsharp.css │ ├── fsharp.js │ ├── webintellisense-codemirror.js │ └── webintellisense.js ├── nuget ├── FSharp.ProjectTemplate.nuspec ├── README.md └── publish.cmd ├── paket.dependencies ├── paket.lock └── src ├── IfSharp.Kernel ├── App.fs ├── AssemblyInfo.fs ├── Config.fs ├── DirectivePreprocessor.fs ├── Evaluation.fs ├── FsCompiler.fs ├── Globals.fs ├── IfSharp.Kernel.fsproj ├── IfSharpResources.fs ├── IfSharpResources.resx ├── Include.fsx ├── Kernel.fs ├── MainTypes.fs ├── NuGetManager.fs ├── Printers.fs ├── ShellMessages.fs ├── Util.fs └── paket.references ├── IfSharp ├── Angara.Charting.Dynamic.fsx ├── Angara.Charting.Paket.fsx ├── Angara.Charting.fsx ├── App.config ├── AssemblyInfo.fs ├── AsyncDisplay.Paket.fsx ├── AsyncDisplay.fsx ├── FSharp.Charting.Gtk.Paket.fsx ├── FSharp.Charting.Gtk.fsx ├── FSharp.Charting.Paket.fsx ├── FSharp.Charting.fsx ├── FsLab.fsx ├── IfSharp.fsproj ├── Paket.Generated.Refs.fsx ├── Paket.fsx ├── Plotly.NET.fsx ├── Program.fs ├── XPlot.GoogleCharts.Paket.fsx ├── XPlot.GoogleCharts.fsx ├── XPlot.Plotly.Paket.fsx ├── XPlot.Plotly.fsx ├── hide │ └── paket.dependencies ├── paket.lock ├── paket.references └── plotly-latest.min.js └── IfSharpNetCore ├── IfSharpNetCore.fsproj ├── Paket.Generated.Refs.fsx ├── Program.fs ├── XPlot.GoogleCharts.Paket.fsx ├── XPlot.GoogleCharts.fsx ├── XPlot.Plotly.Paket.fsx ├── XPlot.Plotly.fsx ├── hide └── paket.dependencies ├── paket.references └── plotly-latest.min.js /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "fake-cli": { 6 | "version": "5.20.1", 7 | "commands": [ 8 | "fake" 9 | ] 10 | }, 11 | "paket": { 12 | "version": "5.249.2", 13 | "commands": [ 14 | "paket" 15 | ] 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | .vs/ 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.sln.docstates 10 | 11 | # Build results 12 | 13 | [Dd]ebug/ 14 | [Rr]elease/ 15 | x64/ 16 | build/ 17 | [Bb]in/ 18 | [Oo]bj/ 19 | 20 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 21 | !packages/*/build/ 22 | 23 | # MSTest test Results 24 | [Tt]est[Rr]esult*/ 25 | [Bb]uild[Ll]og.* 26 | 27 | *_i.c 28 | *_p.c 29 | *.ilk 30 | *.meta 31 | *.obj 32 | *.pch 33 | *.pdb 34 | *.pgc 35 | *.pgd 36 | *.rsp 37 | *.sbr 38 | *.tlb 39 | *.tli 40 | *.tlh 41 | *.tmp 42 | *.tmp_proj 43 | *.log 44 | *.vspscc 45 | *.vssscc 46 | .builds 47 | *.pidb 48 | *.log 49 | *.scc 50 | 51 | # Visual C++ cache files 52 | ipch/ 53 | *.aps 54 | *.ncb 55 | *.opensdf 56 | *.sdf 57 | *.cachefile 58 | 59 | # Visual Studio profiler 60 | *.psess 61 | *.vsp 62 | *.vspx 63 | 64 | # Guidance Automation Toolkit 65 | *.gpState 66 | 67 | # ReSharper is a .NET coding add-in 68 | _ReSharper*/ 69 | *.[Rr]e[Ss]harper 70 | 71 | # TeamCity is a build add-in 72 | _TeamCity* 73 | 74 | # DotCover is a Code Coverage Tool 75 | *.dotCover 76 | 77 | # NCrunch 78 | *.ncrunch* 79 | .*crunch*.local.xml 80 | 81 | # Installshield output folder 82 | [Ee]xpress/ 83 | 84 | # DocProject is a documentation generator add-in 85 | DocProject/buildhelp/ 86 | DocProject/Help/*.HxT 87 | DocProject/Help/*.HxC 88 | DocProject/Help/*.hhc 89 | DocProject/Help/*.hhk 90 | DocProject/Help/*.hhp 91 | DocProject/Help/Html2 92 | DocProject/Help/html 93 | 94 | # Click-Once directory 95 | publish/ 96 | 97 | # Publish Web Output 98 | *.Publish.xml 99 | 100 | # Enable nuget.exe in the .nuget folder (though normally executables are not tracked) 101 | !.nuget/NuGet.exe 102 | 103 | # Windows Azure Build Output 104 | csx 105 | *.build.csdef 106 | 107 | # Windows Store app package directory 108 | AppPackages/ 109 | 110 | # Others 111 | sql/ 112 | *.Cache 113 | ClientBin/ 114 | [Ss]tyle[Cc]op.* 115 | ~$* 116 | *~ 117 | *.dbmdl 118 | *.[Pp]ublish.xml 119 | *.pfx 120 | *.publishsettings 121 | 122 | # RIA/Silverlight projects 123 | Generated_Code/ 124 | 125 | # Backup & report files from converting an old project file to a newer 126 | # Visual Studio version. Backup files are not needed, because we have git ;-) 127 | _UpgradeReport_Files/ 128 | Backup*/ 129 | UpgradeLog*.XML 130 | UpgradeLog*.htm 131 | 132 | # SQL Server files 133 | App_Data/*.mdf 134 | App_Data/*.ldf 135 | 136 | 137 | #LightSwitch generated files 138 | GeneratedArtifacts/ 139 | _Pvt_Extensions/ 140 | ModelManifest.xml 141 | 142 | # ========================= 143 | # Windows detritus 144 | # ========================= 145 | 146 | # Windows image file caches 147 | Thumbs.db 148 | ehthumbs.db 149 | 150 | # Folder config file 151 | Desktop.ini 152 | 153 | # Recycle Bin used on file shares 154 | $RECYCLE.BIN/ 155 | 156 | # Mac desktop service store files 157 | .DS_Store 158 | 159 | # =================================================== 160 | # Exclude F# project specific directories and files 161 | # =================================================== 162 | 163 | # FAKE directory 164 | .fake/ 165 | 166 | # NuGet Packages Directory 167 | packages/ 168 | 169 | # Generated documentation folder 170 | docs/output/ 171 | 172 | # Temp folder used for publishing docs 173 | temp/ 174 | 175 | # Test results produced by build 176 | TestResults.xml 177 | paket-files 178 | /.idea/.idea.IfSharp 179 | /.ionide 180 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | 3 | sudo: required # may be able to use the new container-based Travis infrastructure 4 | 5 | services: 6 | - docker 7 | dist: xenial 8 | 9 | dotnet: 3.1.100 10 | 11 | script: 12 | - ./build.sh --target BuildNetFramework 13 | # - docker build . 14 | 15 | branches: 16 | only: 17 | - master 18 | - /^v\d+\.\d+(\.\d+)?(-\S*)?/ 19 | 20 | deploy: 21 | provider: script 22 | script: >- 23 | echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin && 24 | docker build --tag fsprojects/ifsharp:$TRAVIS_TAG . && 25 | docker tag fsprojects/ifsharp:$TRAVIS_TAG fsprojects/ifsharp:latest && 26 | docker push fsprojects/ifsharp:$TRAVIS_TAG && 27 | docker push fsprojects/ifsharp:latest 28 | on: 29 | tags: true 30 | repo: fsprojects/IfSharp 31 | 32 | 33 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | 2 | # NOTE: If you modify this base image to use a different Linux distro 3 | # then the install of the dotnet SDK may need to be changed 4 | FROM mono:5.20.1.19 5 | 6 | # Install Anaconda (conda / miniconda) 7 | RUN apt update \ 8 | && apt install -y \ 9 | apt-transport-https \ 10 | wget \ 11 | git 12 | RUN wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/Miniconda3-latest-Linux-x86_64.sh 13 | RUN chmod u+x ~/Miniconda3-latest-Linux-x86_64.sh 14 | RUN ~/Miniconda3-latest-Linux-x86_64.sh -b -p /opt/miniconda 15 | RUN . /opt/miniconda/bin/activate 16 | ENV PATH="/opt/miniconda/bin:$PATH" 17 | 18 | # Install dotnet SDK for debian 19 | # see https://dotnet.microsoft.com/download/linux-package-manager/debian9/sdk-current 20 | RUN apt install -y gpg 21 | RUN wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.asc.gpg 22 | RUN mv microsoft.asc.gpg /etc/apt/trusted.gpg.d/ 23 | RUN wget -q https://packages.microsoft.com/config/debian/9/prod.list 24 | RUN mv prod.list /etc/apt/sources.list.d/microsoft-prod.list 25 | RUN chown root:root /etc/apt/trusted.gpg.d/microsoft.asc.gpg 26 | RUN chown root:root /etc/apt/sources.list.d/microsoft-prod.list 27 | RUN apt-get update && apt-get install -y dotnet-sdk-2.2=2.2.105-1 && rm -rf /var/lib/opt/lists 28 | 29 | # Test conda to ensure the above worked. 30 | RUN conda -V 31 | 32 | # Install Jupyter and extensions 33 | RUN conda update -n base -c defaults conda 34 | RUN conda install -c anaconda jupyter 35 | RUN conda install -c conda-forge jupyter_contrib_nbextensions 36 | RUN conda install -c conda-forge jupyter_nbextensions_configurator 37 | 38 | # Install IfSharp 39 | WORKDIR / 40 | RUN git clone https://github.com/fsprojects/IfSharp.git 41 | RUN mkdir notebooks 42 | VOLUME notebooks 43 | 44 | # Add user 45 | RUN useradd -ms /bin/bash ifsharp-user 46 | RUN chown -R ifsharp-user /notebooks && chown -R ifsharp-user /IfSharp 47 | USER ifsharp-user 48 | 49 | WORKDIR /IfSharp 50 | RUN ./fake.sh build --target BuildNetFramework 51 | RUN mono src/IfSharp/bin/Release/ifsharp.exe --install 52 | 53 | # Install extensions and configurator 54 | RUN jupyter contrib nbextension install --user 55 | RUN jupyter nbextensions_configurator enable --user 56 | 57 | EXPOSE 8888 58 | 59 | # Final entrypoint 60 | ENTRYPOINT ["jupyter", \ 61 | "notebook", \ 62 | "--no-browser", \ 63 | "--ip='0.0.0.0'", \ 64 | "--port=8888", \ 65 | "--notebook-dir=/notebooks" \ 66 | ] 67 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | ### Description 3 | 4 | Please provide a succinct description of your issue. 5 | 6 | ### Repro steps 7 | 8 | Please provide the steps required to reproduce the problem 9 | 10 | 1. Step A 11 | 12 | 2. Step B 13 | 14 | ### Expected behavior 15 | 16 | Please provide a description of the behaviour you expect. 17 | 18 | ### Actual behavior 19 | 20 | Please provide a description of the actual behaviour you observe. 21 | 22 | ### Known workarounds 23 | 24 | Please provide a description of any known workarounds. 25 | 26 | ### Related information 27 | 28 | * Operating system 29 | * Branch 30 | * .NET Runtime, CoreCLR or Mono Version 31 | * Performance information, links to performance testing scripts 32 | 33 | -------------------------------------------------------------------------------- /IfSharp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.421 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "IfSharp.Kernel", "src\IfSharp.Kernel\IfSharp.Kernel.fsproj", "{25FE52CD-BCE3-471D-A629-9DC9F0410B6C}" 7 | EndProject 8 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "IfSharp", "src\IfSharp\IfSharp.fsproj", "{614109A5-EC07-47DA-BE73-D91CCC08FB4F}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {25FE52CD-BCE3-471D-A629-9DC9F0410B6C}.Debug|x64.ActiveCfg = Debug|x64 17 | {25FE52CD-BCE3-471D-A629-9DC9F0410B6C}.Debug|x64.Build.0 = Debug|x64 18 | {25FE52CD-BCE3-471D-A629-9DC9F0410B6C}.Release|x64.ActiveCfg = Release|x64 19 | {25FE52CD-BCE3-471D-A629-9DC9F0410B6C}.Release|x64.Build.0 = Release|x64 20 | {614109A5-EC07-47DA-BE73-D91CCC08FB4F}.Debug|x64.ActiveCfg = Debug|x64 21 | {614109A5-EC07-47DA-BE73-D91CCC08FB4F}.Debug|x64.Build.0 = Debug|x64 22 | {614109A5-EC07-47DA-BE73-D91CCC08FB4F}.Release|x64.ActiveCfg = Release|x64 23 | {614109A5-EC07-47DA-BE73-D91CCC08FB4F}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {6E614E07-33B2-4D12-B1CD-38BBFD484F64} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /IfSharpNetCore.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28803.352 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "IfSharp.Kernel", "src\IfSharp.Kernel\IfSharp.Kernel.fsproj", "{25FE52CD-BCE3-471D-A629-9DC9F0410B6C}" 7 | EndProject 8 | Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "IfSharpNetCore", "src\IfSharpNetCore\IfSharpNetCore.fsproj", "{4D3A95BC-3636-4474-B176-9ECCEC4FB3D8}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {25FE52CD-BCE3-471D-A629-9DC9F0410B6C}.Debug|x64.ActiveCfg = Debug|x64 17 | {25FE52CD-BCE3-471D-A629-9DC9F0410B6C}.Debug|x64.Build.0 = Debug|x64 18 | {25FE52CD-BCE3-471D-A629-9DC9F0410B6C}.Release|x64.ActiveCfg = Release|x64 19 | {25FE52CD-BCE3-471D-A629-9DC9F0410B6C}.Release|x64.Build.0 = Release|x64 20 | {4D3A95BC-3636-4474-B176-9ECCEC4FB3D8}.Debug|x64.ActiveCfg = Debug|x64 21 | {4D3A95BC-3636-4474-B176-9ECCEC4FB3D8}.Debug|x64.Build.0 = Debug|x64 22 | {4D3A95BC-3636-4474-B176-9ECCEC4FB3D8}.Release|x64.ActiveCfg = Release|x64 23 | {4D3A95BC-3636-4474-B176-9ECCEC4FB3D8}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {6E614E07-33B2-4D12-B1CD-38BBFD484F64} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Bayard Rock LLC 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the Bayard Rock LLC nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BAYARD ROCK LLC BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | | Build status | Linux | macOS | Windows | 2 | | --- | --- | ----------- | --- | 3 | | .NET Framework / Mono | [![Build Status](https://travis-ci.org/fsprojects/IfSharp.svg?branch=master)](https://travis-ci.org/fsprojects/IfSharp) | | [![Build Status](https://dev.azure.com/IFSharp/IFSharp/_apis/build/status/fsprojects.IfSharp?branchName=master&jobName=Windows)](https://dev.azure.com/IFSharp/IFSharp/_build/latest?definitionId=1&branchName=master) | 4 | | .NET Core (experimental) | [![Build Status](https://dev.azure.com/IFSharp/IFSharp/_apis/build/status/fsprojects.IfSharp?branchName=master&jobName=Linux)](https://dev.azure.com/IFSharp/IFSharp/_build/latest?definitionId=1&branchName=master) | [![Build Status](https://dev.azure.com/IFSharp/IFSharp/_apis/build/status/fsprojects.IfSharp?branchName=master&jobName=macOS)](https://dev.azure.com/IFSharp/IFSharp/_build/latest?definitionId=1&branchName=master) | [![Build Status](https://dev.azure.com/IFSharp/IFSharp/_apis/build/status/fsprojects.IfSharp?branchName=master&jobName=Windows)](https://dev.azure.com/IFSharp/IFSharp/_build/latest?definitionId=1&branchName=master) | 5 | 6 | # F# and Jupyter 7 | 8 | This implements F# for [Jupyter](http://jupyter.org/) notebooks. View the [Feature Notebook](FSharp_Jupyter_Notebooks.ipynb) for some of the features that are included. 9 | 10 | # .NET Interactive (alternative) 11 | 12 | There's related project of [.NET Interactive](https://github.com/dotnet/interactive) which was inspired by this one but a completly rethought approach with integrated package management, VS Code support, and variable sharing between languages. If you're moving to .NET Core support it's definitely worth checking out. There's a great video from [cartermp](https://github.com/cartermp) demoing some of the features: https://youtu.be/_QnbV6CAWXc?t=1298 13 | 14 | # Getting Started 15 | 16 | ## Docker 17 | 18 | To run using a Docker container on Linux/macOS: 19 | 20 | docker run -v $PWD:/notebooks -p 8888:8888 fsprojects/ifsharp 21 | 22 | or with PowerShell on Windows: 23 | 24 | docker run -v ${PWD}:/notebooks -p 8888:8888 fsprojects/ifsharp 25 | 26 | The container exposes your current directory as a volume called `notebooks` where the files get saved. 27 | Open with 28 | 29 | http://localhost:8888 30 | 31 | and enter the token printed by the docker container startup, or set up a password. 32 | 33 | Notes: 34 | 35 | * Add `-p :8888` if a different port mapping is required. 36 | 37 | * If using Windows you must enable file sharing for docker on that drive. 38 | 39 | ## Azure Notebooks 40 | 41 | You can use Jupyter F# Notebooks with free server-side execution at [Azure Notebooks](https://notebooks.azure.com/). 42 | If you select "Show me some samples", then there is an "Introduction to F#" which guides you through the language 43 | and its use in Jupyter. 44 | 45 | ## Windows Local Installation and Use 46 | 47 | 1. Download [Anaconda](https://www.anaconda.com/download/) for Python 3.6 48 | 49 | 2. Launch Anaconda3-4.4.0-Windows-x86_64.exe (or later exe should work, file an issue if you have issues) 50 | Click through the installation wizard, choosing the given install location. At the 'advanced installation options' screen shown below, select "Add Anaconda to my PATH environment variable". The installer warns against this step, as it can clash with previously installed software, however it's currently essential for running IfSharp. Now install. 51 | 52 | This should also install Jupyter: you may check this by entering 'jupyter notebook' into the Anaconda console window. If Jupyter does not launch (it should launch in the browser), install using 'pip install jupyter', or by following [Jupyter](http://jupyter.readthedocs.io/en/latest/install.html) instructions. 53 | 54 | ![Installation screenshot](/docs/files/img/anaconda-installation.png) 55 | 56 | 3. Download [the latest IfSharp zip release](https://github.com/fsprojects/IfSharp/releases/) 57 | 58 | 4. Run IfSharp.exe (IfSharp application icon). 59 | 60 | Jupyter will start and a notebook with F# can be selected. This can be run via "jupyter notebook" in future 61 | 62 | #### Troubleshooting 63 | 64 | If the launch fails in the console window, check that the Anaconda version used is currently added to the path. If not, uninstalling Anaconda and reinstalling using instructions 1- 65 | 66 | ## macOS Local Installation and Use 67 | 68 | 1. Install [Jupyter](http://jupyter.readthedocs.org/en/latest/install.html) via pip or Anaconda etc. 69 | 70 | 2. Install [Mono](http://www.mono-project.com/download/) (tested Mono 6.6.0) 71 | 72 | 3. Download [the latest IfSharp zip release](https://github.com/fsprojects/IfSharp/releases/) 73 | 74 | 4. Unzip the release then run `mono ifsharp.exe` 75 | 76 | Jupyter will start and a notebook with F# can be selected. This can be run via "jupyter notebook" in future 77 | 78 | ## Linux Local Installation and Use 79 | 80 | 1. Install [Jupyter](http://jupyter.readthedocs.org/en/latest/install.html) via pip or Anaconda etc. 81 | 82 | 2. Install [Mono](http://www.mono-project.com/docs/getting-started/install/linux/) (tested Mono 5.18, "mono-complete" recommended). 83 | 84 | 3. Download [the latest IfSharp zip release](https://github.com/fsprojects/IfSharp/releases/) 85 | 86 | 4. Unzip the release then run `mono ifsharp.exe` (this sets up the Jupyter kernel files in `~/.local/share/jupyter/kernels/ifsharp/`) 87 | 88 | Jupyter will start and a notebook with F# can be selected. This can be run via "jupyter notebook" in future 89 | 90 | ## Linux Local Installation (HDInsights) 91 | 92 | 1. Follow instructions to [install or update Mono](https://docs.microsoft.com/en-us/azure/hdinsight/hdinsight-hadoop-install-mono) on HDInsights. 93 | 94 | 2. [SSH into the HDInsights cluster](https://docs.microsoft.com/en-us/azure/hdinsight/hdinsight-hadoop-linux-use-ssh-unix). 95 | 96 | 3. Download [the latest IfSharp zip release](https://github.com/fsprojects/IfSharp/releases/) 97 | 98 | ``` 99 | # create ifsharp folder under /tmp 100 | mkdir ifsharp 101 | cd ifsharp 102 | wget https://github.com/fsprojects/IfSharp/releases/download/v3.0.4/IfSharp.v3.0.4.zip 103 | unzip IfSharp.v3.0.4.zip 104 | chmod +x ifsharp.exe 105 | ``` 106 | 4. From the [Azure portal](https://portal.azure.com/), open your cluster. See [List and show clusters](../hdinsight-administer-use-portal-linux.md#list-and-show-clusters) for the instructions. The cluster is opened in a new portal blade. 107 | 5. From the **Quick links** section, click **Cluster dashboards** to open the **Cluster dashboards** blade. If you don't see **Quick Links**, click **Overview** from the left menu on the blade. 108 | 6. Click **Jupyter Notebook**. If prompted, enter the admin credentials for the cluster. 109 | 110 | > [!NOTE] 111 | > You may also reach the Jupyter notebook on Spark cluster by opening the following URL in your browser. Replace **CLUSTERNAME** with the name of your cluster: 112 | > 113 | > `https://CLUSTERNAME.azurehdinsight.net/jupyter` 114 | > 115 | 7. Click **New**, and then click **Terminal**. 116 | 8. In the terminal window `cd` into the `/tmp/ifsharp/` folder and using mono, run the installer: 117 | 118 | ``` 119 | cd /tmp/ifsharp 120 | mono ifsharp.exe 121 | ``` 122 | 9. Back on the Jupyter homepage, click **New** and you will now see the F# kernel installed. 123 | 124 | # Screenshots 125 | 126 | ## Intellisense 127 | ![Intellisense Example #1](/docs/files/img/intellisense-1.png?raw=true "Intellisense Example #1") 128 | *** 129 | 130 | ![Intellisense Example #2](docs/files/img/intellisense-2.png?raw=true "Intellisense Example #2") 131 | 132 | ## Integrated NuGet (via Paket) 133 | ![NuGet Example](docs/files/img/integratedNuget.png?raw=true "NuGet example") 134 | 135 | ## Inline Error Messages 136 | ![Inline Error Message](docs/files/img/errors-1.png?raw=true "Inline error message") 137 | 138 | 139 | # Development Guide 140 | 141 | ## Building Docker image locally 142 | 143 | Build the container with: 144 | 145 | docker build -t fsprojects/ifsharp:local . 146 | 147 | # Compatibility 148 | 149 | IfSharp supports Jupyter 5.7.7 and works with both Python 2.X and Python 3.X 150 | 151 | If you need IPython 1.x or 2.x support please see the archived https://github.com/fsprojects/IfSharp/tree/ipython-archive 152 | 153 | # Automatic Installation 154 | 155 | Previous releases for the IPython notebook are here: [release repository](https://github.com/fsprojects/IfSharp/releases). 156 | Automatic installs for Jupyter may be provided in the future. Contributions are welcome! 157 | -------------------------------------------------------------------------------- /RELEASE_NOTES.md: -------------------------------------------------------------------------------- 1 | ## 3.0.2 (Released 2019-03-26) 2 | * Docker files being pushed 3 | * Assembly info generated correctly 4 | 5 | ## 3.0.0 beta2 (Released 2017-06-15) 6 | * Improved code completion 7 | * Updated F# Compiler services 8 | * More reliable expression evaluation 9 | * Paket 4 10 | * F# 4.1 11 | * Basic support for Google Charts 12 | * Reduced dependency chain supporting smaller Python installs 13 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # Starter pipeline 2 | # Start with a minimal pipeline that you can customize to build and deploy your code. 3 | # Add steps that build, run tests, deploy, and more: 4 | # https://aka.ms/yaml 5 | 6 | trigger: 7 | - master 8 | 9 | jobs: 10 | - job: Windows 11 | pool: 12 | vmImage: 'windows-2022' 13 | steps: 14 | - task: UseDotNet@2 15 | inputs: 16 | version: 3.1.100 17 | - script: | 18 | dotnet tool restore 19 | dotnet fake build --target All 20 | - job: macOS 21 | pool: 22 | vmImage: 'macOS-11' 23 | steps: 24 | - task: UseDotNet@2 25 | inputs: 26 | version: 3.1.100 27 | - bash: | 28 | dotnet tool restore 29 | dotnet fake build --target BuildNetCore 30 | - job: Linux 31 | pool: 32 | vmImage: 'ubuntu-20.04' 33 | steps: 34 | - task: UseDotNet@2 35 | inputs: 36 | version: 3.1.100 37 | - bash: | 38 | dotnet tool restore 39 | dotnet fake build --target BuildNetCore 40 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | fake.cmd build %* 2 | -------------------------------------------------------------------------------- /build.fsx: -------------------------------------------------------------------------------- 1 | 2 | #r "paket: groupref Build //" 3 | #load "./.fake/build.fsx/intellisense.fsx" 4 | 5 | open Fake.Core 6 | open Fake.DotNet 7 | open Fake.IO 8 | open Fake.IO.FileSystemOperators 9 | open Fake.IO.Globbing.Operators 10 | open Fake.Core.TargetOperators 11 | 12 | Target.create "Clean" (fun _ -> 13 | Shell.cleanDirs ["bin"; "temp"] 14 | ) 15 | 16 | Target.create "CleanDocs" (fun _ -> 17 | Shell.cleanDirs ["docs/output"] 18 | ) 19 | 20 | // -------------------------------------------------------------------------------------- 21 | // Build library & test project 22 | Target.create "BuildNetFramework" (fun _ -> 23 | //Need to restore for .NET Standard 24 | let workingDir = Path.getFullName "src/IfSharp.Kernel" 25 | let result = 26 | DotNet.exec (DotNet.Options.withWorkingDirectory workingDir) "restore" "" 27 | if result.ExitCode <> 0 then failwithf "'dotnet %s' failed in %s messages: %A" "restore" __SOURCE_DIRECTORY__ result.Messages 28 | 29 | let setParams (defaults:MSBuildParams) = 30 | { defaults with 31 | DisableInternalBinLog = true 32 | Verbosity = Some(MSBuildVerbosity.Detailed) 33 | Targets = ["Build"] 34 | Properties = 35 | [ 36 | "Optimize", "True" 37 | "DebugSymbols", "True" 38 | "Configuration", "Release" 39 | ] 40 | } 41 | MSBuild.build setParams "IfSharp.sln" 42 | ) 43 | 44 | Target.create "BuildNetCore" (fun _ -> 45 | let workingDir = Path.getFullName "src/IfSharpNetCore" 46 | let result = 47 | DotNet.exec (DotNet.Options.withWorkingDirectory __SOURCE_DIRECTORY__) "build" "IfSharpNetCore.sln" 48 | if result.ExitCode <> 0 then failwithf "'dotnet %s' failed in %s messages: %A" "build" workingDir result.Messages 49 | ) 50 | 51 | // -------------------------------------------------------------------------------------- 52 | // Run all targets by default. Invoke 'build ' to override 53 | 54 | Target.create "All" ignore 55 | 56 | "Clean" 57 | ==> "BuildNetCore" 58 | 59 | "Clean" 60 | ==> "BuildNetFramework" 61 | 62 | "BuildNetCore" 63 | ==> "All" 64 | 65 | "BuildNetFramework" 66 | ==> "All" 67 | 68 | 69 | Target.runOrDefault "All" 70 | -------------------------------------------------------------------------------- /build.fsx.lock: -------------------------------------------------------------------------------- 1 | STORAGE: NONE 2 | RESTRICTION: == netstandard2.0 3 | NUGET 4 | remote: https://api.nuget.org/v3/index.json 5 | FSharp.Core (4.7) 6 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | dotnet tool restore 3 | source fake.sh build "$@" -------------------------------------------------------------------------------- /fake.cmd: -------------------------------------------------------------------------------- 1 | dotnet tool restore 2 | dotnet fake %* -------------------------------------------------------------------------------- /fake.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu 4 | set -o pipefail 5 | 6 | dotnet tool restore 7 | dotnet fake "$@" -------------------------------------------------------------------------------- /ifsharpsetup.iss: -------------------------------------------------------------------------------- 1 | ; Script generated by the Inno Setup Script Wizard. 2 | ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! 3 | 4 | #define MyAppName "IFSharp" 5 | #define MyAppVersion "3.0" 6 | #define MyAppPublisher "F# Community" 7 | #define MyAppURL "https://github.com/fsprojects/IfSharp" 8 | #define MyAppExeName "ifsharp.exe" 9 | #define BaseDirectory "." 10 | 11 | [Setup] 12 | ; NOTE: The value of AppId uniquely identifies this application. 13 | ; Do not use the same AppId value in installers for other applications. 14 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) 15 | AppId={{4614F8B0-E5CA-4E5D-9F35-AB4D0ACEB3C0} 16 | AppName={#MyAppName} 17 | AppVersion={#MyAppVersion} 18 | ArchitecturesInstallIn64BitMode=x64 19 | ;AppVerName={#MyAppName} {#MyAppVersion} 20 | AppPublisher={#MyAppPublisher} 21 | AppPublisherURL={#MyAppURL} 22 | AppSupportURL={#MyAppURL} 23 | AppUpdatesURL={#MyAppURL} 24 | DefaultDirName={pf}\BayardRock\{#MyAppName} 25 | DefaultGroupName={#MyAppName} 26 | DisableProgramGroupPage=yes 27 | LicenseFile={#BaseDirectory}\LICENSE.txt 28 | OutputDir={#BaseDirectory}\Install 29 | OutputBaseFilename=setup 30 | Compression=lzma 31 | SolidCompression=yes 32 | 33 | [Languages] 34 | Name: "english"; MessagesFile: "compiler:Default.isl" 35 | 36 | [Tasks] 37 | Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked 38 | 39 | [Files] 40 | Source: "{#BaseDirectory}\bin\*"; DestDir: "{app}"; Flags: ignoreversion 41 | ; NOTE: Don't use "Flags: ignoreversion" on any shared system files 42 | 43 | [Icons] 44 | Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" 45 | Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon 46 | 47 | -------------------------------------------------------------------------------- /jupyter-kernel/kernel.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | 3 | var kernelSpecs = requirejs.s.contexts._.config.paths.kernelspecs; 4 | var staticFolder = kernelSpecs + "/ifsharp/static/"; 5 | 6 | var link = document.createElement("link"); 7 | link.type = "text/css"; 8 | link.rel = "stylesheet"; 9 | link.href = staticFolder + "custom/fsharp.css"; 10 | document.getElementsByTagName("head")[0].appendChild(link); 11 | 12 | var changedSinceTypecheck = true; 13 | var changedRecently = false; 14 | var kernelIdledSinceTypeCheck = false; 15 | var kernelIdledRecently = false; 16 | 17 | var onload = function () { 18 | 19 | var md = IPython.notebook.metadata; 20 | if (md.language) { 21 | console.log('language already defined and is :', md.language); 22 | } 23 | else { 24 | md.language = 'fsharp'; 25 | console.log('add metadata hint that language is fsharp...'); 26 | } 27 | 28 | IPython.CodeCell.options_default.cm_config.mode = 'fsharp'; 29 | 30 | // callback called by the end-user 31 | function updateMarkers(data) { 32 | // applies intellisense hooks onto all cells 33 | var cells = getCodeCells(); 34 | 35 | // clear old error marks 36 | cells.cells.forEach(function (cell) { 37 | cell.code_mirror.doc.getAllMarks().forEach(function (m) { 38 | if (m.className === 'br-errormarker') { 39 | m.clear(); 40 | } 41 | }); 42 | }); 43 | 44 | // apply new error marks 45 | data.forEach(function (err) { 46 | var editor = cells.cells[err.CellNumber].code_mirror; 47 | var from = { line: err.StartLine, ch: err.StartColumn }; 48 | var to = { line: err.EndLine, ch: err.EndColumn }; 49 | editor.doc.markText(from, to, { title: err.Message, className: 'br-errormarker' }); 50 | }); 51 | } 52 | 53 | function getCodeCells() { 54 | var results = { codes: [], cells: [], selectedCell: null, selectedIndex: 0 }; 55 | IPython.notebook.get_cells() 56 | .forEach(function (c) { 57 | if (c.cell_type === 'code') { 58 | if (c.selected === true) { 59 | results.selectedCell = c; 60 | results.selectedIndex = results.cells.length; 61 | } 62 | results.cells.push(c); 63 | results.codes.push(c.code_mirror.getValue()); 64 | } 65 | }); 66 | 67 | return results; 68 | } 69 | 70 | function intellisenseRequest(item) { 71 | var cells = getCodeCells(); 72 | var editor = cells.selectedCell != null ? cells.selectedCell.code_mirror : null; 73 | var cursor = editor != null ? editor.doc.getCursor() : { ch: 0, line: 0 }; 74 | var callbacks = { shell: {}, iopub: {} }; 75 | 76 | if (editor != null) { 77 | var line = editor.getLine(cursor.line); 78 | var isSlash = item.keyCode === 191 || item.keyCode === 220; 79 | var isQuote = item.keyCode === 222; 80 | 81 | var isLoadOrRef = line.indexOf('#load') === 0 82 | || line.indexOf('#r') === 0; 83 | 84 | var isStartLoadOrRef = line === '#load "' 85 | || line === '#r "' 86 | || line === '#load @"' 87 | || line === '#r @"'; 88 | 89 | if (isSlash && !isLoadOrRef) { 90 | return; 91 | } 92 | 93 | if (isQuote && !isStartLoadOrRef) { 94 | return; 95 | } 96 | } 97 | 98 | callbacks.shell.reply = function (msg) { 99 | if (editor != null && item.keyCode !== 0) { 100 | editor.intellisense.setDeclarations(msg.content.matches); 101 | editor.intellisense.setStartColumnIndex(msg.content.cursor_start); 102 | } 103 | }; 104 | 105 | callbacks.iopub.output = function (msg) { 106 | updateMarkers(msg.content.data.errors); 107 | }; 108 | 109 | var content = { 110 | text: JSON.stringify(cells.codes), 111 | line: '', 112 | block: JSON.stringify({ selectedIndex: cells.selectedIndex, ch: cursor.ch, line: cursor.line }), 113 | cursor_pos: cursor.ch 114 | }; 115 | 116 | IPython.notebook.kernel.send_shell_message("intellisense_request", content, callbacks, null, null); 117 | } 118 | 119 | //There are dependencies in the lazy loading 120 | require(['codemirror/addon/mode/loadmode'], function () { 121 | require([staticFolder + 'custom/webintellisense.js', staticFolder + 'custom/webintellisense-codemirror.js'], function () { 122 | // applies intellisense hooks onto a cell 123 | function applyIntellisense(cell) { 124 | if (cell.cell_type !== 'code') { return; } 125 | 126 | var editor = cell.code_mirror; 127 | if (editor.intellisense == null) { 128 | var intellisense = new CodeMirrorIntellisense(editor); 129 | editor.intellisense = intellisense; 130 | 131 | editor.on('changes', function (cm, changes) { 132 | changedSinceTypecheck = true; 133 | changedRecently = true; 134 | }); 135 | 136 | intellisense.addDeclarationTrigger({ keyCode: 190 }); // `.` 137 | intellisense.addDeclarationTrigger({ keyCode: 32, ctrlKey: true, preventDefault: true, type: 'down' }); // `ctrl+space` 138 | intellisense.addDeclarationTrigger({ keyCode: 191 }); // `/` 139 | intellisense.addDeclarationTrigger({ keyCode: 220 }); // `\` 140 | intellisense.addDeclarationTrigger({ keyCode: 222 }); // `"` 141 | intellisense.addDeclarationTrigger({ keyCode: 222, shiftKey: true }); // `"` 142 | intellisense.addMethodsTrigger({ keyCode: 57, shiftKey: true }); // `(` 143 | intellisense.addMethodsTrigger({ keyCode: 48, shiftKey: true });// `)` 144 | intellisense.onMethod(function (item) { }); 145 | intellisense.onDeclaration(intellisenseRequest); 146 | } 147 | } 148 | 149 | // applies intellisense hooks onto all cells 150 | IPython.notebook.get_cells().forEach(function (cell) { 151 | applyIntellisense(cell); 152 | }); 153 | 154 | // applies intellisense hooks onto cells that are selected 155 | $([IPython.events]).on('create.Cell', function (event, data) { 156 | data.cell.cm_config.mode = 'text/x-fsharp'; 157 | applyIntellisense(data.cell); 158 | }); 159 | 160 | $([IPython.events]).on('delete.Cell', function (event, data) { 161 | data.cell.code_mirror.intellisense.setDeclarations([]); 162 | }); 163 | 164 | $([IPython.events]).on('kernel_idle.Kernel', function (event, data) { 165 | kernelIdledSinceTypeCheck = true; 166 | kernelIdledRecently = true; 167 | }); 168 | 169 | 170 | 171 | window.setInterval(function () { 172 | if (!changedSinceTypecheck && !kernelIdledSinceTypeCheck) 173 | return; 174 | 175 | if (changedRecently || kernelIdledRecently) { 176 | changedRecently = false; 177 | kernelIdledRecently = false; 178 | return; 179 | } 180 | 181 | changedSinceTypecheck = false; 182 | changedRecently = false; 183 | kernelIdledSinceTypeCheck = false; 184 | kernelIdledRecently = false; 185 | intellisenseRequest({ keyCode: 0 }); 186 | }, 1000); 187 | 188 | }); 189 | }); 190 | } 191 | 192 | return { onload: onload } 193 | }) -------------------------------------------------------------------------------- /jupyter-kernel/logo-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsprojects/IfSharp/6bca367feb90d98fc83350764f56f965d2afcd91/jupyter-kernel/logo-32x32.png -------------------------------------------------------------------------------- /jupyter-kernel/logo-64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsprojects/IfSharp/6bca367feb90d98fc83350764f56f965d2afcd91/jupyter-kernel/logo-64x64.png -------------------------------------------------------------------------------- /jupyter-kernel/static/custom/fsharp.css: -------------------------------------------------------------------------------- 1 | th { 2 | background-color: #ececec; 3 | } 4 | 5 | .br-intellisense { 6 | min-width: 220px; 7 | max-height: 176px; 8 | min-height: 22px; 9 | z-index: 10; 10 | overflow: auto; 11 | position: absolute; 12 | background-color: white; 13 | border: 1px solid #E5C365; 14 | box-shadow: 2px 3px 5px rgba(0, 0, 0, .2); 15 | padding: 0; 16 | margin: 5px; 17 | display: none; 18 | -moz-user-select: none; 19 | -ms-user-select: none; 20 | -webkit-user-select: none; 21 | user-select: none; 22 | } 23 | 24 | .br-documentation { 25 | min-width: 200px; 26 | padding: 3px; 27 | overflow: auto; 28 | position: absolute; 29 | z-index: 10; 30 | background-color: #E7E8EC; 31 | border: 1px solid #CCCEDB; 32 | box-shadow: 2px 3px 5px rgba(0,0,0,.2); 33 | font-family: 'Segoe UI'; 34 | font-size: 10pt; 35 | white-space: pre-line; 36 | display: none; 37 | } 38 | 39 | .br-listlink { 40 | font-family: 'Segoe UI'; 41 | font-size: 10pt; 42 | list-style: none; 43 | cursor: pointer; 44 | border: 1px solid white; 45 | white-space: nowrap; 46 | overflow: hidden; 47 | } 48 | 49 | .br-listlink:hover { 50 | background-color: #FDF4BF; 51 | } 52 | 53 | .br-selected { 54 | background-color: #FDF4BF; 55 | border: 1px dotted black; 56 | } 57 | 58 | .br-icon { 59 | width: 16px; 60 | height: 16px; 61 | display: inline-block; 62 | vertical-align: text-top; 63 | margin: 2px; 64 | } 65 | 66 | .br-methods { 67 | min-width: 220px; 68 | min-height: 22px; 69 | z-index: 10; 70 | padding: 3px; 71 | overflow: auto; 72 | position: absolute; 73 | background-color: #E7E8EC; 74 | border: 1px solid #CCCEDB; 75 | margin: 5px; 76 | display: none; 77 | font-family: 'Segoe UI'; 78 | font-size: 10pt; 79 | } 80 | 81 | .br-methods-text { 82 | margin-left: 75px; 83 | } 84 | 85 | .br-methods-arrows { 86 | width: 75px; 87 | float: left; 88 | font-family: Calibri; 89 | font-weight: bold; 90 | -webkit-touch-callout: none; 91 | -webkit-user-select: none; 92 | -moz-user-select: none; 93 | -ms-user-select: none; 94 | user-select: none; 95 | } 96 | 97 | .br-methods-arrow { 98 | cursor: pointer; 99 | } 100 | 101 | .br-methods-arrow-text { 102 | font-weight: normal; 103 | margin-left: 2px; 104 | margin-right: 2px; 105 | } 106 | 107 | .br-tooltip { 108 | min-width: 220px; 109 | max-height: 176px; 110 | min-height: 22px; 111 | z-index: 10; 112 | position: absolute; 113 | background-color: #E7E8EC; 114 | border: 1px solid #CCCEDB; 115 | box-shadow: 2px 3px 5px rgba(0, 0, 0, .2); 116 | padding: 5px; 117 | margin: 5px; 118 | display: none; 119 | font-size: 12px; 120 | font-family: Monaco, Menlo, 'Ubuntu Mono', Consolas, source-code-pro, monospace; 121 | overflow: auto; 122 | } 123 | 124 | .br-errormarker { 125 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAQCAYAAAAxtt7zAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjExR/NCNwAAABdJREFUKFNjGNbgPxihAZggiiSEw8AAAMxEB/k37k01AAAAAElFTkSuQmCC); 126 | background-repeat: repeat-x; 127 | background-position: left bottom; 128 | margin-bottom: -1px; 129 | } 130 | 131 | .icon-glyph-72 { 132 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAARZJREFUeNpi/P//PwMlgBEIsImHQTEIrIJiDPDv3z+wCejYBIjXAbETEOtA2djUMYBcz4LFYCMg/gvEF4H4LRAH4fMCExYxLSB+BtVMECAb0AXE24FYHYjVoGw9KA3CMVB14ih8NH9ZAvFuKA3ix0HpCKg4KFyWALEbrjAwBWJQvN6B8hdB6UdADFJbC8SOyBrQDdAH4sdA/BpNXBCIWYG4AF8YiAKxKhBfw5ImaqGWCeMzQBOIeYD4NIgDTaHlQFwBxBZAzAbEYlC157DFSC007sWh/BwgvoEkD+ODsDeSJWBgCcRHgXgLgWjngWIGmAGgjPASygclnhQgfghK5kj4Lxr/P4wGAVDAGCILkpwbKc3OAAEGAOsaUbKinMktAAAAAElFTkSuQmCC) 133 | } 134 | .icon-glyph-74 { 135 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjExR/NCNwAAAQlJREFUOE+l0r9KwlEYxvGjFBFGRH8UvYZwscUGh5Aa3MVBG5vExcGpG3DKC2hrK5qCIAchFJqKtm6hm8i+j74/ORzObyiHj+d9Hw6PP/+4+ditxWXqPzFNPBjNsTupBSd4xBmObY7dSy24wj0OvCwqreAGoyCLCguGeA6UvbkN3Sske+wJqhjbqf3SzhaU63u5wzmiH6GHFxx5mZxiYlZ5rODWhHkDU+gXWuVhgd71FX0vE/0P3syFZQthQQ3vdjpXnysbWKZZZ8eblwW6aK7xiYLtXXzZ7O/SUOYXVDHDk+1pdsxiTwq+zQcqOMQ+9rCLHLaxhU1sIItMUlBCEXr0PP5WoJf/c+4X/GGBYJtXJyYAAAAASUVORK5CYII=) 136 | } 137 | .icon-glyph-102 { 138 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAqNJREFUeNqUU0tIVFEY/u5jxpmaEQwHAh+gNZoNvkjTUUYNRtLwtXERROuoli5KS2oTtq02hQRFpW2cnCDMQUe7SQuTyGKGlMTIBzHgiON4de7cezv/hTFd9Prg55xzz/995z/f/Q/X2dkJwgWbzxg5Dqc5oBF/gQ4EEkm8FlMf/LIHzWaJpi3e7keXv4XDiK6t4UR9PdRkEpHlZQiiCJPJBJPZjLd3LqXpOkTB5XIZAjH9AFY0B9K0LdPS5FPZfPh4eXltLcZ9PuQVFiIRjyOytARlexuqoiC3sunk1+nANlWQz6KKhf2HlgmLnl3kyM2uLa6oQHB4GJUejzF6mpqQZMRYNAplZwfrq4uReEI/KKqq6u7q6rrqcDhckdAE5C8BVNfVY6C/Hy0dHRj1+3GqsRHSyAjKmKimqvqn9++i89NjnwUer3hN09Lj8bhrYWEBs/57qKh2w/d8ELI1Cw8f3EddQwOCgQCKS0shBYMYDU5xdwfHx7YU/Zyq4bHITNG8Xq/hw7xNhm+gDzVnr8BZ046wNIThJ7fQ2taGNxMTOFTWjhqnG9L67bGPwEr2TghiMpnkWBXQmaX5VS1GENjVUMBEaO/lsz7kNZxH+pEqI484lLMoFBgCPCW7XxzDVFsIkiQhIyMDFosFZva7jla3GpECz/MkwKfWuwKTZ2ZpA263e1/D0Le9EARhv4CiKDwlfejtQXHvTczMzMBqte4SZFk21qmxpKQExNkVSCQSAlVQ1H3dOK2Uuf0nUC5x9goYV+gZysSN1lWEqYVZs5APhNTcZrMhJyfH8IA4tLexsfGrgmvN30HXdTqdvz2dKhTZeyDO5uYm5ubmILImMnHsCdIj+RdQLnEY2UEWcXa7/SJzNgv/AVZxJBaLjbLp2k8BBgCbzEoRe8NC/gAAAABJRU5ErkJggg==) 139 | } 140 | .icon-glyph-42 { 141 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAqNJREFUeNqUU0tIVFEY/u5jxpmaEQwHAh+gNZoNvkjTUUYNRtLwtXERROuoli5KS2oTtq02hQRFpW2cnCDMQUe7SQuTyGKGlMTIBzHgiON4de7cezv/hTFd9Prg55xzz/995z/f/Q/X2dkJwgWbzxg5Dqc5oBF/gQ4EEkm8FlMf/LIHzWaJpi3e7keXv4XDiK6t4UR9PdRkEpHlZQiiCJPJBJPZjLd3LqXpOkTB5XIZAjH9AFY0B9K0LdPS5FPZfPh4eXltLcZ9PuQVFiIRjyOytARlexuqoiC3sunk1+nANlWQz6KKhf2HlgmLnl3kyM2uLa6oQHB4GJUejzF6mpqQZMRYNAplZwfrq4uReEI/KKqq6u7q6rrqcDhckdAE5C8BVNfVY6C/Hy0dHRj1+3GqsRHSyAjKmKimqvqn9++i89NjnwUer3hN09Lj8bhrYWEBs/57qKh2w/d8ELI1Cw8f3EddQwOCgQCKS0shBYMYDU5xdwfHx7YU/Zyq4bHITNG8Xq/hw7xNhm+gDzVnr8BZ046wNIThJ7fQ2taGNxMTOFTWjhqnG9L67bGPwEr2TghiMpnkWBXQmaX5VS1GENjVUMBEaO/lsz7kNZxH+pEqI484lLMoFBgCPCW7XxzDVFsIkiQhIyMDFosFZva7jla3GpECz/MkwKfWuwKTZ2ZpA263e1/D0Le9EARhv4CiKDwlfejtQXHvTczMzMBqte4SZFk21qmxpKQExNkVSCQSAlVQ1H3dOK2Uuf0nUC5x9goYV+gZysSN1lWEqYVZs5APhNTcZrMhJyfH8IA4tLexsfGrgmvN30HXdTqdvz2dKhTZeyDO5uYm5ubmILImMnHsCdIj+RdQLnEY2UEWcXa7/SJzNgv/AVZxJBaLjbLp2k8BBgCbzEoRe8NC/gAAAABJRU5ErkJggg==) 142 | } 143 | .icon-glyph-6 { 144 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAqNJREFUeNqUU0tIVFEY/u5jxpmaEQwHAh+gNZoNvkjTUUYNRtLwtXERROuoli5KS2oTtq02hQRFpW2cnCDMQUe7SQuTyGKGlMTIBzHgiON4de7cezv/hTFd9Prg55xzz/995z/f/Q/X2dkJwgWbzxg5Dqc5oBF/gQ4EEkm8FlMf/LIHzWaJpi3e7keXv4XDiK6t4UR9PdRkEpHlZQiiCJPJBJPZjLd3LqXpOkTB5XIZAjH9AFY0B9K0LdPS5FPZfPh4eXltLcZ9PuQVFiIRjyOytARlexuqoiC3sunk1+nANlWQz6KKhf2HlgmLnl3kyM2uLa6oQHB4GJUejzF6mpqQZMRYNAplZwfrq4uReEI/KKqq6u7q6rrqcDhckdAE5C8BVNfVY6C/Hy0dHRj1+3GqsRHSyAjKmKimqvqn9++i89NjnwUer3hN09Lj8bhrYWEBs/57qKh2w/d8ELI1Cw8f3EddQwOCgQCKS0shBYMYDU5xdwfHx7YU/Zyq4bHITNG8Xq/hw7xNhm+gDzVnr8BZ046wNIThJ7fQ2taGNxMTOFTWjhqnG9L67bGPwEr2TghiMpnkWBXQmaX5VS1GENjVUMBEaO/lsz7kNZxH+pEqI484lLMoFBgCPCW7XxzDVFsIkiQhIyMDFosFZva7jla3GpECz/MkwKfWuwKTZ2ZpA263e1/D0Le9EARhv4CiKDwlfejtQXHvTczMzMBqte4SZFk21qmxpKQExNkVSCQSAlVQ1H3dOK2Uuf0nUC5x9goYV+gZysSN1lWEqYVZs5APhNTcZrMhJyfH8IA4tLexsfGrgmvN30HXdTqdvz2dKhTZeyDO5uYm5ubmILImMnHsCdIj+RdQLnEY2UEWcXa7/SJzNgv/AVZxJBaLjbLp2k8BBgCbzEoRe8NC/gAAAABJRU5ErkJggg==) 145 | } 146 | .icon-glyph-90 { 147 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABAElEQVR4Xs1PXctEQBgdvEmIkDtCiET4RX7y/JS5Vup5n9POblO763pPnc50PmYQv4dt29Z93xXrYXiH9tbb8TzP67IsiknQp2966HwcD8NQjeOomASdpulVxNnM0BUm2raNu66TTGKqvu/fXoGHTHckNgKoqiqu61oyiamapvn6n8jQ0V2JrSiKQjKJqcqyxPgW6KCrN/Lvui5BRMi03uM8T2FZFoyH5nkeZ1kmmcRUaZp+/Qpk6OiuxFYASZLEDMkkpoqi6O0SeMh0R2IjTIRhWAVBoJgE9X3/dQnOZoau+ATP81bXdRWToE/f9NARd3AcZ7VtW7EehndoD+Mfwz/GwWVuFIPZmAAAAABJRU5ErkJggg==) 148 | } 149 | .icon-glyph-84 { 150 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACKUlEQVR4XqWTX0hTcRTHP/e3TTevyxkURFiCg0DwRciaD0lLKoPMPwWZkkFFUL1IQdZDD/UUgpFGry2LsHrqHz2IMYgCFVJEJPMOUzNjMlFyOjd2T4sFiVd78QNfDgfO+XIezlcTETbEegbSSetooFhGO3wy+miPfGnNDksnntW7dqwgD2gxYv4m7/5rEB0Huw5oW4yXZ2dhSbEChRWMeN5Vb/l5GLkO0wGYaIPJdry1DzWjxfXjvwbhKxzAEQUtJbcbXBroTnCZKU2x8FNjJXaAFxAkDR/u4cyrnGN46BwkAGWj8GQSNMBZxVyUXxaDzCy1+ejXgSLsDhNbhinxRTQH8H2I4dt1UADo8DnQQWJq8ZDFQJmmYymuM9nZrWwOURp2kosJ9NJ6WABfr/B4voiJ92Mz1a/5ZjEwTUSmQ2TP9QGCUgoxk2wzxrgfa6LtOJw5cmPi47tTO1mFAkgmQc0Y5ER6cId70MN9eIxX8PQOby62MjQARQ11OwovST7AWhfgyDBxzg6CkMYFubZZmvPgSTfUlEBgnBBgs14gaKqgEA6mVF4MFV7682vI9OUS/AS2OLztAX9pQrmrI5ctr/wMBrvK9kqwsiIxWL0v0V9VHKVepPSmyO5mkZLmdPXfEsmqHRe9dsTzd3ftLNj8w88b74psbRDZfjqlxj813V9oF1GHe4PrZkEd6yrY5IqciMZC+HYtg8Y/BCILmeR4lsvmU3NAaMNx/g3wxfZdOoWSNAAAAABJRU5ErkJggg==) 151 | } 152 | .icon-glyph-0 { 153 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACKUlEQVR4XqWTX0hTcRTHP/e3TTevyxkURFiCg0DwRciaD0lLKoPMPwWZkkFFUL1IQdZDD/UUgpFGry2LsHrqHz2IMYgCFVJEJPMOUzNjMlFyOjd2T4sFiVd78QNfDgfO+XIezlcTETbEegbSSetooFhGO3wy+miPfGnNDksnntW7dqwgD2gxYv4m7/5rEB0Huw5oW4yXZ2dhSbEChRWMeN5Vb/l5GLkO0wGYaIPJdry1DzWjxfXjvwbhKxzAEQUtJbcbXBroTnCZKU2x8FNjJXaAFxAkDR/u4cyrnGN46BwkAGWj8GQSNMBZxVyUXxaDzCy1+ejXgSLsDhNbhinxRTQH8H2I4dt1UADo8DnQQWJq8ZDFQJmmYymuM9nZrWwOURp2kosJ9NJ6WABfr/B4voiJ92Mz1a/5ZjEwTUSmQ2TP9QGCUgoxk2wzxrgfa6LtOJw5cmPi47tTO1mFAkgmQc0Y5ER6cId70MN9eIxX8PQOby62MjQARQ11OwovST7AWhfgyDBxzg6CkMYFubZZmvPgSTfUlEBgnBBgs14gaKqgEA6mVF4MFV7682vI9OUS/AS2OLztAX9pQrmrI5ctr/wMBrvK9kqwsiIxWL0v0V9VHKVepPSmyO5mkZLmdPXfEsmqHRe9dsTzd3ftLNj8w88b74psbRDZfjqlxj813V9oF1GHe4PrZkEd6yrY5IqciMZC+HYtg8Y/BCILmeR4lsvmU3NAaMNx/g3wxfZdOoWSNAAAAABJRU5ErkJggg==) 154 | } 155 | .icon-glyph-48 { 156 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACKUlEQVR4XqWTX0hTcRTHP/e3TTevyxkURFiCg0DwRciaD0lLKoPMPwWZkkFFUL1IQdZDD/UUgpFGry2LsHrqHz2IMYgCFVJEJPMOUzNjMlFyOjd2T4sFiVd78QNfDgfO+XIezlcTETbEegbSSetooFhGO3wy+miPfGnNDksnntW7dqwgD2gxYv4m7/5rEB0Huw5oW4yXZ2dhSbEChRWMeN5Vb/l5GLkO0wGYaIPJdry1DzWjxfXjvwbhKxzAEQUtJbcbXBroTnCZKU2x8FNjJXaAFxAkDR/u4cyrnGN46BwkAGWj8GQSNMBZxVyUXxaDzCy1+ejXgSLsDhNbhinxRTQH8H2I4dt1UADo8DnQQWJq8ZDFQJmmYymuM9nZrWwOURp2kosJ9NJ6WABfr/B4voiJ92Mz1a/5ZjEwTUSmQ2TP9QGCUgoxk2wzxrgfa6LtOJw5cmPi47tTO1mFAkgmQc0Y5ER6cId70MN9eIxX8PQOby62MjQARQ11OwovST7AWhfgyDBxzg6CkMYFubZZmvPgSTfUlEBgnBBgs14gaKqgEA6mVF4MFV7682vI9OUS/AS2OLztAX9pQrmrI5ctr/wMBrvK9kqwsiIxWL0v0V9VHKVepPSmyO5mkZLmdPXfEsmqHRe9dsTzd3ftLNj8w88b74psbRDZfjqlxj813V9oF1GHe4PrZkEd6yrY5IqciMZC+HYtg8Y/BCILmeR4lsvmU3NAaMNx/g3wxfZdOoWSNAAAAABJRU5ErkJggg==) 157 | } 158 | .icon-glyph-12 { 159 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABp0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuMTFH80I3AAABCklEQVQ4T6XSPWpCQRSG4atEgigiiVHiGoKNNqZIkUILe7FQC4tUIU2KVG7AKlmAnZ1iJQSSIhAiWCl2bsFNeH3P9VwZhrlFtHiccz6Hz1/PG/rn2fViLk1MlMyuO5EFFUzxiDudXfciC54wxrWROUUVvOPDypzsggE+LSVjbkPuFcLd9Q6q+NZT9q6eLUgu38sINTg/wgu+cGNk4h4/6pi7CobKzhv4g/xCx9wukFf9xauRCfkfLFRds4Bd8IClnp7fC55700xmOTvGfCiQi6qPNQq6P2Ojs7mLhmRmQRVzzHSPklbBHhZs1Qpl5HCFLDJIIYlLJHCBOGJhQRG3kLeex/8KgoeT+d4euPiUmIoqyN4AAAAASUVORK5CYII=) 160 | } 161 | .icon-glyph-108 { 162 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACKUlEQVR4XqWTX0hTcRTHP/e3TTevyxkURFiCg0DwRciaD0lLKoPMPwWZkkFFUL1IQdZDD/UUgpFGry2LsHrqHz2IMYgCFVJEJPMOUzNjMlFyOjd2T4sFiVd78QNfDgfO+XIezlcTETbEegbSSetooFhGO3wy+miPfGnNDksnntW7dqwgD2gxYv4m7/5rEB0Huw5oW4yXZ2dhSbEChRWMeN5Vb/l5GLkO0wGYaIPJdry1DzWjxfXjvwbhKxzAEQUtJbcbXBroTnCZKU2x8FNjJXaAFxAkDR/u4cyrnGN46BwkAGWj8GQSNMBZxVyUXxaDzCy1+ejXgSLsDhNbhinxRTQH8H2I4dt1UADo8DnQQWJq8ZDFQJmmYymuM9nZrWwOURp2kosJ9NJ6WABfr/B4voiJ92Mz1a/5ZjEwTUSmQ2TP9QGCUgoxk2wzxrgfa6LtOJw5cmPi47tTO1mFAkgmQc0Y5ER6cId70MN9eIxX8PQOby62MjQARQ11OwovST7AWhfgyDBxzg6CkMYFubZZmvPgSTfUlEBgnBBgs14gaKqgEA6mVF4MFV7682vI9OUS/AS2OLztAX9pQrmrI5ctr/wMBrvK9kqwsiIxWL0v0V9VHKVepPSmyO5mkZLmdPXfEsmqHRe9dsTzd3ftLNj8w88b74psbRDZfjqlxj813V9oF1GHe4PrZkEd6yrY5IqciMZC+HYtg8Y/BCILmeR4lsvmU3NAaMNx/g3wxfZdOoWSNAAAAABJRU5ErkJggg==) 163 | } 164 | .icon-glyph-18 { 165 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAz0lEQVR4XqVTwQ2DMAz0Vd2hjEMX4M2cTEMnKGpCGcGVG9GTLSO16ikXk2Aup1MQVW0UMdqsfCb2vts8q9WdJ/kR67YJIRSA8a0JWMWRQK25gMp3qHU9cqDKyiwiSnm49dkFJYATTAVK5iAHcoEjBwA+acCININScwG1Ec5FYqKumQCDBAWRZvAM9wB71oALU5sYN7vuoqo+oOW+gA7ixwF9f5VpmpqmigzD4O+47aq0QRKthy/5LzjbzM3WUWQcR1edA+uOtBH7eHojbPoHL7yxpA/wfZSBAAAAAElFTkSuQmCC) 166 | } 167 | .icon-glyph-30 { 168 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACO0lEQVR4Xo2SS0hUURiAv3PunWFMMinNiijG3BQ9wIykh6skU2xji2gTSFEY1EJyYWHLqEURBaY9wGVBBC3KMsIEGUmLGi1RRs0YnPH9Gu80cx+nWVhckgG/xVkc+D5+zvmFUgoAIQShx8cPOY7VqWwLlu8RIKREaB6E1CiobhUAfz0dF0vxeOWWwr3kHLiEYxlgG0jPOqxEjJFn9bzujl7GxYqALpwKX+52knPfiY/eB+klc0cdU59eYSTMwStNvS38h8SFx6v2+HL8WIs/ENpavOuPYhtzLIR6KGvoOQUspJ0g9Kik0LchC9BRZhjpycSTtYuJwBuCo7Hb0dlEH0DagPHbrMrO86OSU+AkEPoaJgPNLA5Nsm+br26w8WCdkBpC0xFSAgh3AF04lRl5m3DsaaSeAcDGI7XklSgUFkItoZCMtTYxHom15wMA/74x1Fys8k9fwIr9AnMRx7FIHSAEUtNQShENfCUaWXpXXNtdk/KG3BMgpCDS9hzHtlFWkq0nGzDnO5DKxDQMJnuC9Idmmk/cCN4Chle8QcH5riKAu+f8xVWl/gdCgqZJzJhFpCNAR99cffW9gRZgLN0efAYoK8y+6cvNRTCFHU8y9rGdzv756yn5ITCbZg9cRZ3SjM27MWd/Ev7wlqtPhsrP3hlodMnpA8NP95+RQqTkMOG2F1xrGal4GZh+D8yQBh0XSUvVeDUYD3ZN7Lz4rRzoBUyAVQW8OodtRy2k5GPLsotVBPKrvxQB9mplgD9z7vSpojdyCgAAAABJRU5ErkJggg==) 169 | } 170 | 171 | .icon-glyph-1000 { 172 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAASklEQVR42mNkgIKGhob/DAQAUA0juhgjsgH19fU4NTc2NmI1hCQDQPIgGtkQkg2AsWGGkOwF9DAh2gBsBo4aMGoAbQwgWjdCDyMAjqlwEfGZXsQAAAAASUVORK5CYII=); 173 | } 174 | 175 | .icon-glyph-1001 { 176 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAoklEQVR4XsXTPQ6CQBCG4Q8ksTAbrb2BB6CioLT0Cl7Bxmt4Bc9gZwmJieEChsKCUkMFFT9hCJspiAVxGRKeevPObDZrEREkbAg5AJDfTwS2UNvbyjsfMKC/dXcFHVD+DjoWvPAvtb9YDn5waFB/kA5USYjs8YGJOok5wJauZxZ4x5O9AiOSBaguhYGqmHmDJv3CXm9GB45l9LzCjD4//29sAVazOELv0oQIAAAAAElFTkSuQmCC); 177 | } 178 | 179 | .cm-s-ipython span.cm-comment { color: #008000; } 180 | .cm-s-ipython span.cm-keyword { line-height: 1em; font-weight: bold; color: blue; } 181 | .cm-s-ipython span.cm-string { color: #B21543; } 182 | .cm-s-ipython span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; } 183 | .cm-s-ipython span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; } 184 | .cm-s-ipython span.cm-variable { color: black; } 185 | .cm-s-ipython span.cm-number, .cm-s-ipython span.cm-atom { color: #3a3; } 186 | .cm-s-ipython span.cm-meta {color: #555;} 187 | .cm-s-ipython span.cm-link { color: #3a3; } 188 | 189 | .cm-s-ipython .CodeMirror-activeline-background {background: #e8f2ff !important;} 190 | .cm-s-ipython .CodeMirror-matchingbracket {outline:1px solid grey; color:black !important;} 191 | 192 | .cm-s-ipython.CodeMirror { 193 | font-family: "Fira Code", Consolas, Monaco, Menlo, "Andale Mono", "lucida console", "Courier New", monospace !important; 194 | font-feature-settings: "calt" 1; 195 | box-shadow: inset 0 0 2px black; 196 | background: #f5f5f5; 197 | } 198 | 199 | .cm-s-ipython .CodeMirror-line { 200 | color: dimgray; 201 | } -------------------------------------------------------------------------------- /jupyter-kernel/static/custom/fsharp.js: -------------------------------------------------------------------------------- 1 | CodeMirror.defineMode('fsharp', function () { 2 | var words = { 3 | 'abstract': 'keyword', 4 | 'and': 'keyword', 5 | 'as': 'keyword', 6 | 'assert': 'keyword', 7 | 'base': 'keyword', 8 | 'begin': 'keyword', 9 | 'class': 'keyword', 10 | 'default': 'keyword', 11 | 'delegate': 'keyword', 12 | 'do': 'keyword', 13 | 'done': 'keyword', 14 | 'downcast': 'keyword', 15 | 'downto': 'keyword', 16 | 'elif': 'keyword', 17 | 'else': 'keyword', 18 | 'end': 'keyword', 19 | 'exception': 'keyword', 20 | 'extern': 'keyword', 21 | 'false': 'keyword', 22 | 'finally': 'keyword', 23 | 'for': 'keyword', 24 | 'fun': 'keyword', 25 | 'function': 'keyword', 26 | 'global': 'keyword', 27 | 'if': 'keyword', 28 | 'in': 'keyword', 29 | 'inherit': 'keyword', 30 | 'inline': 'keyword', 31 | 'interface': 'keyword', 32 | 'internal': 'keyword', 33 | 'lazy': 'keyword', 34 | 'let': 'keyword', 35 | 'let!': 'keyword', 36 | 'match': 'keyword', 37 | 'member': 'keyword', 38 | 'module': 'keyword', 39 | 'mutable': 'keyword', 40 | 'namespace': 'keyword', 41 | 'new': 'keyword', 42 | 'not': 'keyword', 43 | 'null': 'keyword', 44 | 'of': 'keyword', 45 | 'open': 'keyword', 46 | 'or': 'keyword', 47 | 'override': 'keyword', 48 | 'private': 'keyword', 49 | 'public': 'keyword', 50 | 'rec': 'keyword', 51 | 'return': 'keyword', 52 | 'return!': 'keyword', 53 | 'select': 'keyword', 54 | 'static': 'keyword', 55 | 'struct': 'keyword', 56 | 'then': 'keyword', 57 | 'to': 'keyword', 58 | 'true': 'keyword', 59 | 'try': 'keyword', 60 | 'type': 'keyword', 61 | 'upcast': 'keyword', 62 | 'use': 'keyword', 63 | 'use!': 'keyword', 64 | 'val': 'keyword', 65 | 'void': 'keyword', 66 | 'when': 'keyword', 67 | 'while': 'keyword', 68 | 'with': 'keyword', 69 | 'yield': 'keyword', 70 | 'yield!': 'keyword', 71 | '__SOURCE_DIRECTORY__': 'keyword', 72 | 'asr': 'keyword', 73 | 'land': 'keyword', 74 | 'lor': 'keyword', 75 | 'lsl': 'keyword', 76 | 'lsr': 'keyword', 77 | 'lxor': 'keyword', 78 | 'mod': 'keyword', 79 | 'sig': 'keyword', 80 | 'atomic': 'keyword', 81 | 'break': 'keyword', 82 | 'checked': 'keyword', 83 | 'component': 'keyword', 84 | 'const': 'keyword', 85 | 'constraint': 'keyword', 86 | 'constructor': 'keyword', 87 | 'continue': 'keyword', 88 | 'eager': 'keyword', 89 | 'event': 'keyword', 90 | 'external': 'keyword', 91 | 'fixed': 'keyword', 92 | 'functor': 'keyword', 93 | 'include': 'keyword', 94 | 'method': 'keyword', 95 | 'mixin': 'keyword', 96 | 'object': 'keyword', 97 | 'parallel': 'keyword', 98 | 'process': 'keyword', 99 | 'protected': 'keyword', 100 | 'pure': 'keyword', 101 | 'sealed': 'keyword', 102 | 'tailcall': 'keyword', 103 | 'trait': 'keyword', 104 | 'virtual': 'keyword', 105 | 'volatile': 'keyword' 106 | }; 107 | 108 | function tokenBase(stream, state) { 109 | var ch = stream.next(); 110 | 111 | if (ch === '"') { 112 | state.tokenize = tokenString; 113 | return state.tokenize(stream, state); 114 | } 115 | if (ch === '/') { 116 | if (stream.eat('/')) { 117 | stream.skipToEnd(); 118 | return 'comment'; 119 | } 120 | } 121 | if (ch === '(') { 122 | if (stream.eat('*')) { 123 | state.commentLevel++; 124 | state.tokenize = tokenComment; 125 | return state.tokenize(stream, state); 126 | } 127 | } 128 | if (ch === '~') { 129 | stream.eatWhile(/\w/); 130 | return 'variable-2'; 131 | } 132 | if (ch === '`') { 133 | stream.eatWhile(/\w/); 134 | return 'quote'; 135 | } 136 | if (/\d/.test(ch)) { 137 | stream.eatWhile(/[\d]/); 138 | if (stream.eat('.')) { 139 | stream.eatWhile(/[\d]/); 140 | } 141 | return 'number'; 142 | } 143 | if (/[+\-*&%=<>!?|]/.test(ch)) { 144 | return 'operator'; 145 | } 146 | stream.eatWhile(/\w/); 147 | var cur = stream.current(); 148 | return words[cur] || 'variable'; 149 | } 150 | 151 | function tokenString(stream, state) { 152 | var next, end = false, escaped = false; 153 | while ((next = stream.next()) != null) { 154 | if (next === '"' && !escaped) { 155 | end = true; 156 | break; 157 | } 158 | escaped = !escaped && next === '\\'; 159 | } 160 | if (end && !escaped) { 161 | state.tokenize = tokenBase; 162 | } 163 | return 'string'; 164 | } 165 | 166 | function tokenComment(stream, state) { 167 | var prev, next; 168 | while (state.commentLevel > 0 && (next = stream.next()) != null) { 169 | if (prev === '(' && next === '*') state.commentLevel++; 170 | if (prev === '*' && next === ')') state.commentLevel--; 171 | prev = next; 172 | } 173 | if (state.commentLevel <= 0) { 174 | state.tokenize = tokenBase; 175 | } 176 | return 'comment'; 177 | } 178 | 179 | return { 180 | startState: function () { return { tokenize: tokenBase, commentLevel: 0 }; }, 181 | token: function (stream, state) { 182 | if (stream.eatSpace()) return null; 183 | return state.tokenize(stream, state); 184 | }, 185 | 186 | blockCommentStart: "(*", 187 | blockCommentEnd: "*)", 188 | lineComment: '//' 189 | }; 190 | }); 191 | 192 | CodeMirror.defineMIME("text/x-fsharp", "fsharp"); -------------------------------------------------------------------------------- /jupyter-kernel/static/custom/webintellisense-codemirror.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This class provides intellisense for either a textarea or an inputbox. 3 | * Triggers can be added 4 | * 5 | * @param {string|HTMLElement} editor - The id of a textarea or inputbox or the actual element 6 | * @class CodeMirrorIntellisense 7 | */ 8 | var CodeMirrorIntellisense = function (editor) 9 | { 10 | var decls = new DeclarationsIntellisense(); 11 | var meths = new MethodsIntellisense(); 12 | var triggers = { upDecls: [], downDecls: [], upMeths: [], downMeths: [] }; 13 | var declarationsCallback = null; 14 | var methodsCallback = null; 15 | var autoCompleteStart = { lineIndex: 0, columnIndex: 0, replaceStart: 0 }; 16 | var triggered = false; 17 | 18 | function processTriggers(triggers, evt, callback) 19 | { 20 | for (var k in triggers) 21 | { 22 | var item = triggers[k]; 23 | var shiftKey = item.shiftKey || false; 24 | var ctrlKey = item.ctrlKey || false; 25 | var keyCode = item.keyCode || 0; 26 | var preventDefault = item.preventDefault || false; 27 | 28 | if (evt.keyCode === keyCode && evt.shiftKey === shiftKey && evt.ctrlKey === ctrlKey) 29 | { 30 | var cursor = editor.getCursor(); 31 | autoCompleteStart.columnIndex = cursor.ch; 32 | autoCompleteStart.lineIndex = cursor.line; 33 | callback(item); 34 | if (preventDefault) 35 | { 36 | evt.preventDefault(); 37 | evt.cancelBubble = true; 38 | } 39 | return true; 40 | } 41 | } 42 | return false; 43 | } 44 | 45 | function setEditor(e) 46 | { 47 | editor = e; 48 | editor.on('keyup', function (cm, evt) 49 | { 50 | if (decls.isVisible()) 51 | { 52 | decls.setFilter(getFilterText()); 53 | } 54 | 55 | if (!processTriggers(triggers.upDecls, evt, declarationsCallback)) 56 | { 57 | processTriggers(triggers.upMeths, evt, methodsCallback); 58 | } 59 | }); 60 | 61 | editor.on('keydown', function (cm, evt) 62 | { 63 | if (decls.isVisible()) 64 | { 65 | decls.handleKeyDown(evt); 66 | } 67 | 68 | if (!processTriggers(triggers.downDecls, evt, declarationsCallback)) 69 | { 70 | processTriggers(triggers.downMeths, evt, methodsCallback); 71 | } 72 | 73 | if (meths.isVisible()) 74 | { 75 | meths.handleKeyDown(evt); 76 | } 77 | }); 78 | 79 | editor.on('focus', function (cm, evt) 80 | { 81 | IPython.notebook.get_cells() 82 | .forEach(function (cell) { 83 | var intellisense = cell.code_mirror.intellisense 84 | 85 | if (typeof intellisense != "undefined") 86 | { 87 | intellisense.setDeclarations([]) 88 | } 89 | }); 90 | }); 91 | 92 | editor.on('cursorActivity', function (cm) 93 | { 94 | if (decls.isVisible()) 95 | { 96 | var cursor = editor.getCursor(); 97 | var pos = autoCompleteStart.replaceStart + autoCompleteStart.columnIndex; 98 | 99 | if (cursor.line !== autoCompleteStart.lineIndex || 100 | cursor.ch <= pos) 101 | { 102 | decls.setVisible(false); 103 | } 104 | else 105 | { 106 | decls.setFilter(getFilterText()); 107 | } 108 | } 109 | }); 110 | } 111 | 112 | // when the visiblity has changed for the declarations, set the position of the methods UI 113 | decls.onVisibleChanged(function (v) 114 | { 115 | if (v) 116 | { 117 | var coords = editor.cursorCoords(true, 'page'); 118 | decls.setPosition(coords.left, coords.bottom); 119 | } 120 | }); 121 | 122 | // when the visiblity has changed for the methods, set the position of the methods UI 123 | meths.onVisibleChanged(function (v) 124 | { 125 | if (v) 126 | { 127 | var coords = editor.cursorCoords(true, 'page'); 128 | meths.setPosition(coords.left, coords.bottom); 129 | } 130 | }); 131 | 132 | // when an item is chosen by the declarations UI, set the value. 133 | decls.onItemChosen(function (item) 134 | { 135 | var itemValue = item.value || item.name; 136 | var cursor = editor.getCursor(); 137 | var line = editor.getLine(autoCompleteStart.lineIndex); 138 | var pos = autoCompleteStart.replaceStart + autoCompleteStart.columnIndex; 139 | 140 | var startRange = { line: cursor.line, ch: pos }; 141 | var endRange = { line: cursor.line, ch: cursor.ch }; 142 | editor.replaceRange(itemValue, startRange, endRange); 143 | editor.setSelection({ line: cursor.line, ch: pos + itemValue.length }); 144 | decls.setVisible(false); 145 | editor.focus(); 146 | }); 147 | 148 | function addTrigger(trigger, methsOrDecls) 149 | { 150 | var type = trigger.type || 'up'; 151 | if (triggers[type + methsOrDecls]) 152 | { 153 | triggers[type + methsOrDecls].push(trigger); 154 | } 155 | } 156 | 157 | function addDeclarationTrigger(trigger) 158 | { 159 | addTrigger(trigger, 'Decls'); 160 | } 161 | 162 | function addMethodsTrigger(trigger) 163 | { 164 | addTrigger(trigger, 'Meths'); 165 | } 166 | 167 | function onDeclaration(callback) 168 | { 169 | declarationsCallback = callback; 170 | } 171 | 172 | function onMethod(callback) 173 | { 174 | methodsCallback = callback; 175 | } 176 | 177 | function getFilterText() 178 | { 179 | var cursor = editor.getCursor(); 180 | var line = editor.getLine(autoCompleteStart.lineIndex); 181 | return line.substring(autoCompleteStart.replaceStart + autoCompleteStart.columnIndex, cursor.ch); 182 | } 183 | 184 | // set the editor 185 | setEditor(editor); 186 | 187 | /** 188 | * Gets the declarations user interface 189 | * @returns {DeclarationsIntellisense} 190 | * @function getDecls 191 | */ 192 | this.getDecls = function () { return decls; }; 193 | 194 | /** 195 | * Gets the methods user interface 196 | * @returns {MethodsIntellisense} 197 | * @function getMeths 198 | */ 199 | this.getMeths = function () { return meths; }; 200 | 201 | /** 202 | * Adds a trigger to the list of triggers that can cause the declarations user interface 203 | * to popup. 204 | * @instance 205 | * @param {KeyTrigger} trigger - The trigger to add 206 | * @function addDeclarationTrigger 207 | */ 208 | this.addDeclarationTrigger = addDeclarationTrigger; 209 | 210 | /** 211 | * Adds a trigger to the list of triggers that can cause the methods user interface 212 | * to popup. 213 | * @param {KeyTrigger} trigger - The trigger to add 214 | * @function addMethodsTrigger 215 | */ 216 | this.addMethodsTrigger = addMethodsTrigger; 217 | 218 | /** 219 | * Sets a callback to invoke when a key is pressed that causes the declarations list to 220 | * popup. 221 | * @param {function} callback - The callback to set 222 | * @function onDeclaration 223 | */ 224 | this.onDeclaration = onDeclaration; 225 | 226 | /** 227 | * Sets a callback to invoke when a key is pressed that causes the methods list to 228 | * popup. 229 | * @param {function} callback - The callback to set 230 | * @function onMethod 231 | */ 232 | this.onMethod = onMethod; 233 | 234 | /** 235 | * Delegate for setting the methods to display to the user 236 | * @param {string[]} data - The methods to display 237 | * @function setMethods 238 | */ 239 | this.setMethods = function (data) { meths.setMethods(data); }; 240 | 241 | /** 242 | * Delegate for setting the declarations to display to the user 243 | * @param {DeclarationItem[]} data - The declarations to display 244 | * @function setDeclarations 245 | */ 246 | this.setDeclarations = function (data) { decls.setDeclarations(data); }; 247 | 248 | /** 249 | * Sets the starting location where filtering can occur. This is set when 250 | * a trigger happens that would cause the declarations list to show 251 | * @param {int} i - The index to set 252 | * @function setStartColumnIndex 253 | */ 254 | this.setStartColumnIndex = function (i) 255 | { 256 | autoCompleteStart.replaceStart = i; 257 | decls.setFilter(getFilterText()); 258 | }; 259 | 260 | /** 261 | * Gets the text after startColumnIndex but before caret offset. 262 | * @returns {int} 263 | * @function getFilterText 264 | */ 265 | this.getFilterText = getFilterText; 266 | }; -------------------------------------------------------------------------------- /nuget/FSharp.ProjectTemplate.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @project@ 5 | @build.number@ 6 | @authors@ 7 | @authors@ 8 | http://github.com/pblasucci/FSharp.ProjectScaffold/blob/master/LICENSE.txt 9 | http://pblasucci.github.com/FSharp.ProjectScaffold 10 | https://raw.github.com/fsharp/FSharp.ProjectScaffold/master/nuget/logo.png 11 | false 12 | @summary@ 13 | @description@ 14 | @releaseNotes@ 15 | Copyright 2013 16 | @tags@ 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /nuget/README.md: -------------------------------------------------------------------------------- 1 | This file is in the `nuget` directory. 2 | 3 | You should use this directory to store any artifacts required to produce a NuGet package for your project. 4 | This typically includes a `.nuspec` file and some `.ps1` scripts, for instance. 5 | Additionally, this example project includes a `.cmd` file suitable for manual deployment of packages to http://nuget.org. 6 | 7 | --- 8 | NOTE: 9 | 10 | This file is a placeholder, used to preserve directory structure in Git. 11 | 12 | This file does not need to be edited. 13 | -------------------------------------------------------------------------------- /nuget/publish.cmd: -------------------------------------------------------------------------------- 1 | @for %%f in (..\bin\*.nupkg) do @..\.nuget\NuGet.exe push %%f -------------------------------------------------------------------------------- /paket.dependencies: -------------------------------------------------------------------------------- 1 | version 5.249.2 2 | 3 | framework: net48 4 | source https://api.nuget.org/v3/index.json 5 | 6 | nuget FSharp.Compiler.Service ~> 37.0.0 7 | nuget FSharp.Compiler.Tools ~> 10.2.3 8 | nuget FSharp.Core = 5.0.2 9 | nuget AsyncIO >= 0.1.69 10 | nuget NetMQ 4.0.0.272-pre 11 | nuget Newtonsoft.Json ~> 13.0.1 12 | nuget FAKE >= 5.16.0 13 | nuget Paket.Core ~> 5.249.2 14 | nuget Trinet.Core.IO.Ntfs 15 | nuget Plotly.NET 2.0.0-preview.17 16 | nuget Plotly.NET.ImageExport 2.0.0-preview.17 17 | nuget System.Memory 4.5.4 18 | nuget Microsoft.Extensions.Logging 6.0.0 19 | 20 | group NETCORE 21 | 22 | framework: netstandard2.0, netcoreapp3.1 23 | source https://api.nuget.org/v3/index.json 24 | 25 | nuget FSharp.Compiler.Service ~> 37.0.0 26 | nuget FSharp.Compiler.Tools ~> 10.2.3 27 | nuget FSharp.Core = 5.0.2 28 | nuget AsyncIO >= 0.1.69 29 | nuget NetMQ 4.0.0.272-pre 30 | nuget Newtonsoft.Json ~> 13.0.1 31 | nuget FAKE >= 5.16.0 32 | nuget Paket.Core ~> 5.249.2 33 | nuget Trinet.Core.IO.Ntfs 34 | nuget Plotly.NET 2.0.0-preview.17 35 | nuget Plotly.NET.ImageExport 2.0.0-preview.17 36 | nuget System.Memory 4.5.4 37 | nuget Microsoft.Extensions.Logging 6.0.0 38 | 39 | group Build 40 | storage none 41 | source https://api.nuget.org/v3/index.json 42 | nuget Fake.DotNet.Cli 43 | nuget Fake.IO.FileSystem 44 | nuget Fake.Core.Target -------------------------------------------------------------------------------- /src/IfSharp.Kernel/App.fs: -------------------------------------------------------------------------------- 1 | namespace IfSharp.Kernel 2 | 3 | open System 4 | open System.Diagnostics 5 | open System.IO 6 | open System.Reflection 7 | open System.Text 8 | open System.Threading 9 | 10 | open Newtonsoft.Json 11 | open NetMQ 12 | 13 | open Microsoft.FSharp.Reflection 14 | 15 | 16 | 17 | module App = 18 | open System.Threading.Tasks 19 | 20 | let internal Black = "\u001B[0;30m" 21 | let internal Blue = "\u001B[0;34m" 22 | let internal Green = "\u001B[0;32m" 23 | let internal Cyan = "\u001B[0;36m" 24 | let internal Red = "\u001B[0;31m" 25 | let internal Purple = "\u001B[0;35m" 26 | let internal Brown = "\u001B[0;33m" 27 | let internal Gray = "\u001B[0;37m" 28 | let internal DarkGray = "\u001B[1;30m" 29 | let internal LightBlue = "\u001B[1;34m" 30 | let internal LightGreen = "\u001B[1;32m" 31 | let internal LightCyan = "\u001B[1;36m" 32 | let internal LightRed = "\u001B[1;31m" 33 | let internal LightPurple = "\u001B[1;35m" 34 | let internal Yellow = "\u001B[1;33m" 35 | let internal White = "\u001B[1;37m" 36 | let internal Reset = "\u001B[0m" 37 | 38 | let mutable Kernel : Option = None 39 | 40 | /// Public API for addDisplayPrinter 41 | let AddDisplayPrinter = Printers.addDisplayPrinter 42 | 43 | /// Convenience method for adding an fsi printer 44 | let AddFsiPrinter = FSharp.Compiler.Interactive.Shell.Settings.fsi.AddPrinter 45 | 46 | /// Global clear display function 47 | let Clear () = Kernel.Value.ClearDisplay() 48 | 49 | /// Global display function 50 | let Display (value : obj) = 51 | 52 | if value <> null then 53 | if sbPrint.Length > 0 then 54 | Kernel.Value.SendDisplayData("text/plain", sbPrint.ToString()) |> ignore 55 | sbPrint.Clear() |> ignore 56 | Kernel.Value.DisplayValue(value) 57 | 58 | /// Global help function 59 | let Help (value : obj) = 60 | 61 | let text = StringBuilder() 62 | 63 | let rec getTypeText (t : Type) = 64 | let text = StringBuilder(Blue) 65 | 66 | if FSharpType.IsTuple(t) then 67 | let args = FSharpType.GetTupleElements(t) 68 | let str:array = [| for a in args do yield getTypeText(a) |] 69 | text.Append(String.Join(" * ", str)) |> ignore 70 | 71 | else if t.IsGenericType then 72 | let args = t.GetGenericArguments() 73 | let str:array = [| for a in args do yield getTypeText(a) |] 74 | text.Append(t.Name) 75 | .Append("<") 76 | .Append(String.Join(" ", str)) 77 | .Append(">") 78 | |> ignore 79 | else 80 | text.Append(t.Name) |> ignore 81 | 82 | text.Append(Reset).ToString() 83 | 84 | let getPropertyText (p : PropertyInfo) = 85 | let text = StringBuilder() 86 | text.Append(p.Name) 87 | .Append(" -> ") 88 | .Append(getTypeText(p.PropertyType)) 89 | |> ignore 90 | 91 | text.ToString() 92 | 93 | let getParameterInfoText (p : ParameterInfo) = 94 | let sb = StringBuilder() 95 | if p.IsOptional then sb.Append("? ") |> ignore 96 | if p.IsOut then sb.Append("out ") |> ignore 97 | sb.Append(p.Name).Append(": ").Append(getTypeText(p.ParameterType)).Append(" ") |> ignore 98 | if p.HasDefaultValue then sb.Append("= ").Append(p.DefaultValue).Append(" ") |> ignore 99 | sb.ToString().Trim() 100 | 101 | let getMethodText (m : MethodInfo) = 102 | let sb = StringBuilder() 103 | sb.Append(m.Name).Append("(") |> ignore 104 | 105 | let pametersString = String.Join(", ", m.GetParameters() |> Seq.map(fun x -> getParameterInfoText(x))) 106 | sb.Append(pametersString) |> ignore 107 | 108 | sb.Append(") -> ").Append(getTypeText(m.ReturnType)) |> ignore 109 | sb.ToString() 110 | 111 | let props = 112 | value.GetType().GetProperties() 113 | |> Seq.sortBy (fun x -> x.Name) 114 | |> Seq.toArray 115 | 116 | let meths = 117 | value.GetType().GetMethods() 118 | |> Seq.filter (fun x -> x.Name.StartsWith("get_") = false) 119 | |> Seq.filter (fun x -> x.Name.StartsWith("set_") = false) 120 | |> Seq.sortBy (fun x -> x.Name) 121 | |> Seq.toArray 122 | 123 | // type information 124 | text.Append(Blue) 125 | .Append("Type: ") 126 | .AppendLine(value.GetType().FullName) 127 | .Append(Reset) |> ignore 128 | 129 | // output properties 130 | text.AppendLine() |> ignore 131 | text.Append(Red) 132 | .AppendLine("Properties") 133 | .Append(Reset) |> ignore 134 | 135 | props |> Seq.iter (fun x -> text.AppendLine(getPropertyText(x)) |> ignore) 136 | 137 | // output methods 138 | text.AppendLine() |> ignore 139 | text.Append(Red) 140 | .AppendLine("Methods") 141 | .Append(Reset) |> ignore 142 | 143 | meths |> Seq.iter (fun x -> text.AppendLine(getMethodText(x)) |> ignore) 144 | 145 | // add to the payload 146 | Kernel.Value.AddPayload(text.ToString()) 147 | 148 | /// Installs the ifsharp files if they do not exist 149 | let Install forceInstall (runtime : Config.Runtime) = 150 | 151 | let thisExecutablePath = Assembly.GetEntryAssembly().Location 152 | let kernelDir = Config.KernelDir 153 | let staticDir = Config.StaticDir 154 | let tempDir = Config.TempDir 155 | let customDir = Path.Combine(staticDir, "custom") 156 | 157 | let createDir(str) = 158 | if Directory.Exists(str) = false then 159 | Directory.CreateDirectory(str) |> ignore 160 | 161 | createDir kernelDir 162 | createDir staticDir 163 | createDir tempDir 164 | createDir customDir 165 | 166 | let allFiles = new System.Collections.Generic.List() 167 | let addFile fn = allFiles.Add(fn); fn 168 | let kernelFile = Path.Combine(kernelDir, "kernel.json") |> addFile 169 | let kjsFile = Path.Combine(kernelDir, "kernel.js") |> addFile 170 | let wjsFile = Path.Combine(customDir, "webintellisense.js") |> addFile 171 | let wcjsFile = Path.Combine(customDir, "webintellisense-codemirror.js") |> addFile 172 | let logo64File = Path.Combine(kernelDir, "logo-64x64.png") |> addFile 173 | let logo32File = Path.Combine(kernelDir, "logo-32x32.png") |> addFile 174 | let versionFile = Path.Combine(kernelDir, "version.txt") |> addFile 175 | let missingFiles = Seq.exists (fun fn -> File.Exists(fn) = false) allFiles 176 | 177 | let differentVersion = File.Exists(versionFile) && File.ReadAllText(versionFile) <> Config.Version 178 | 179 | if forceInstall then printfn "Force install required, performing install..." 180 | else if missingFiles then printfn "One or more files are missing, performing install..." 181 | else if differentVersion then printfn "Different version found, performing install..." 182 | 183 | if forceInstall || missingFiles || differentVersion then 184 | 185 | // write the version file 186 | File.WriteAllText(versionFile, Config.Version) 187 | 188 | let writeStream filePath (stream: unit -> Stream) = 189 | use f = File.Create filePath 190 | stream().CopyTo f 191 | f.Flush(true) 192 | 193 | // write fsharp css file 194 | let cssFile = Path.Combine(customDir, "fsharp.css") 195 | printfn "Saving fsharp css [%s]" cssFile 196 | writeStream cssFile IfSharpResources.fsharp_css 197 | 198 | // write kernel js file 199 | printfn "Saving kernel js [%s]" kjsFile 200 | writeStream kjsFile IfSharpResources.kernel_js 201 | 202 | // write webintellisense js file 203 | printfn "Saving webintellisense js [%s]" wjsFile 204 | writeStream wjsFile IfSharpResources.webintellisense_js 205 | 206 | // write webintellisense-codemirror js file 207 | printfn "Saving webintellisense-codemirror js [%s]" wcjsFile 208 | writeStream wcjsFile IfSharpResources.webintellisense_codemirror_js 209 | 210 | let jsonTemplate = """{ 211 | "display_name": "F#", 212 | "argv": ["mono", "%s", "{connection_file}"], 213 | "language": "fsharp" 214 | }""" 215 | 216 | // Make the Kernel info folder 217 | let code = 218 | match runtime with 219 | | Config.NetCore -> 220 | jsonTemplate.Replace("mono", "dotnet") 221 | | Config.NetFramework -> 222 | match Environment.OSVersion.Platform with 223 | | PlatformID.Win32Windows -> jsonTemplate.Replace("\"mono\",", "") 224 | | PlatformID.Win32NT -> jsonTemplate.Replace("\"mono\",", "") 225 | | _ -> jsonTemplate 226 | let code = code.Replace("%s", thisExecutablePath.Replace("\\","\/")) 227 | printfn "Saving custom kernel.json file [%s]" kernelFile 228 | File.WriteAllText(kernelFile, code) 229 | 230 | printfn "Saving kernel icon [%s]" logo64File 231 | writeStream logo64File IfSharpResources.ifsharp_64logo 232 | 233 | printfn "Saving kernel icon [%s]" logo32File 234 | writeStream logo32File IfSharpResources.ifsharp_32logo 235 | 236 | printfn "Installing dependencies via Paket" 237 | let dependencies = Paket.Dependencies.Locate(System.IO.Path.GetDirectoryName(thisExecutablePath)) 238 | dependencies.Install(false) 239 | 240 | /// Starts jupyter in the user's home directory 241 | let StartJupyter () = 242 | 243 | let userDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); 244 | 245 | printfn "Starting Jupyter..." 246 | let p = new Process() 247 | p.StartInfo.FileName <- "jupyter" 248 | p.StartInfo.Arguments <- "notebook" 249 | p.StartInfo.WorkingDirectory <- userDir 250 | 251 | // tell the user something bad happened 252 | 253 | try 254 | if p.Start() = false then failwith "Unable to start Jupyter, please install Jupyter and ensure it is on the path" 255 | with _ -> failwith "Unable to start Jupyter, please install Jupyter and ensure it is on the path" 256 | 257 | /// First argument must be an Jupyter connection file, blocks forever 258 | let Start (args : array) (runtime : Config.Runtime) = 259 | 260 | match args with 261 | | [||] -> 262 | Install true runtime 263 | StartJupyter() //Eventually Jupyter will call back in with the connection file 264 | 265 | | [|"--install"|] -> 266 | Install true runtime 267 | 268 | | _ -> 269 | // Verify kernel installation status 270 | Install false runtime 271 | 272 | // Clear the temporary folder 273 | try 274 | if Directory.Exists(Config.TempDir) then Directory.Delete(Config.TempDir, true) 275 | with exc -> Console.Out.Write(exc.ToString()) 276 | 277 | // adds the default display printers 278 | Printers.addDefaultDisplayPrinters() 279 | 280 | // get connection information 281 | let fileName = args.[0] 282 | let json = File.ReadAllText(fileName) 283 | let connectionInformation = JsonConvert.DeserializeObject(json) 284 | 285 | // start the kernel 286 | Kernel <- Some (IfSharpKernel(connectionInformation, runtime)) 287 | Kernel.Value.StartAsync() 288 | 289 | // block forever 290 | Thread.Sleep(Timeout.Infinite) 291 | -------------------------------------------------------------------------------- /src/IfSharp.Kernel/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | // Auto-Generated by FAKE; do not edit 2 | namespace System 3 | open System.Reflection 4 | 5 | [] 6 | [] 7 | [] 8 | [] 9 | //[] 10 | //[] 11 | do () 12 | 13 | module internal AssemblyVersionInformation = 14 | let [] AssemblyTitle = "IfSharp.Kernel" 15 | let [] AssemblyProduct = "IfSharp.Kernel" 16 | let [] AssemblyDescription = "A short summary of your project." 17 | let [] AssemblyVersion = "2017-06-15" 18 | let [] AssemblyFileVersion = "2017-06-15" 19 | -------------------------------------------------------------------------------- /src/IfSharp.Kernel/Config.fs: -------------------------------------------------------------------------------- 1 | module Config 2 | 3 | open System 4 | open System.IO 5 | 6 | type Runtime = 7 | | NetFramework 8 | | NetCore 9 | 10 | let ActualPlatform = 11 | match Environment.OSVersion.Platform with 12 | | PlatformID.Unix -> 13 | //Mono pretends MacOSX is Unix, undo this by heuristic 14 | if (Directory.Exists("/Applications") 15 | && Directory.Exists("/System") 16 | && Directory.Exists("/Users") 17 | && Directory.Exists("/Volumes")) 18 | then 19 | PlatformID.MacOSX 20 | else 21 | PlatformID.Unix 22 | | p -> p 23 | 24 | //http://jupyter-client.readthedocs.io/en/latest/kernels.html#kernel-specs 25 | let KernelDir = 26 | //let thisExecutable = System.Reflection.Assembly.GetEntryAssembly().Location 27 | let userDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); 28 | let appData = 29 | match ActualPlatform with 30 | | PlatformID.Win32Windows | PlatformID.Win32NT -> Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) 31 | | PlatformID.MacOSX -> Path.Combine(userDir, "Library") 32 | | PlatformID.Unix -> Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) // PlatformID.Unix 33 | | p -> failwithf "Unknown platform: %A" p 34 | let jupyterDir = 35 | match Environment.OSVersion.Platform with 36 | | PlatformID.Unix -> Path.Combine(appData, "jupyter") 37 | | _ -> Path.Combine(appData, "Jupyter") 38 | let kernelsDir = Path.Combine(jupyterDir, "kernels") 39 | let kernelDir = Path.Combine(kernelsDir, "ifsharp") 40 | kernelDir 41 | let StaticDir = Path.Combine(KernelDir, "static") 42 | let TempDir = Path.Combine(StaticDir, "temp") 43 | 44 | let Version = "1" -------------------------------------------------------------------------------- /src/IfSharp.Kernel/DirectivePreprocessor.fs: -------------------------------------------------------------------------------- 1 | namespace IfSharp.Kernel 2 | 3 | module DirectivePreprocessor = 4 | 5 | type Line = 6 | | HelpDirective 7 | | FSIOutputDirective 8 | | NugetDirective 9 | | Other 10 | 11 | let determineLineType (idx, (line:string)) = 12 | match line.ToLower() with 13 | | line when line.StartsWith "#n" -> NugetDirective 14 | | line when line.StartsWith "#help" -> HelpDirective 15 | | line when line.StartsWith "#fsioutput" -> FSIOutputDirective 16 | | _ -> Other 17 | 18 | /// Separates into map of directive types 19 | let partitionLines(lines : string[]) = 20 | lines 21 | |> Seq.mapi (fun (idx) (line) -> (idx, line)) 22 | |> Seq.groupBy determineLineType 23 | |> Map.ofSeq 24 | 25 | /// Parses a directive line. Example: #N "Deedle" 26 | let parseDirectiveLine (prefix : string) (line : string) = 27 | line.Substring(prefix.Length + 1).Trim().Trim('"') 28 | -------------------------------------------------------------------------------- /src/IfSharp.Kernel/Evaluation.fs: -------------------------------------------------------------------------------- 1 | namespace IfSharp.Kernel 2 | 3 | open System 4 | open System.IO 5 | open System.Text 6 | open FSharp.Compiler.SourceCodeServices 7 | open FSharp.Compiler.Interactive.Shell 8 | 9 | [] 10 | module Evaluation = 11 | open FSharp.Compiler 12 | 13 | type SimpleDeclaration = 14 | { 15 | Documentation: string 16 | Glyph: FSharpGlyph 17 | Name: string 18 | Value: string 19 | } 20 | 21 | type EvaluationResult = 22 | | ActualValue of FsiValue 23 | | BackupString of string 24 | | Empty 25 | 26 | /// Extend the `fsi` object with `fsi.AddHtmlPrinter` 27 | let addHtmlPrinter = """ 28 | module FsInteractiveService = 29 | let mutable htmlPrinters = new ResizeArray seq * string)>() 30 | let htmlPrinterParams = System.Collections.Generic.Dictionary() 31 | do htmlPrinterParams.["html-standalone-output"] <- false 32 | 33 | type FSharp.Compiler.Interactive.Shell.FsiEvaluationSession with 34 | member x.HtmlPrinterParameters = FsInteractiveService.htmlPrinterParams 35 | member x.AddHtmlPrinter<'T>(f:'T -> seq * string) = 36 | FsInteractiveService.htmlPrinters.Add(typeof<'T>, fun (value:obj) -> 37 | f (value :?> 'T))""" 38 | 39 | /// Start the F# interactive session with HAS_FSI_ADDHTMLPRINTER symbol defined 40 | let internal startSession () = 41 | let sbOut = new StringBuilder() 42 | let sbErr = new StringBuilder() 43 | let sbPrint = new StringBuilder() 44 | let inStream = new StringReader("") 45 | let outStream = new StringWriter(sbOut) 46 | let errStream = new StringWriter(sbErr) 47 | let printStream = new StringWriter(sbPrint) 48 | 49 | 50 | 51 | let fsiObj = FSharp.Compiler.Interactive.Shell.Settings.fsi 52 | // The following is a workaround for IfSharp github issue #143 53 | // Mono fails to handle tailcall in Fsi printing code, thus constraining the length of print on Mono 54 | // https://github.com/mono/mono/issues/8975 55 | if Type.GetType("Mono.Runtime") <> null then 56 | // Default PrintLength value of 100 triggers the issue when printing the array of size 12x100 57 | // Value of 50 "postpones" the issue. E.g. Issue is triggered on printing larger arrays of size 50x100 58 | // Value of 10 seems to work, arrays 1000x1000 are printed without the error, although truncated with ellipsis as expected 59 | // After the value is set to 10, effectively the sequences are truncated to 100 elements during printing . Maybe F# interactive issue 60 | fsiObj.PrintLength <- 10 61 | fsiObj.PrintDepth <- 10 62 | fsiObj.PrintWidth <- 10 63 | fsiObj.PrintSize <- 10 64 | let fsiConfig = FsiEvaluationSession.GetDefaultConfiguration(fsiObj, false) 65 | let args = [|"--noninteractive"; "--define:HAS_FSI_ADDHTMLPRINTER"; "--define:IFSHARP"; "--define:JUPYTER" |] 66 | let fsiSession = FsiEvaluationSession.Create(fsiConfig, args, inStream, outStream, errStream) 67 | 68 | // Load the `fsi` object from the right location of the `FSharp.Compiler.Interactive.Settings.dll` 69 | // assembly and add the `fsi.AddHtmlPrinter` extension method; then clean it from FSI output 70 | let origLength = sbOut.Length 71 | let fsiLocation = typeof.Assembly.Location 72 | let _, errors1 = fsiSession.EvalInteractionNonThrowing("#r @\"" + fsiLocation + "\"") 73 | let _, errors2 = fsiSession.EvalInteractionNonThrowing(addHtmlPrinter) 74 | sbOut.Remove(origLength, sbOut.Length-origLength) |> ignore 75 | 76 | // Get reference to the extra HTML printers registered inside the FSI session 77 | let extraPrinters = 78 | unbox seq * string)>> 79 | (fsiSession.EvalExpression("FsInteractiveService.htmlPrinters").Value.ReflectionValue) 80 | 81 | Console.SetOut(printStream) 82 | sbErr, sbOut, sbPrint, extraPrinters, fsiSession 83 | 84 | let internal fsiout = ref false 85 | let internal sbErr, sbOut, sbPrint, extraPrinters, fsiEval = startSession () 86 | 87 | /// Gets `it` only if `it` was printed to the console 88 | let GetLastExpression() = 89 | 90 | let lines = 91 | sbOut.ToString().Split('\r', '\n') 92 | |> Seq.filter (fun x -> x <> "") 93 | |> Seq.toArray 94 | 95 | let index = lines |> Seq.tryFindIndex (fun x -> x.StartsWith("val it :")) 96 | if index.IsSome then 97 | //We could display more of these errors but the errors may be confusing. Consider. 98 | try 99 | let result, _ = fsiEval.EvalExpressionNonThrowing("it") 100 | match result with 101 | | Choice1Of2 (Some value) -> ActualValue value 102 | | Choice1Of2 None -> Empty 103 | | Choice2Of2 (_:exn) -> BackupString lines.[index.Value] //backup to just the string for things that can't be evaluated: https://github.com/fsprojects/IfSharp/issues/153 104 | 105 | with _ -> Empty 106 | else 107 | Empty 108 | 109 | /// New way of getting the declarations 110 | let GetDeclarations (runtime : Config.Runtime) (source:Text.ISourceText, lineNumber, charIndex) = 111 | 112 | let scriptFileName = Path.Combine(Environment.CurrentDirectory, "script.fsx") 113 | 114 | let assumeDotNetFramework = 115 | match runtime with 116 | | Config.Runtime.NetCore -> false 117 | | Config.Runtime.NetFramework -> true 118 | 119 | let options, errors = 120 | fsiEval.InteractiveChecker.GetProjectOptionsFromScript( 121 | scriptFileName, source, assumeDotNetFramework = assumeDotNetFramework) 122 | |> Async.RunSynchronously 123 | 124 | // dotnet core is does not return System.Runtime.dll when assumeDotNetFramework is set 125 | // to false, add it here 126 | let options = 127 | match runtime with 128 | | Config.Runtime.NetCore -> 129 | let corelib = "System.Private.CoreLib.dll" 130 | let runtime = 131 | options.OtherOptions 132 | |> Array.find (fun v -> v.Contains(corelib)) 133 | |> (fun v -> v.Replace(corelib, "System.Runtime.dll")) 134 | let other = options.OtherOptions |> Array.append [|runtime|] 135 | { options with OtherOptions = other } 136 | | Config.Runtime.NetFramework -> options 137 | 138 | let (parseFileResults, checkFileAnswer) = 139 | fsiEval.InteractiveChecker.ParseAndCheckFileInProject(scriptFileName, 0, source, options) 140 | |> Async.RunSynchronously 141 | 142 | let checkFileResults = 143 | match checkFileAnswer with 144 | | FSharpCheckFileAnswer.Aborted -> failwith (sprintf "fsiEval.InteractiveChecker.ParseAndCheckFileInProject returned FSharpCheckFileAnswer.Aborted. %s:%d:%d" (source.ToString()) lineNumber charIndex) 145 | | FSharpCheckFileAnswer.Succeeded x -> x 146 | 147 | try 148 | //let lines = source.Split([| '\n' |]) 149 | //let line = lines.[lineNumber - 1] 150 | let line = source.GetLineString(lineNumber - 1) 151 | let preprocess = getPreprocessorIntellisense "." charIndex line 152 | match preprocess with 153 | | None -> 154 | match extractNames(line, charIndex) with 155 | | Some (names, startIdx) -> 156 | let filterString = line.Substring(startIdx, charIndex - startIdx) 157 | let getValue(str:string) = 158 | if str.Contains(" ") then "``" + str + "``" else str 159 | 160 | //https://github.com/fsharp/FSharp.Compiler.Service/issues/835 161 | //Particularly suggestion it should be folded into GetDeclarationListInfo, and perhaps we should move to the F# AST as well 162 | let partialName = QuickParse.GetPartialLongNameEx(line, charIndex-1) 163 | 164 | let decls = 165 | checkFileResults.GetDeclarationListInfo(Some parseFileResults, lineNumber, line, partialName) 166 | |> Async.RunSynchronously 167 | 168 | // get declarations for a location 169 | (*let decls = 170 | checkFileResults.GetDeclarationListInfo(Some(parseFileResults), lineNumber, charIndex, line, names, filterString, (fun _ -> [])) 171 | |> Async.RunSynchronously*) 172 | 173 | let items = 174 | decls.Items 175 | |> Array.filter (fun x -> x.Name.StartsWith(filterString, StringComparison.OrdinalIgnoreCase)) 176 | |> Array.map 177 | (fun x -> 178 | async { 179 | let! descriptionText = formatTip(x.DescriptionTextAsync, None) 180 | return { Documentation = descriptionText; Glyph = x.Glyph; Name = x.Name; Value = getValue x.Name } 181 | } 182 | 183 | ) 184 | |> Async.Parallel 185 | |> Async.RunSynchronously 186 | 187 | (items, checkFileResults, startIdx, filterString) 188 | | None -> 189 | ([||], checkFileResults, charIndex, "") 190 | | Some(x) -> 191 | 192 | let items = 193 | x.Matches 194 | |> Array.map (fun x -> { Documentation = matchToDocumentation x; Glyph = matchToGlyph x.MatchType; Name = x.Name; Value = x.Name }) 195 | 196 | (items, checkFileResults, x.FilterStartIndex, "") 197 | with _ -> 198 | ([||], checkFileResults, 0, "") 199 | -------------------------------------------------------------------------------- /src/IfSharp.Kernel/FsCompiler.fs: -------------------------------------------------------------------------------- 1 | namespace IfSharp.Kernel 2 | 3 | open System 4 | open System.Collections.Generic 5 | open System.Diagnostics 6 | open System.Linq 7 | open System.IO 8 | open System.Text 9 | open System.Reflection 10 | 11 | open FSharp.Compiler 12 | open FSharp.Compiler.SourceCodeServices 13 | 14 | [] 15 | module FsCompilerInternals = 16 | 17 | type PreprocessorMatchType = 18 | | Folder 19 | | File 20 | 21 | type PreprocessorMatch = 22 | { 23 | MatchType: PreprocessorMatchType 24 | Name: string 25 | } 26 | 27 | type Directive = 28 | | Load 29 | | Reference 30 | 31 | type PreprocessorMatches = 32 | { 33 | Directive: Directive 34 | Directory: string 35 | Filter: string 36 | Matches: PreprocessorMatch[] 37 | FilterStartIndex: int 38 | } 39 | 40 | type String with 41 | member this.Substring2(startIndex, endIndex) = 42 | this.Substring(startIndex, endIndex - startIndex) 43 | 44 | let matchToDocumentation (m:PreprocessorMatch) = 45 | match m.MatchType with 46 | | File -> "File: " + m.Name 47 | | Folder -> "Folder: " + m.Name 48 | 49 | let directiveToFileFilter d = 50 | match d with 51 | | Reference -> "*.dll" 52 | | Load -> "*.fsx" 53 | 54 | let matchToGlyph m = 55 | match m with 56 | | File -> FSharpGlyph.Variable //1000 57 | | Folder -> FSharpGlyph.Variable //1001 58 | 59 | /// Formats a comment into a string 60 | let buildFormatComment (xmlCommentRetriever: string * string -> string) cmt (sb: StringBuilder) = 61 | match cmt with 62 | | FSharpXmlDoc.Text(s) -> sb.AppendLine(s) |> ignore 63 | | FSharpXmlDoc.XmlDocFileSignature(file, signature) -> 64 | let comment = xmlCommentRetriever (file, signature) 65 | if (not (comment.Equals(null))) && comment.Length > 0 then sb.AppendLine(comment) |> ignore 66 | | FSharpXmlDoc.None -> () 67 | 68 | /// Converts a ToolTipElement into a string 69 | let buildFormatElement isSingle el (sb: StringBuilder) xmlCommentRetriever = 70 | 71 | match el with 72 | | FSharpToolTipElement.None -> () 73 | (*| FSharpToolTipElement.Single(it, comment) -> 74 | sb.AppendLine(it) |> buildFormatComment xmlCommentRetriever comment 75 | | FSharpToolTipElement.SingleParameter(it, comment, _) -> 76 | sb.AppendLine(it) |> buildFormatComment xmlCommentRetriever comment*) 77 | | FSharpToolTipElement.Group(items) -> 78 | let items, msg = 79 | if items.Length > 10 then 80 | (items |> Seq.take 10 |> List.ofSeq), 81 | sprintf " (+%d other overloads)" (items.Length - 10) 82 | else items, null 83 | if isSingle && items.Length > 1 then 84 | sb.AppendLine("Multiple overloads") |> ignore 85 | //for (it, comment) in items do 86 | for elementData in items do 87 | //sb.AppendLine elementData.MainDescription |> ignore 88 | sb.AppendLine(elementData.MainDescription) |> buildFormatComment xmlCommentRetriever elementData.XmlDoc 89 | if msg <> null then sb.AppendFormat(msg) |> ignore 90 | | FSharpToolTipElement.CompositionError(err) -> 91 | sb.Append("Composition error: " + err) |> ignore 92 | 93 | /// Formats a DataTipText into a string 94 | let formatTip (tipAsync, xmlCommentRetriever) = 95 | async{ 96 | let commentRetriever = defaultArg xmlCommentRetriever (fun _ -> "") 97 | let sb = new StringBuilder() 98 | let! tip = tipAsync 99 | match tip with 100 | | FSharpToolTipText.FSharpToolTipText([single]) -> buildFormatElement true single sb commentRetriever 101 | | FSharpToolTipText.FSharpToolTipText(its) -> for item in its do buildFormatElement false item sb commentRetriever 102 | return sb.ToString().Trim('\n', '\r') 103 | } 104 | 105 | /// Tries to figure out the names to pass to GetDeclarations or GetMethods. 106 | let extractNames (line, charIndex) = 107 | 108 | let sourceTok = FSharpSourceTokenizer([], Some "/home/test.fsx") 109 | let tokenizer = sourceTok.CreateLineTokenizer(line) 110 | let rec gatherTokens (tokenizer:FSharpLineTokenizer) state = 111 | seq { 112 | match tokenizer.ScanToken(state) with 113 | | Some tok, state -> 114 | yield tok 115 | yield! gatherTokens tokenizer state 116 | | None, state -> () 117 | } 118 | 119 | let invalidTokens = 120 | [| 121 | "IEEE64" 122 | "INT32_DOT_DOT" 123 | "INFIX_BAR_OP" 124 | "STRING_TEXT" 125 | "RARROW" 126 | |] 127 | 128 | 129 | let tokens = gatherTokens tokenizer FSharpTokenizerLexState.Initial |> Seq.toArray 130 | let idx = tokens |> Array.tryFindIndex(fun x -> charIndex >= x.LeftColumn && charIndex <= x.LeftColumn + x.FullMatchedLength) 131 | 132 | match idx with 133 | | Some(endIndex) -> 134 | 135 | let token = tokens.[endIndex] 136 | if invalidTokens.Contains(token.TokenName) then 137 | None 138 | else 139 | let idx = 140 | tokens.[0..endIndex] 141 | |> Array.rev 142 | |> Array.tryFindIndex (fun x -> x.TokenName <> "IDENT" && x.TokenName <> "DOT") 143 | 144 | let startIndex = 145 | match idx with 146 | | Some(x) -> endIndex - x 147 | | None -> 0 148 | 149 | let finalIndex = 150 | if token.TokenName = "IDENT" then 151 | endIndex - 1 152 | else 153 | endIndex 154 | 155 | let relevantTokens = 156 | tokens.[startIndex..finalIndex] 157 | |> Array.filter (fun x -> x.TokenName = "IDENT") 158 | |> Array.map (fun x -> line.Substring(x.LeftColumn, x.FullMatchedLength)) 159 | |> Array.map (fun x -> x.Trim([|'`'|])) 160 | 161 | let filterStartIndex = if finalIndex = -1 then tokens.[0].LeftColumn else tokens.[finalIndex].RightColumn + 1 162 | let lst = relevantTokens |> Seq.toList 163 | Some <| (lst, filterStartIndex) 164 | 165 | | None -> 166 | Some <| ([], 0) 167 | 168 | let getPreprocessorIntellisense baseDirectory charIndex (line:string) = 169 | 170 | let directive = 171 | if line.StartsWith "#load" then Some Load 172 | elif line.StartsWith "#r" then Some Reference 173 | else None 174 | 175 | match directive with 176 | | Some d -> 177 | let nextQuote = line.IndexOf('"') 178 | let firstQuote = line.LastIndexOf('"', charIndex - 1) 179 | 180 | // make sure we are inside quotes 181 | if firstQuote <> -1 && nextQuote <> -1 && firstQuote = nextQuote then 182 | 183 | let previousSlash = line.LastIndexOfAny([| '/'; '\\' |], charIndex - 1) 184 | 185 | let directory, filter, startIndex = 186 | if previousSlash <> -1 && previousSlash > firstQuote then 187 | let directory = line.Substring2(firstQuote + 1, previousSlash + 1) 188 | let filter = line.Substring2(previousSlash + 1, charIndex) 189 | if Path.IsPathRooted(directory) then 190 | directory, filter, previousSlash + 1 191 | else 192 | Path.Combine(baseDirectory, directory), filter, previousSlash + 1 193 | else 194 | baseDirectory, line.Substring2(firstQuote + 1, charIndex), firstQuote + 1 195 | 196 | let files = 197 | Directory.GetFiles(directory, directiveToFileFilter d) 198 | |> Array.map Path.GetFileName 199 | |> Array.map (fun x -> { MatchType = PreprocessorMatchType.File; Name = x }) 200 | 201 | let dirs = 202 | DirectoryInfo(directory).GetDirectories() 203 | |> Array.map (fun x -> x.Name) 204 | |> Array.map (fun x -> { MatchType = PreprocessorMatchType.Folder; Name = x }) 205 | 206 | { 207 | Matches = Array.append dirs files 208 | Directory = directory 209 | Filter = filter 210 | FilterStartIndex = startIndex 211 | Directive = d 212 | } |> Some 213 | 214 | else 215 | 216 | None 217 | 218 | | None -> None 219 | -------------------------------------------------------------------------------- /src/IfSharp.Kernel/Globals.fs: -------------------------------------------------------------------------------- 1 | namespace IfSharp.Kernel.Globals 2 | 3 | /// This module provides access to common types and functions so the user can get intellisense 4 | [] 5 | module Globals = 6 | 7 | type Util = IfSharp.Kernel.Util 8 | 9 | let Display = IfSharp.Kernel.App.Display 10 | 11 | let Help = IfSharp.Kernel.App.Help 12 | 13 | let Clear = IfSharp.Kernel.App.Clear -------------------------------------------------------------------------------- /src/IfSharp.Kernel/IfSharp.Kernel.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | x64 6 | 7 | 10 | 11 | 12 | 13 | 14 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/IfSharp.Kernel/IfSharpResources.fs: -------------------------------------------------------------------------------- 1 | namespace IfSharp.Kernel 2 | 3 | open System 4 | open System.Text 5 | open System.Reflection 6 | open System.IO 7 | 8 | module IfSharpResources = 9 | let private executingAssembly = Assembly.GetExecutingAssembly() 10 | 11 | let resources () = 12 | executingAssembly.GetManifestResourceNames() 13 | let streamFor resource = 14 | let resourceName = sprintf "IfSharp.Kernel.%s" resource 15 | let s = executingAssembly.GetManifestResourceStream(resourceName) 16 | if isNull s 17 | then failwithf "could not find stream for %s. Available names are:\n%s" resourceName (resources() |> String.concat "\n\t") 18 | else s 19 | 20 | let getString (stream: Stream) = 21 | use s = stream 22 | use reader = new StreamReader(s) 23 | reader.ReadToEnd() 24 | 25 | let kernel_js() = streamFor "kernel.js" 26 | let fsharp_css() = streamFor "static.custom.fsharp.css" 27 | let webintellisense_js() = streamFor "static.custom.webintellisense.js" 28 | let webintellisense_codemirror_js() = streamFor "static.custom.webintellisense-codemirror.js" 29 | let ifsharp_64logo() = streamFor "logo-32x32.png" 30 | let ifsharp_32logo() = streamFor "logo-64x64.png" -------------------------------------------------------------------------------- /src/IfSharp.Kernel/IfSharpResources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\..\jupyter-kernel\kernel.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 123 | 124 | 125 | ..\..\jupyter-kernel\static\custom\fsharp.css;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 126 | 127 | 128 | ..\..\jupyter-kernel\logo-32x32.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 129 | 130 | 131 | ..\..\jupyter-kernel\logo-64x64.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 132 | 133 | 134 | ..\..\jupyter-kernel\static\custom\webintellisense.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 135 | 136 | 137 | ..\..\jupyter-kernel\static\custom\webintellisense-codemirror.js;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 138 | 139 | -------------------------------------------------------------------------------- /src/IfSharp.Kernel/Include.fsx: -------------------------------------------------------------------------------- 1 | // include directory, this will be replaced by the kernel 2 | #I "{0}" 3 | 4 | // load base dlls 5 | #r "IfSharp.Kernel.dll" 6 | #r "NetMQ.dll" 7 | 8 | // open the global functions and methods 9 | open IfSharp.Kernel 10 | open IfSharp.Kernel.Globals 11 | -------------------------------------------------------------------------------- /src/IfSharp.Kernel/MainTypes.fs: -------------------------------------------------------------------------------- 1 | namespace IfSharp.Kernel 2 | 3 | open System.Collections.Generic 4 | 5 | //http://jupyter-client.readthedocs.io/en/latest/kernels.html#connection-files 6 | type ConnectionInformation = 7 | { 8 | stdin_port: int; 9 | ip: string; 10 | control_port: int; 11 | hb_port: int; 12 | signature_scheme: string; 13 | key: string; 14 | shell_port: int; 15 | transport: string; 16 | iopub_port: int; 17 | } 18 | 19 | type IntellisenseItem = 20 | { 21 | glyph: FSharp.Compiler.SourceCodeServices.FSharpGlyph 22 | name: string 23 | documentation: string 24 | value: string 25 | } -------------------------------------------------------------------------------- /src/IfSharp.Kernel/NuGetManager.fs: -------------------------------------------------------------------------------- 1 | namespace IfSharp.Kernel 2 | 3 | open System 4 | open System.Collections.Generic 5 | open System.IO 6 | open System.Text 7 | open System.Reflection 8 | open FSharp.Compiler 9 | 10 | /// Assembly information 11 | type AssemblyInfo = { FileName : string; GuessedVersion : string; } 12 | 13 | /// Wrapper for ErrorInfo 14 | type CustomErrorInfo = 15 | { 16 | FileName : string 17 | StartLine : int 18 | StartColumn : int 19 | EndLine : int 20 | EndColumn : int 21 | Message : string 22 | Severity : string 23 | Subcategory : string 24 | CellNumber : int 25 | } 26 | static member From(fileName, startLine, startColumn, endLine, endColumn, message, severity, subcategory) = 27 | { 28 | FileName = fileName 29 | StartLine = startLine 30 | StartColumn = startColumn 31 | EndLine = endLine 32 | EndColumn = endColumn 33 | Message = message 34 | Severity = severity 35 | Subcategory = subcategory 36 | CellNumber = 0 37 | } 38 | static member From(e : FSharp.Compiler.SourceCodeServices.FSharpErrorInfo) = 39 | let severityString = match e.Severity with FSharp.Compiler.SourceCodeServices.FSharpErrorSeverity.Error -> "Error" | _ -> "Warning" 40 | { 41 | FileName = e.FileName 42 | StartLine = e.StartLineAlternate 43 | StartColumn = e.StartColumn 44 | EndLine = e.EndLineAlternate 45 | EndColumn = e.EndColumn 46 | Message = e.Message 47 | Severity = severityString 48 | Subcategory = e.Subcategory 49 | CellNumber = 0 50 | } 51 | 52 | /// The results from preprocessing some code 53 | type PreprocessResults = 54 | { 55 | OriginalLines : string[]; 56 | HelpLines : string[]; 57 | FsiOutputLines : string[]; 58 | NuGetLines : string[]; 59 | FilteredLines : string[]; 60 | Errors: CustomErrorInfo[]; 61 | } 62 | 63 | type VersionWithType = 64 | { 65 | ReleaseType : string; 66 | Version : Version; 67 | } 68 | 69 | /// The NuGetManager class contains methods for downloading nuget packages and such 70 | type NuGetManager (executingDirectory : string) = 71 | 72 | let syncObject = Object() 73 | let packagesDir = Path.Combine(executingDirectory, "packages") 74 | 75 | // events from the NuGet.exe 76 | let errDataReceivedEvent = Event<_>() 77 | let outDataReceivedEvent = Event<_>() 78 | 79 | /// The directory for the packages 80 | member this.PackagesDir = packagesDir 81 | 82 | /// This event is called whenever a line is written to the error writer 83 | [] 84 | member this.StdErrDataReceived = errDataReceivedEvent.Publish 85 | 86 | /// This event is called whenever a line is written to the error writer 87 | [] 88 | member this.StdOutDataReceived = outDataReceivedEvent.Publish 89 | 90 | /// Parses a 'nuget line'. Example #N "[/[/pre]]". 91 | /// Returns a tuple with the name of the package, the version, and if 92 | /// prerelease should be used or not. 93 | member this.ParseNugetLine (line : string) = 94 | 95 | let contents = DirectivePreprocessor.parseDirectiveLine "#N" line 96 | if contents.Contains("/") then 97 | let splits = contents.Split([| '/' |]) 98 | if splits.Length > 2 then 99 | (splits.[0], Some splits.[1], true) 100 | else 101 | (splits.[0], Some splits.[1], false) 102 | else 103 | (contents, None, false) 104 | 105 | /// Preprocesses the specified source string 106 | member this.Preprocess (source : string) = 107 | 108 | // split the source code into lines, then get the nuget lines 109 | let lines = source.Split('\n') 110 | let linesSplit = DirectivePreprocessor.partitionLines lines 111 | 112 | let orEmpty key = let opt = Map.tryFind key linesSplit 113 | if opt.IsSome then opt.Value else Seq.empty 114 | 115 | let helpLines = DirectivePreprocessor.Line.HelpDirective |> orEmpty 116 | let fsiOutputLines = DirectivePreprocessor.Line.FSIOutputDirective |> orEmpty 117 | let nugetLines = DirectivePreprocessor.Line.NugetDirective |> orEmpty 118 | let otherLines = DirectivePreprocessor.Line.Other |> orEmpty 119 | 120 | //NuGet broke, we've replaced it with Paket: https://github.com/fsprojects/IfSharp/issues/106 121 | 122 | { 123 | OriginalLines = lines; 124 | HelpLines = helpLines |> Seq.map(fun (_, line) -> line) |> Seq.toArray; 125 | FsiOutputLines = fsiOutputLines |> Seq.map(fun (_, line) -> line) |> Seq.toArray; 126 | NuGetLines = nugetLines |> Seq.map(fun (_, line) -> line) |> Seq.toArray; 127 | FilteredLines = otherLines |> Seq.map(fun (_, line) -> line) |> Seq.toArray; 128 | Errors = Array.empty //errors; 129 | } 130 | -------------------------------------------------------------------------------- /src/IfSharp.Kernel/Printers.fs: -------------------------------------------------------------------------------- 1 | namespace IfSharp.Kernel 2 | 3 | open System 4 | open System.Text 5 | open System.Web 6 | 7 | type SendExecutionResultType = string -> (string * obj) list -> string -> unit 8 | type SendDisplayDataType = string -> obj -> string -> string -> unit 9 | 10 | type IAsyncPrinter = 11 | interface 12 | /// Whether the printer is capable of printing the object 13 | abstract member CanPrint: obj -> bool 14 | /// Print the project in asynchronous manner (possible doing some async computations) 15 | /// what to print -> is the print is execution_result -> send results callback -> send dispaly callback 16 | abstract member Print: obj -> bool -> SendExecutionResultType -> SendDisplayDataType -> unit 17 | end 18 | 19 | module Printers = 20 | 21 | let mutable internal displayPrinters : list BinaryOutput)> = [] 22 | let mutable internal asyncPrinters : list = [] //(printer * its priority). Capable printer with higher priority is selected for printing 23 | 24 | /// Convenience method for encoding a string within HTML 25 | let internal htmlEncode(str) = HttpUtility.HtmlEncode(str) 26 | 27 | /// Adds a custom display printer for extensibility 28 | let addDisplayPrinter(printer : 'T -> BinaryOutput) = 29 | displayPrinters <- (typeof<'T>, (fun (x:obj) -> printer (unbox x))) :: displayPrinters 30 | 31 | /// Adds a custom async display printer for extensibility 32 | /// Priority affects the cases where several printers are capabale of printing the save value. 33 | /// The printer with higher priority is selected 34 | let addAsyncDisplayPrinter(printer:IAsyncPrinter, priority: int) = 35 | let printers = List.filter (fun entry -> let p,_ = entry in p <> printer) asyncPrinters //unregister if previously registered 36 | asyncPrinters <- (printer,priority) :: printers 37 | 38 | /// Removes all registered async diaplay printers 39 | let clearDisplayPrinters() = 40 | asyncPrinters <- List.empty 41 | 42 | /// Default display printer 43 | let defaultDisplayPrinter(x) = 44 | { ContentType = "text/plain"; Data = sprintf "%A" x } 45 | 46 | //https://technet.microsoft.com/en-us/ee353649(v=vs.85) 47 | let mapToFSharpAliases fullType name = 48 | //Attempt to use more standard F# types in signature 49 | match fullType with 50 | //| array<'T> -> "" 51 | | _ when fullType = typeof -> "bigint" 52 | | _ when fullType = typeof -> "bool" 53 | | _ when fullType = typeof -> "byte" 54 | | _ when fullType = typeof -> "char" 55 | | _ when fullType = typeof -> "decimal" 56 | | _ when fullType = typeof -> "double" 57 | | _ when fullType = typeof -> "exn" 58 | | _ when fullType = typeof -> "single" 59 | //| "Format<'Printer,'State,'Residue,'Result,'Tuple> Type of a formatting expression. 60 | //| "Format<'Printer,'State,'Residue,'Result> Type of a formatting expression. 61 | | _ when fullType = typeof -> "int16" 62 | | _ when fullType = typeof -> "int" 63 | | _ when fullType = typeof -> "int64" 64 | | _ when fullType = typeof -> "nativeint" 65 | | _ when fullType = typeof -> "obj" 66 | | _ when fullType = typeof -> "sbyte" 67 | | _ when fullType = typeof -> "single" 68 | | _ when fullType = typeof -> "string" 69 | | _ when fullType = typeof -> "uint16" 70 | | _ when fullType = typeof -> "uint32" 71 | | _ when fullType = typeof -> "uint64" 72 | | _ when fullType = typeof -> "uint8" 73 | | _ when fullType = typeof -> "unativeint" 74 | //Unit 75 | | _ -> name 76 | 77 | let rec possiblyAFuncAsString(p) = 78 | if FSharp.Reflection.FSharpType.IsFunction p then 79 | let fromType, toType = FSharp.Reflection.FSharpType.GetFunctionElements p 80 | sprintf "(%s -> %s)" (possiblyAFuncAsString fromType) (possiblyAFuncAsString toType) 81 | else 82 | mapToFSharpAliases p p.Name 83 | 84 | let functionPrinter(func:obj) = 85 | let funcArguments = possiblyAFuncAsString (func.GetType()) 86 | { ContentType = "text/plain"; Data = sprintf "%A : %s" func funcArguments } 87 | 88 | let tryFindAsyncPrinter(objToPrint:obj)= 89 | asyncPrinters 90 | |> Seq.filter (fun entry -> let (p:IAsyncPrinter),_ = entry in p.CanPrint objToPrint) //only capable 91 | |> Seq.sortByDescending (fun entry -> let _,priority = entry in priority) //sorted by priority desc 92 | |> Seq.map (fun entry -> let printer,_ = entry in printer) // filtering out priority data 93 | |> Seq.tryHead 94 | 95 | /// Finds a display printer based off of the type 96 | let findDisplayPrinter(findType) = 97 | // Get printers that were registered using `fsi.AddHtmlPrinter` and turn them 98 | // into printers expected here (just contactenate all """ } 148 | 149 | static member Base64 (bytes:seq, contentType:string) = 150 | let base64 = Convert.ToBase64String(Array.ofSeq bytes) 151 | let data = "data:"+contentType+";base64,"+base64 152 | data 153 | 154 | /// Loads a local image from disk and wraps a BinaryOutput around the image data. 155 | static member Image (fileName:string) = 156 | Util.Image (File.ReadAllBytes(fileName)) 157 | 158 | 159 | static member CreatePublicFile (name:string) (content:byte[]) = 160 | try 161 | if Directory.Exists(Config.TempDir) = false then 162 | Directory.CreateDirectory(Config.TempDir) |> ignore; 163 | let path = Path.Combine(Config.TempDir,name) 164 | File.WriteAllBytes(path, content) 165 | "/static/temp/"+name 166 | with exc -> 167 | exc.ToString() 168 | 169 | static member MoveSvg (svg:string) (delta:float*float) = 170 | let (dx,dy) = delta 171 | let doc = XElement.Parse(svg) 172 | let width = match Seq.tryFind (fun (xa:XAttribute) -> xa.Name.LocalName="width") (doc.Attributes()) with None -> 0. | Some xa -> float xa.Value 173 | let height = match Seq.tryFind (fun (xa:XAttribute) -> xa.Name.LocalName="height") (doc.Attributes()) with None -> 0. | Some xa -> float xa.Value 174 | let width = Math.Max(width, width + dx) 175 | let height = Math.Max(height, height + dy) 176 | doc.SetAttributeValue(XName.Get("width"), width) 177 | doc.SetAttributeValue(XName.Get("height"), height) 178 | let gnode = new XElement(XName.Get("g")) 179 | gnode.SetAttributeValue(XName.Get("transform"), "translate("+(string dx)+","+(string dy)+")") 180 | let objects = doc.Elements() |> Array.ofSeq; 181 | doc.RemoveNodes() 182 | gnode.Add(objects) 183 | doc.Add(gnode) 184 | let svg = doc.ToString() 185 | svg 186 | 187 | static member MergeSvg (svg1:string) (svg2:string) = 188 | let doc1 = XElement.Parse(svg1) 189 | let doc2 = XElement.Parse(svg2) 190 | let width1 = match Seq.tryFind (fun (xa:XAttribute) -> xa.Name.LocalName="width") (doc1.Attributes()) with None -> 0. | Some xa -> float xa.Value 191 | let height1 = match Seq.tryFind (fun (xa:XAttribute) -> xa.Name.LocalName="height") (doc1.Attributes()) with None -> 0. | Some xa -> float xa.Value 192 | let width2 = match Seq.tryFind (fun (xa:XAttribute) -> xa.Name.LocalName="width") (doc2.Attributes()) with None -> 0. | Some xa -> float xa.Value 193 | let height2 = match Seq.tryFind (fun (xa:XAttribute) -> xa.Name.LocalName="height") (doc2.Attributes()) with None -> 0. | Some xa -> float xa.Value 194 | let width = Math.Max(width1, width2) 195 | let height = Math.Max(height1, height2) 196 | doc1.SetAttributeValue(XName.Get("width"), width) 197 | doc1.SetAttributeValue(XName.Get("height"), height) 198 | let doc2Objects = doc2.Elements() |> Array.ofSeq; 199 | doc2.RemoveNodes() 200 | doc1.Add(doc2Objects) 201 | let svg = doc1.ToString() 202 | svg -------------------------------------------------------------------------------- /src/IfSharp.Kernel/paket.references: -------------------------------------------------------------------------------- 1 | group NETCORE 2 | 3 | FSharp.Compiler.Service 4 | NetMQ 5 | Newtonsoft.Json 6 | Paket.Core 7 | FSharp.Core 8 | System.Memory -------------------------------------------------------------------------------- /src/IfSharp/Angara.Charting.Dynamic.fsx: -------------------------------------------------------------------------------- 1 | #load ".paket/load/Itis.Angara.Html.fsx" 2 | 3 | open System 4 | open IfSharp.Kernel 5 | open IfSharp.Kernel.Globals 6 | open FSharp.Control 7 | open Angara.Charting 8 | open Angara.Serialization 9 | open Newtonsoft.Json 10 | 11 | type DynamicChartPrinter private () = 12 | static let instance = DynamicChartPrinter() 13 | static member Instance : IfSharp.Kernel.IAsyncPrinter = upcast instance 14 | interface IfSharp.Kernel.IAsyncPrinter with 15 | member __.CanPrint value = 16 | let t = value.GetType() 17 | match AsyncDisplay.getAsyncSeqType(t) with 18 | | Some iface -> 19 | iface.GetGenericArguments().[0] = typedefof 20 | | None -> false 21 | member __.Print value isExecutionResult sendExecutionResult sendDisplayData = 22 | let chart_display_id = Guid.NewGuid().ToString() 23 | let data_display_id = Guid.NewGuid().ToString() 24 | let chart_id = Guid.NewGuid().ToString("N") 25 | let aSeq: FSharp.Control.AsyncSeq = value :?> FSharp.Control.AsyncSeq 26 | 27 | let displayDiv = @" 28 |
29 |
30 | 31 | 79 |
" 80 | 81 | sendDisplayData "text/html" displayDiv "display_data" chart_display_id 82 | 83 | 84 | let resolver = SerializerCompositeResolver([CoreSerializerResolver.Instance; Angara.Html.Serializers]) 85 | 86 | let sendUpdatedData (chart:Angara.Charting.Chart) = 87 | let dataJToken = Angara.Serialization.Json.FromObject(resolver,chart) 88 | let dataString = dataJToken.ToString(Formatting.Indented) 89 | let bytes = System.Text.Encoding.UTF8.GetBytes(dataString) 90 | let base64 = System.Convert.ToBase64String(bytes) 91 | // printfn "%s" dataSerialized 92 | let updateDiv = @"
93 | 99 |
" 100 | sendDisplayData "text/html" updateDiv "update_display_data" data_display_id 101 | sendDisplayData "text/html" "
" "display_data" data_display_id 102 | AsyncSeq.iter sendUpdatedData aSeq |> Async.StartImmediate 103 | 104 | IfSharp.Kernel.Printers.addAsyncDisplayPrinter(DynamicChartPrinter.Instance, 20) 105 | -------------------------------------------------------------------------------- /src/IfSharp/Angara.Charting.Paket.fsx: -------------------------------------------------------------------------------- 1 | #load "Paket.fsx" 2 | 3 | Paket.Version 4 | [ "Itis.Angara.Base", "~> 0.3.3" 5 | "Itis.Angara.Html", "~> 0.3.3" 6 | "Angara.Chart", "" 7 | "Itis.Angara.Reinstate", "~> 0.3.3" 8 | "Angara.Serialization", "~> 0.3.0" 9 | "Angara.Serialization.Json", "~> 0.3.0" 10 | "Suave", "~> 1.1.3" 11 | ] 12 | -------------------------------------------------------------------------------- /src/IfSharp/Angara.Charting.fsx: -------------------------------------------------------------------------------- 1 | #r "IfSharp.Kernel.dll" 2 | 3 | #load ".paket/load/Itis.Angara.Base.fsx" 4 | #load ".paket/load/Itis.Angara.Html.fsx" 5 | #load ".paket/load/Angara.Chart.fsx" 6 | #load ".paket/load/Itis.Angara.Table.fsx" 7 | #load ".paket/load/Itis.Angara.Reinstate.fsx" 8 | #load ".paket/load/Angara.Serialization.fsx" 9 | #load ".paket/load/Angara.Serialization.Json.fsx" 10 | 11 | open IfSharp.Kernel 12 | open IfSharp.Kernel.Globals 13 | open Angara.Charting 14 | 15 | Angara.Base.Init() 16 | 17 | Printers.addDisplayPrinter(fun (chart: Chart) -> 18 | { ContentType = "text/html" 19 | Data = Angara.Html.MakeEmbeddable "auto" chart }) 20 | 21 | type Angara.Charting.Chart with 22 | 23 | static member WithHeight (height: int) (chart: Chart) = 24 | { ContentType = "text/html" 25 | Data = Angara.Html.MakeEmbeddable (sprintf "%dpx" height) chart } 26 | -------------------------------------------------------------------------------- /src/IfSharp/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | True 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/IfSharp/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace IfSharp.AssemblyInfo 2 | 3 | open System.Reflection 4 | open System.Runtime.CompilerServices 5 | open System.Runtime.InteropServices 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Build and Revision Numbers 35 | // by using the '*' as shown below: 36 | // [] 37 | [] 38 | [] 39 | 40 | do 41 | () 42 | -------------------------------------------------------------------------------- /src/IfSharp/AsyncDisplay.Paket.fsx: -------------------------------------------------------------------------------- 1 | #load "Paket.fsx" 2 | 3 | Paket.Version ["FSharp.Control.AsyncSeq", "~> 2.0.21"] -------------------------------------------------------------------------------- /src/IfSharp/AsyncDisplay.fsx: -------------------------------------------------------------------------------- 1 | #load ".paket/load/FSharp.Control.AsyncSeq.fsx" 2 | #r "IfSharp.Kernel.dll" 3 | 4 | open System 5 | open FSharp.Control 6 | open System.Reflection 7 | open System.Threading.Tasks 8 | open System.Threading 9 | open System.Text 10 | open FSharp.Control 11 | 12 | /// Returns the AsyncSeq if the passed object is AsyncSeq, None otherwise 13 | let getAsyncSeqType (t:Type) = 14 | if t.IsGenericType then 15 | let targetIface = typedefof> 16 | let isAsyncSeqIface (t:Type) = 17 | if t.IsGenericType && (t.GetGenericTypeDefinition() = targetIface) then Some t else None 18 | match t.GetInterfaces() |> Seq.tryPick isAsyncSeqIface with 19 | | Some iface -> 20 | Some iface 21 | | None -> None 22 | else 23 | None 24 | 25 | /// Adapts the IAsyncEnumerator to IAsyncEnumerator 26 | /// o is IAsyncEnumerator to adapt 27 | /// moveNext is a MethodInfo of o.MoveNext() 28 | /// dispose is o.Dispose() 29 | type AsyncSeqGenEnumerator(o:obj, moveNext:MethodInfo,dispose:unit -> unit) = 30 | interface IAsyncEnumerator with 31 | member __.MoveNext(): Async = 32 | async { 33 | let value = moveNext.Invoke(o,[||]) //returns Async 34 | let t = value.GetType() 35 | // the actual "pooling" of the next value is done in a threadpool thread 36 | // as the thread is temporary blocked by "Task.Result" call 37 | do! Async.SwitchToThreadPool() 38 | 39 | // We are dealing with Async 40 | let argToption = t.GenericTypeArguments.[0] 41 | 42 | let argT = argToption.GenericTypeArguments.[0] 43 | 44 | // Extracting Async.StartAsTask with reflection 45 | let asyncT = typedefof 46 | let methodInfo = asyncT.GetMethod("StartAsTask") 47 | let methodInfo2 = methodInfo.MakeGenericMethod([|argToption|]) 48 | 49 | // And then invoking it 50 | let noneTaskCreationOptions: TaskCreationOptions option = None 51 | let noneCancelationToken: CancellationToken option = None 52 | 53 | let resultTaskObj = methodInfo2.Invoke(null,[|value; noneTaskCreationOptions; noneCancelationToken|]) //Task is returned 54 | 55 | // Extracting Task.Result property accessor 56 | let taskT = typedefof> 57 | let taskT2 = taskT.MakeGenericType([|argToption|]) 58 | let resultExtractor = taskT2.GetProperty("Result") 59 | // And invoking it 60 | let extractedResult = resultExtractor.GetValue(resultTaskObj) //T' option 61 | 62 | if extractedResult = null then 63 | return None 64 | else 65 | let resultType = extractedResult.GetType() 66 | 67 | let optionT = typedefof> 68 | let optionTyped = optionT.MakeGenericType([|argT|]) 69 | 70 | let isSomeMI = optionTyped.GetProperty("IsSome") 71 | 72 | let isSomeRes = isSomeMI.GetValue(null,[|extractedResult|]) :?> bool // bool is returned 73 | if isSomeRes then 74 | let valueExtractor = resultType.GetProperty("Value") 75 | let value = valueExtractor.GetValue(extractedResult) // T' is returned 76 | return Some value 77 | else 78 | return None 79 | } 80 | member __.Dispose() = 81 | dispose() 82 | 83 | /// Adapts IAsyncEnumerable to IAsyncEnumerable 84 | type AsyncSeqGenEnumerable(asyncSeqObj:obj) = 85 | // t is supposed to be IAsyncEnumerable<'t> 86 | interface IAsyncEnumerable with 87 | member __.GetEnumerator() = 88 | let t = asyncSeqObj.GetType() 89 | match getAsyncSeqType(t) with 90 | | Some(iAsyncEnumGen) -> 91 | let enumeratorExtractorGen = iAsyncEnumGen.GetMethod("GetEnumerator") 92 | let enumerator = enumeratorExtractorGen.Invoke(asyncSeqObj,[||]) 93 | 94 | let asyncEnumerator = enumerator.GetType() 95 | let iAsyncEnumerator = asyncEnumerator.GetInterface("IAsyncEnumerator`1") 96 | let moveNextInfo = iAsyncEnumerator.GetMethod("MoveNext") 97 | 98 | let iDisposable = asyncEnumerator.GetInterface("IDisposable") 99 | let disposeInfo = iDisposable.GetMethod("Dispose") 100 | new AsyncSeqGenEnumerator(enumerator,moveNextInfo, fun () -> disposeInfo.Invoke(enumerator,[||]) |> ignore) :> IAsyncEnumerator 101 | | None -> 102 | failwith "asyncSeqObj is supposed to be AsyncSeq<_>" 103 | 104 | /// Prints any Async by computing async in separate thread. Prints resulting 'T using registered (synchronous) printers 105 | type AsyncPrinter private () = 106 | static let instance = AsyncPrinter() 107 | static member Instance : IfSharp.Kernel.IAsyncPrinter = upcast instance 108 | interface IfSharp.Kernel.IAsyncPrinter with 109 | member __.CanPrint value = 110 | let t = value.GetType() 111 | t.IsGenericType && t.GetGenericTypeDefinition() = typedefof> 112 | member __.Print value isExecutionResult sendExecutionResult sendDisplayData = 113 | let t = value.GetType() 114 | let display_id = Guid.NewGuid().ToString() 115 | 116 | let deferredOutput = async { 117 | // This async execution will block the thread when accessing ".Result" of the Task (see below). 118 | // I do such blocking here because attaching task continuation via reflection is too complicated, so simply block the dedicated thread 119 | 120 | // Before switching to a dedicated thread the display placeholder is produced synchronously 121 | // This is done to keep the visual order of "produceOutput" call outputs (in case of several async computations are initiated) in the frontend 122 | let deferredMessage = "(Async is being calculated. Results will appear as they are ready)" 123 | if isExecutionResult then 124 | sendExecutionResult deferredMessage [] display_id 125 | else 126 | sendDisplayData "text/plain" deferredMessage "display_data" display_id 127 | 128 | // the rest is done in dedicated thread 129 | do! Async.SwitchToNewThread() 130 | 131 | // We are dealing with Async 132 | let argT = t.GenericTypeArguments.[0] 133 | 134 | // Extracting Async.StartAsTask with reflection 135 | let asyncT = typedefof 136 | let methodInfo = asyncT.GetMethod("StartAsTask") 137 | let methodInfo2 = methodInfo.MakeGenericMethod([|argT|]) 138 | 139 | // And then invoking it 140 | let noneTaskCreationOptions: TaskCreationOptions option = None 141 | let noneCancelationToken: CancellationToken option = None 142 | 143 | try 144 | let resultTaskObj = methodInfo2.Invoke(null,[|value; noneTaskCreationOptions; noneCancelationToken|]) 145 | 146 | // Extracting Task.Result property accessor 147 | let taskT = typedefof> 148 | let taskT2 = taskT.MakeGenericType([|argT|]) 149 | let resultExtractor = taskT2.GetProperty("Result") 150 | // And invoking it 151 | let extractedResult = resultExtractor.GetValue(resultTaskObj) 152 | 153 | // updating corresponding cell content by printing resulted argT value 154 | let printer = IfSharp.Kernel.Printers.findDisplayPrinter (argT) 155 | let (_, callback) = printer 156 | let callbackValue = callback(extractedResult) 157 | sendDisplayData callbackValue.ContentType callbackValue.Data "update_display_data" display_id 158 | with 159 | | exc -> 160 | sendDisplayData "text/plain" (sprintf "EXCEPTION OCCURRED:\r\n%A" exc) "update_display_data" display_id 161 | } 162 | Async.StartImmediate deferredOutput 163 | 164 | /// Prints any AsyncSeq by pooling elements from it one by one. Updates the output to reflect the most recently computed element. 165 | type AsyncSeqPrinter() = 166 | static let instance = AsyncSeqPrinter() 167 | static member Instance : IfSharp.Kernel.IAsyncPrinter = upcast instance 168 | interface IfSharp.Kernel.IAsyncPrinter with 169 | member __.CanPrint value = 170 | let t = value.GetType() 171 | match getAsyncSeqType t with 172 | | Some _ -> true 173 | | None -> false 174 | member __.Print value isExecutionResult sendExecutionResult sendDisplayData = 175 | let display_id = Guid.NewGuid().ToString() 176 | 177 | let deferredOutput = async { 178 | 179 | let deferredMessage = "(AsyncSeq is being calculated. Results will appear as they are ready)" 180 | if isExecutionResult then 181 | sendExecutionResult deferredMessage [] display_id 182 | else 183 | sendDisplayData "text/plain" deferredMessage "display_data" display_id 184 | 185 | let asyncSeqObj = AsyncSeqGenEnumerable value 186 | 187 | let printer obj1 = 188 | let printer = IfSharp.Kernel.Printers.findDisplayPrinter (obj1.GetType()) 189 | let (_, callback) = printer 190 | let callbackValue = callback(obj1) 191 | 192 | sendDisplayData callbackValue.ContentType callbackValue.Data "update_display_data" display_id 193 | try 194 | do! AsyncSeq.iter printer asyncSeqObj 195 | with 196 | | exc -> 197 | sendDisplayData "text/plain" (sprintf "EXCEPTION OCCURRED:\r\n%A" exc) "update_display_data" display_id 198 | } 199 | Async.StartImmediate deferredOutput 200 | 201 | 202 | IfSharp.Kernel.Printers.addAsyncDisplayPrinter(AsyncPrinter.Instance, 10) 203 | IfSharp.Kernel.Printers.addAsyncDisplayPrinter(AsyncSeqPrinter.Instance, 10) 204 | -------------------------------------------------------------------------------- /src/IfSharp/FSharp.Charting.Gtk.Paket.fsx: -------------------------------------------------------------------------------- 1 | #load "Paket.fsx" 2 | 3 | Paket.Package ["FSharp.Charting.Gtk"] 4 | -------------------------------------------------------------------------------- /src/IfSharp/FSharp.Charting.Gtk.fsx: -------------------------------------------------------------------------------- 1 | [] 2 | module FSharp.Charting 3 | 4 | #I "packages/FSharp.Charting.Gtk/lib/net40" 5 | 6 | #r "FSharp.Compiler.Service.dll" 7 | #r "System.Windows.Forms.DataVisualization.dll" 8 | #r "/usr/lib/cli/gtk-sharp-3.0/gtk-sharp.dll" 9 | #r "/usr/lib/cli/gdk-sharp-3.0/gdk-sharp.dll" 10 | #r "/usr/lib/cli/atk-sharp-3.0/atk-sharp.dll" 11 | #r "/usr/lib/cli/glib-sharp-3.0/glib-sharp.dll" 12 | #r "/usr/lib/mono/4.0/Mono.Cairo.dll" 13 | #r "OxyPlot.dll" 14 | #r "OxyPlot.GtkSharp.dll" 15 | #r "FSharp.Charting.Gtk.dll" 16 | #r "IfSharp.Kernel.dll" 17 | 18 | // Current status 19 | // Modified FSCharting so that it exposes "CopyAsBitmap" 20 | // Build FSCharting in my home dir 21 | // Then install it in Ifsharp 22 | // FSharp.Charting$ cp bin/FSharp.Charting.Gtk.* ../ifsharp/IfSharp_git/bin/packages/FSharp.Charting.Gtk/lib/net40/ 23 | // however, testing in feature notebook 4. 24 | //#I "/home/nmurphy/coding/ifsharp/IfSharp_git/bin" //?why need this? 25 | //#load "FSCharting.Gtk.fsx" 26 | //IfSharp.FSCharting.Initialize() 27 | // FSharp.Charting.Chart.Bar(data) //|> Display 28 | // We get a broken image. 29 | 30 | open System.IO 31 | 32 | open IfSharp.Kernel 33 | open System.Drawing 34 | open System.Drawing.Imaging 35 | open OxyPlot 36 | open OxyPlot.Series 37 | //open GTKSharp 38 | open FSharp.Charting 39 | 40 | type GenericChartWithSize = 41 | { 42 | Chart: ChartTypes.GenericChart; 43 | Size: int * int; 44 | } 45 | type GenericChartsWithSize = 46 | { 47 | Charts: ChartTypes.GenericChart list; 48 | Size: int * int; 49 | Columns: int; 50 | } 51 | 52 | //static member 53 | let MultipleCharts (charts: ChartTypes.GenericChart list) (size:int*int) (cols:int) = 54 | { Charts = charts; Size = size; Columns = cols } 55 | 56 | 57 | type ChartTypes.GenericChart with 58 | /// Wraps a GenericChartWithSize around the GenericChart 59 | member self.WithSize(x:int, y:int) = 60 | { 61 | Chart = self; 62 | Size = (x, y); 63 | } 64 | 65 | /// Converts the GenericChart to a PNG, in order to do this, we must show a form with ChartControl on it, save the bmp, then write the png to memory 66 | member self.ToPng(?size) = 67 | // get the size 68 | let (width, height) = if size.IsNone then (320, 240) else size.Value 69 | 70 | // create a new ChartControl in order to get the underlying Chart 71 | //let ctl = new ChartTypes.ChartControl(self) 72 | 73 | // save 74 | use ms = new MemoryStream() 75 | //let plot = new OxyPlot.GtkSharp.PlotView(Model = self.Model ) 76 | //let bm = self.CopyAsBitmap() 77 | let pngExporter = new OxyPlot.GtkSharp.PngExporter() 78 | pngExporter.Width <- width 79 | pngExporter.Height <- height 80 | pngExporter.Background <- OxyPlot.OxyColors.White 81 | // write to a temporary file 82 | //let tmp = sprintf "%s.png" (System.Guid.NewGuid().ToString()) 83 | pngExporter.Export(self.Model, ms) //tmp, width, height, OxyPlot.OxyColors.White) 84 | //let bytes = File.ReadAllBytes(tmp); 85 | // write to the stream 86 | //stream.Write(bytes, 0, bytes.Length); 87 | // delete the temporary file 88 | //File.Delete(tmp); 89 | 90 | //Export(self.Model, ms, width, height, e, 96) 91 | 92 | //self.Chart.SaveImage(ms, ChartImageFormat.Png |> int |> enum) 93 | 94 | ms.Seek(0L, System.IO.SeekOrigin.Begin) |> ignore 95 | ms.ToArray() 96 | //Bitmap.FromStream ms 97 | //let actualChart = ctl.Controls.[0] :?> System.Windows.Forms.DataVisualization.Charting.Chart 98 | //actualChart.Dock <- DockStyle.None 99 | //actualChart.Size <- Size(width, height) 100 | //actualChart.SaveImage(ms, ImageFormat.Png) 101 | //ms.ToArray() 102 | 103 | member self.ToData(?size) = 104 | let bytes = match size with Some size -> self.ToPng(size) | _ -> self.ToPng() 105 | let base64 = System.Convert.ToBase64String(bytes) 106 | let data = "data:image/png;base64,"+base64 107 | data 108 | 109 | type FSharp.Charting.Chart with 110 | 111 | /// Wraps a GenericChartWithSize around the GenericChart 112 | static member WithSize(x:int, y:int) = 113 | 114 | fun (ch : #ChartTypes.GenericChart) -> 115 | ch.WithSize(x, y) 116 | 117 | do 118 | Printers.addDisplayPrinter(fun (x:ChartTypes.GenericChart) -> 119 | { ContentType = "image/png"; Data = x.ToPng() }) 120 | 121 | // add chart printer 122 | Printers.addDisplayPrinter(fun (x:GenericChartWithSize) -> 123 | { ContentType = "image/png"; Data = x.Chart.ToPng(x.Size) }) 124 | 125 | // add generic chart printer 126 | Printers.addDisplayPrinter(fun (x:ChartTypes.GenericChart) -> 127 | { ContentType = "image/png"; Data = x.ToPng() }) 128 | 129 | // add chart printer 130 | Printers.addDisplayPrinter(fun (x:GenericChartWithSize) -> 131 | { ContentType = "image/png"; Data = x.Chart.ToPng(x.Size) }) 132 | 133 | 134 | Printers.addDisplayPrinter(fun (x:GenericChartsWithSize) -> 135 | let count = x.Charts.Length 136 | let (width, height) = x.Size 137 | let totalWidth = if count = 1 then width else width * x.Columns 138 | let numRows = int (System.Math.Ceiling (float count / float x.Columns)) 139 | let totalHeight = numRows * height 140 | let finalBitmap = new Bitmap(totalWidth, totalHeight) 141 | let finalGraphics = Graphics.FromImage(finalBitmap) 142 | let copy i (chart:ChartTypes.GenericChart) = 143 | let img = chart.ToPng(x.Size) 144 | let bitmap = new Bitmap(new MemoryStream(img)) 145 | finalGraphics.DrawImage(bitmap, i % x.Columns * width, i / x.Columns * height) 146 | List.iteri copy x.Charts; 147 | finalGraphics.Dispose(); 148 | let ms = new MemoryStream() 149 | //TODO finalBitmap.Save(ms, ImageFormat.Png); 150 | { ContentType = "image/png"; Data = ms.ToArray() } 151 | ) 152 | 153 | Printers.addDisplayPrinter(fun (x:GenericChartsWithSize) -> 154 | let count = x.Charts.Length 155 | let (width, height) = x.Size 156 | let totalWidth = if count = 1 then width else width * x.Columns 157 | let numRows = int (System.Math.Ceiling (float count / float x.Columns)) 158 | let totalHeight = numRows * height 159 | let finalBitmap = new Bitmap(totalWidth, totalHeight) 160 | let finalGraphics = Graphics.FromImage(finalBitmap) 161 | let copy i (chart:ChartTypes.GenericChart) = 162 | let img = chart.ToPng(x.Size) 163 | let bitmap = new Bitmap(new MemoryStream(img)) 164 | finalGraphics.DrawImage(bitmap, i % x.Columns * width, i / x.Columns * height) 165 | List.iteri copy x.Charts; 166 | finalGraphics.Dispose(); 167 | let ms = new MemoryStream() 168 | //TODO finalBitmap.Save(ms, ImageFormat.Png); 169 | { ContentType = "image/png"; Data = ms.ToArray() } 170 | ) 171 | -------------------------------------------------------------------------------- /src/IfSharp/FSharp.Charting.Paket.fsx: -------------------------------------------------------------------------------- 1 | #load "Paket.fsx" 2 | 3 | Paket.Version ["FSharp.Charting", "0.91.1"] -------------------------------------------------------------------------------- /src/IfSharp/FSharp.Charting.fsx: -------------------------------------------------------------------------------- 1 | #r "IfSharp.Kernel.dll" 2 | 3 | #r "System.Windows.Forms.DataVisualization.dll" 4 | #r "packages/FSharp.Charting/lib/net45/FSharp.Charting.dll" 5 | 6 | open FSharp.Charting 7 | open System.IO 8 | 9 | open IfSharp.Kernel 10 | open System.Drawing 11 | open System.Drawing.Imaging 12 | open System.Windows.Forms 13 | 14 | type GenericChartWithSize = 15 | { 16 | Chart: ChartTypes.GenericChart; 17 | Size: int * int; 18 | } 19 | type GenericChartsWithSize = 20 | { 21 | Charts: ChartTypes.GenericChart list; 22 | Size: int * int; 23 | Columns: int; 24 | } 25 | 26 | //static member 27 | let MultipleCharts (charts: ChartTypes.GenericChart list) (size:int*int) (cols:int) = 28 | { Charts = charts; Size = size; Columns = cols } 29 | 30 | type ChartTypes.GenericChart with 31 | /// Wraps a GenericChartWithSize around the GenericChart 32 | member self.WithSize(x:int, y:int) = 33 | { 34 | Chart = self; 35 | Size = (x, y); 36 | } 37 | 38 | /// Converts the GenericChart to a PNG, in order to do this, we must show a form with ChartControl on it, save the bmp, then write the png to memory 39 | member self.ToPng(?size) = 40 | // get the size 41 | let (width, height) = if size.IsNone then (320, 240) else size.Value 42 | 43 | // create a new ChartControl in order to get the underlying Chart 44 | let ctl = new ChartTypes.ChartControl(self) 45 | 46 | // save 47 | use ms = new MemoryStream() 48 | let actualChart = ctl.Controls.[0] :?> System.Windows.Forms.DataVisualization.Charting.Chart 49 | actualChart.Dock <- DockStyle.None 50 | actualChart.Size <- Size(width, height) 51 | actualChart.SaveImage(ms, ImageFormat.Png) 52 | ms.ToArray() 53 | 54 | member self.ToData(?size) = 55 | let bytes = match size with Some size -> self.ToPng(size) | _ -> self.ToPng() 56 | let base64 = System.Convert.ToBase64String(bytes) 57 | let data = "data:image/png;base64,"+base64 58 | data 59 | 60 | type FSharp.Charting.Chart with 61 | 62 | /// Wraps a GenericChartWithSize around the GenericChart 63 | static member WithSize(x:int, y:int) = 64 | 65 | fun (ch : #ChartTypes.GenericChart) -> 66 | ch.WithSize(x, y) 67 | 68 | do 69 | Printers.addDisplayPrinter(fun (x:ChartTypes.GenericChart) -> 70 | { ContentType = "image/png"; Data = x.ToPng() }) 71 | 72 | // add chart printer 73 | Printers.addDisplayPrinter(fun (x:GenericChartWithSize) -> 74 | { ContentType = "image/png"; Data = x.Chart.ToPng(x.Size) }) 75 | 76 | // add generic chart printer 77 | Printers.addDisplayPrinter(fun (x:ChartTypes.GenericChart) -> 78 | { ContentType = "image/png"; Data = x.ToPng() }) 79 | 80 | // add chart printer 81 | Printers.addDisplayPrinter(fun (x:GenericChartWithSize) -> 82 | { ContentType = "image/png"; Data = x.Chart.ToPng(x.Size) }) 83 | 84 | 85 | Printers.addDisplayPrinter(fun (x:GenericChartsWithSize) -> 86 | let count = x.Charts.Length 87 | let (width, height) = x.Size 88 | let totalWidth = if count = 1 then width else width * x.Columns 89 | let numRows = int (System.Math.Ceiling (float count / float x.Columns)) 90 | let totalHeight = numRows * height 91 | let finalBitmap = new Bitmap(totalWidth, totalHeight) 92 | let finalGraphics = Graphics.FromImage(finalBitmap) 93 | let copy i (chart:ChartTypes.GenericChart) = 94 | let img = chart.ToPng(x.Size) 95 | let bitmap = new Bitmap(new MemoryStream(img)) 96 | finalGraphics.DrawImage(bitmap, i % x.Columns * width, i / x.Columns * height) 97 | List.iteri copy x.Charts; 98 | finalGraphics.Dispose(); 99 | let ms = new MemoryStream() 100 | finalBitmap.Save(ms, ImageFormat.Png); 101 | { ContentType = "image/png"; Data = ms.ToArray() } 102 | ) 103 | 104 | Printers.addDisplayPrinter(fun (x:GenericChartsWithSize) -> 105 | let count = x.Charts.Length 106 | let (width, height) = x.Size 107 | let totalWidth = if count = 1 then width else width * x.Columns 108 | let numRows = int (System.Math.Ceiling (float count / float x.Columns)) 109 | let totalHeight = numRows * height 110 | let finalBitmap = new Bitmap(totalWidth, totalHeight) 111 | let finalGraphics = Graphics.FromImage(finalBitmap) 112 | let copy i (chart:ChartTypes.GenericChart) = 113 | let img = chart.ToPng(x.Size) 114 | let bitmap = new Bitmap(new MemoryStream(img)) 115 | finalGraphics.DrawImage(bitmap, i % x.Columns * width, i / x.Columns * height) 116 | List.iteri copy x.Charts; 117 | finalGraphics.Dispose(); 118 | let ms = new MemoryStream() 119 | finalBitmap.Save(ms, ImageFormat.Png); 120 | { ContentType = "image/png"; Data = ms.ToArray() } 121 | ) 122 | -------------------------------------------------------------------------------- /src/IfSharp/FsLab.fsx: -------------------------------------------------------------------------------- 1 | #load "Paket.fsx" 2 | Paket.Package [ "FsLab" ] 3 | #load "Paket.Generated.Refs.fsx" 4 | 5 | #load "XPlot.GoogleCharts.fsx" 6 | #load "XPlot.Plotly.fsx" 7 | -------------------------------------------------------------------------------- /src/IfSharp/Paket.Generated.Refs.fsx: -------------------------------------------------------------------------------- 1 | #load @".paket/load/main.group.fsx" -------------------------------------------------------------------------------- /src/IfSharp/Paket.fsx: -------------------------------------------------------------------------------- 1 | #r "IfSharp.Kernel.dll" 2 | #r "Chessie.dll" 3 | #r "Paket.Core.dll" 4 | 5 | open System 6 | open Paket 7 | open Paket.LoadingScripts.ScriptGeneration 8 | 9 | let deps = 10 | let dir = 11 | Reflection.Assembly.GetEntryAssembly().Location 12 | |> IO.Path.GetDirectoryName 13 | 14 | let d = 15 | try 16 | Dependencies.Locate(dir) 17 | with _ -> 18 | Dependencies.Init(dir) 19 | Dependencies.Locate(dir) 20 | 21 | d.Restore(false) 22 | d 23 | 24 | let RootPath = 25 | deps.RootPath 26 | 27 | let private remove_quiet packageName = 28 | deps.Remove( 29 | None, 30 | packageName, 31 | force = false, 32 | interactive = false, 33 | installAfter = false) 34 | 35 | let private add package version = 36 | remove_quiet package 37 | deps.Add( 38 | None, 39 | package, 40 | version, 41 | force = false, 42 | withBindingRedirects = false, 43 | cleanBindingRedirects = false, 44 | createNewBindingFiles = false, 45 | interactive = false, 46 | installAfter = false, 47 | semVerUpdateMode = SemVerUpdateMode.NoRestriction, 48 | touchAffectedRefs = false) 49 | 50 | let Package list = 51 | for package in list do 52 | add package "" 53 | 54 | deps.Install(false) 55 | () 56 | 57 | let private addGitHub repo file version options = 58 | remove_quiet repo 59 | deps.AddGithub( 60 | None, 61 | repo, 62 | file, 63 | version, 64 | options) 65 | 66 | let private getPartOrDefault delimiter s = 67 | let splitBy delimiter (line:string) = Seq.toList (line.Split delimiter) 68 | let splitedByDelimiter = splitBy [|delimiter|] s 69 | if splitedByDelimiter.Length > 1 then 70 | splitedByDelimiter.[0], splitedByDelimiter.[1] 71 | else 72 | splitedByDelimiter.[0], "" 73 | 74 | let private GitHubString gitHubRepoString = 75 | //This RegEx may be overly restrictive a prevent characters, is there are more sustainable way? Does Paket itself have a checker? 76 | let GitHubRepoStringCheck = 77 | System.Text.RegularExpressions.Regex("^[_a-zA-Z\d]+(-[_a-zA-Z\d]+)*/[_a-zA-Z\d\.]+(-[_a-zA-Z\d\.]+)*(:[_a-zA-Z\d\.]+(-[_a-zA-Z\d\.]+)*)?( [_a-zA-Z\d\.]+(-[_a-zA-Z\d\.]+)*(/[_a-zA-Z\d\.]+(-[_a-zA-Z\d\.]+)*)*)*$") 78 | let GitHubRepoStringCheckIsValid (s:string) = GitHubRepoStringCheck.IsMatch s 79 | 80 | if not(GitHubRepoStringCheckIsValid gitHubRepoString) 81 | then raise (System.ArgumentException("GitHub repository string should match the pattern: user/repo[:version][ file]", "GitHubRepoString")) 82 | 83 | 84 | let repo, file, version = 85 | let repoVersion, file = 86 | getPartOrDefault ' ' gitHubRepoString 87 | let repo, version = 88 | getPartOrDefault ':' repoVersion 89 | repo, file, version 90 | 91 | addGitHub repo file version InstallerOptions.Default 92 | deps.Install(false) 93 | () 94 | 95 | let GitHub list = 96 | for repo in list do 97 | GitHubString repo 98 | deps.Install(false) 99 | () 100 | 101 | let private addGit repo version options = 102 | printfn "addGit repo=%s version=%s" repo version 103 | deps.AddGit( 104 | None, 105 | repo, 106 | version, 107 | options) 108 | 109 | let private GitString gitRepoString = 110 | let GitRepoStringCheck = 111 | System.Text.RegularExpressions.Regex("^\S*(\s+\S*)?$") 112 | let GitRepoStringCheckIsValid (s:string) = GitRepoStringCheck.IsMatch s 113 | 114 | if not(GitRepoStringCheckIsValid gitRepoString) 115 | then raise (System.ArgumentException("Git repository string should match the pattern: repo[ version]", "GitRepoString")) 116 | 117 | let repo, version = getPartOrDefault ' ' gitRepoString 118 | addGit repo version InstallerOptions.Default 119 | 120 | deps.Install(false) 121 | () 122 | 123 | let Git list = 124 | for repo in list do 125 | GitString repo 126 | deps.Install(false) 127 | () 128 | 129 | let Version list = 130 | for package, version in list do 131 | add package version 132 | 133 | deps.Install(false) 134 | () 135 | 136 | let Clear() = 137 | //TODO: this currently doesn't remove GitHub packages. Can't find a corresponding Paket api 138 | deps.GetInstalledPackages() |> List.iter (fun (_, package, _) -> remove_quiet package) 139 | add "FSharp.Core" "= 5.0.2" 140 | () 141 | -------------------------------------------------------------------------------- /src/IfSharp/Plotly.NET.fsx: -------------------------------------------------------------------------------- 1 | #r "IfSharp.Kernel.dll" 2 | #r "Plotly.NET.dll" 3 | #r "Plotly.NET.ImageExport.dll" 4 | #r "DynamicObj.dll" 5 | #r "Newtonsoft.Json.dll" 6 | 7 | open Plotly.NET 8 | 9 | open GenericChart 10 | open IfSharp.Kernel 11 | open IfSharp.Kernel.Globals 12 | 13 | open DynamicObj 14 | open Newtonsoft.Json 15 | 16 | 17 | // The following code is modified from Plotly.NET: 18 | (* Copyright 2020 Timo Mühlhaus 19 | 20 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | *) 26 | 27 | // The code is modified in the way that plotly and requirejs are not loaded from the cdn. 28 | // Plotly is inlined, requirejs is already available from jupyter notebooks 29 | let chart = 30 | let newScript = new System.Text.StringBuilder() 31 | newScript.AppendLine("""
""") |> ignore 32 | newScript.AppendLine("") |> ignore 45 | newScript.ToString() 46 | 47 | let toChartHTML gChart = 48 | 49 | 50 | let jsonConfig = JsonSerializerSettings() 51 | jsonConfig.ReferenceLoopHandling <- ReferenceLoopHandling.Serialize 52 | 53 | let guid = System.Guid.NewGuid().ToString() 54 | 55 | let tracesJson = 56 | let traces = GenericChart.getTraces gChart 57 | JsonConvert.SerializeObject(traces, jsonConfig) 58 | 59 | let layoutJson = 60 | let layout = GenericChart.getLayout gChart 61 | JsonConvert.SerializeObject(layout, jsonConfig) 62 | 63 | let configJson = 64 | let config = GenericChart.getConfig gChart 65 | JsonConvert.SerializeObject(config, jsonConfig) 66 | 67 | let displayOpts = GenericChart.getDisplayOptions gChart 68 | 69 | let dims = GenericChart.tryGetLayoutSize gChart 70 | 71 | let width, height = 72 | let w, h = GenericChart.tryGetLayoutSize gChart 73 | w |> Option.defaultValue 600, h |> Option.defaultValue 600 74 | 75 | 76 | 77 | chart.Replace("[WIDTH]", string width) 78 | .Replace("[HEIGHT]", string height) 79 | .Replace("[ID]", guid) 80 | .Replace("[SCRIPTID]", guid.Replace("-", "")) 81 | .Replace("[DATA]", tracesJson) 82 | .Replace("[LAYOUT]", layoutJson) 83 | .Replace("[CONFIG]", configJson) 84 | |> DisplayOptions.replaceHtmlPlaceholders displayOpts 85 | 86 | 87 | do 88 | Printers.addDisplayPrinter(fun (plot: GenericChart.GenericChart) -> 89 | let contentType = "text/html" 90 | let generatedHTML = toChartHTML plot 91 | { ContentType = "text/html"; Data = generatedHTML} 92 | ) 93 | 94 | 95 | // Require plotly inlined to avoid calls to cdn 96 | sprintf 97 | """ 98 | 110 | """ 111 | (System.IO.File.ReadAllText(__SOURCE_DIRECTORY__ + "/plotly-latest.min.js")) 112 | |> Util.Html 113 | |> Display 114 | -------------------------------------------------------------------------------- /src/IfSharp/Program.fs: -------------------------------------------------------------------------------- 1 | open System 2 | open IfSharp.Kernel 3 | open System.Globalization 4 | open System.IO 5 | open Trinet.Core.IO.Ntfs 6 | 7 | //This hidden info can be left behind depending how you unzip a release on Windows, which in turn can break notebook's use of Paket 8 | let ClearAlternativeStreamsWindows() = 9 | let path = System.Reflection.Assembly.GetEntryAssembly().Location 10 | if path <> null then 11 | for filePath in (FileInfo(path).Directory.GetFileSystemInfos()) do 12 | filePath.DeleteAlternateDataStream("Zone.Identifier") |> ignore 13 | 14 | //Move SystemNet so that the mono one is used instead https://github.com/dotnet/corefx/issues/19914 15 | let MoveSystemNetHttp() = 16 | if File.Exists("System.Net.Http.dll") then 17 | printfn("Moving System.Net.Http.dll to Hide.System.Net.Http.dll to workaround https://github.com/dotnet/corefx/issues/19914") 18 | File.Move("System.Net.Http.dll", "Hide.System.Net.Http.dll") 19 | 20 | [] 21 | let main args = 22 | 23 | //This is really useful if you need debug the start-up process 24 | //System.Diagnostics.Debugger.Launch() |> ignore 25 | 26 | if (Environment.OSVersion.Platform <> PlatformID.Unix && Environment.OSVersion.Platform <> PlatformID.MacOSX) then 27 | ClearAlternativeStreamsWindows() 28 | if Type.GetType ("Mono.Runtime") <> null then 29 | MoveSystemNetHttp() 30 | CultureInfo.DefaultThreadCurrentCulture <- CultureInfo.InvariantCulture 31 | CultureInfo.DefaultThreadCurrentUICulture <- CultureInfo.InvariantCulture 32 | App.Start args Config.NetFramework 33 | 0 -------------------------------------------------------------------------------- /src/IfSharp/XPlot.GoogleCharts.Paket.fsx: -------------------------------------------------------------------------------- 1 | #load "Paket.fsx" 2 | 3 | Paket.Version ["XPlot.GoogleCharts", "2.0.0"] -------------------------------------------------------------------------------- /src/IfSharp/XPlot.GoogleCharts.fsx: -------------------------------------------------------------------------------- 1 | #r "IfSharp.Kernel.dll" 2 | 3 | #load @".paket/load/main.group.fsx" 4 | 5 | open IfSharp.Kernel 6 | open IfSharp.Kernel.App 7 | open IfSharp.Kernel.Globals 8 | 9 | do 10 | System.Net.ServicePointManager.SecurityProtocol <- System.Net.SecurityProtocolType.Tls12 11 | use wc = new System.Net.WebClient() 12 | sprintf 13 | """ 14 | 20 | """ 21 | (wc.DownloadString("https://www.gstatic.com/charts/loader.js")) 22 | |> Util.Html 23 | |> Display 24 | 25 | type XPlot.GoogleCharts.GoogleChart with 26 | member __.GetContentHtml() = 27 | let html = __.GetInlineHtml() 28 | html 29 | .Replace ("google.charts.setOnLoadCallback(drawChart);", "google.charts.load('current',{ packages: ['corechart', 'annotationchart', 'calendar', 'gauge', 'geochart', 'map', 'sankey', 'table', 'timeline', 'treemap'], callback: drawChart });") 30 | 31 | type XPlot.GoogleCharts.Chart with 32 | static member Content (chart : XPlot.GoogleCharts.GoogleChart) = 33 | { ContentType = "text/html"; Data = chart.GetContentHtml() } 34 | 35 | AddDisplayPrinter (fun (plot: XPlot.GoogleCharts.GoogleChart) -> { ContentType = "text/html"; Data = plot.GetContentHtml() }) 36 | -------------------------------------------------------------------------------- /src/IfSharp/XPlot.Plotly.Paket.fsx: -------------------------------------------------------------------------------- 1 | #load "Paket.fsx" 2 | 3 | Paket.Version ["XPlot.Plotly", "2.0.0"] -------------------------------------------------------------------------------- /src/IfSharp/XPlot.Plotly.fsx: -------------------------------------------------------------------------------- 1 | #r "IfSharp.Kernel.dll" 2 | 3 | #load @".paket/load/main.group.fsx" 4 | 5 | open XPlot.Plotly 6 | open IfSharp.Kernel 7 | open IfSharp.Kernel.Globals 8 | 9 | do 10 | Printers.addDisplayPrinter(fun (plot: PlotlyChart) -> 11 | { ContentType = "text/html"; Data = plot.GetInlineHtml() }) 12 | 13 | //System.Net.ServicePointManager.SecurityProtocol <- System.Net.SecurityProtocolType.Tls12 14 | //use wc = new System.Net.WebClient() 15 | 16 | sprintf 17 | """ 18 | 49 | """ 50 | //(wc.DownloadString("https://cdn.plot.ly/plotly-latest.min.js")) 51 | (System.IO.File.ReadAllText(__SOURCE_DIRECTORY__ + "/plotly-latest.min.js")) 52 | |> Util.Html 53 | |> Display 54 | 55 | type XPlot.Plotly.PlotlyChart with 56 | 57 | member __.GetPngHtml() = 58 | let html = __.GetInlineHtml() 59 | html 60 | .Replace("Plotly.newPlot(", "Plotly.plot(") 61 | .Replace( 62 | "data, layout);", 63 | "data, layout).then(ifsharpMakePng);") 64 | 65 | member __.GetSvgHtml() = 66 | let html = __.GetInlineHtml() 67 | html 68 | .Replace("Plotly.newPlot(", "Plotly.plot(") 69 | .Replace( 70 | "data, layout);", 71 | "data, layout).then(ifsharpMakeSvg);") 72 | 73 | type XPlot.Plotly.Chart with 74 | 75 | static member Png (chart: PlotlyChart) = 76 | { ContentType = "text/html" 77 | Data = chart.GetPngHtml() 78 | } 79 | 80 | static member Svg (chart: PlotlyChart) = 81 | { ContentType = "text/html" 82 | Data = chart.GetSvgHtml() 83 | } 84 | -------------------------------------------------------------------------------- /src/IfSharp/hide/paket.dependencies: -------------------------------------------------------------------------------- 1 | framework: net48 2 | generate_load_scripts: true 3 | source https://api.nuget.org/v3/index.json 4 | #When changing the default FSharp.Core version make sure to change everywhere e.g. Clear() 5 | nuget FSharp.Core = 5.0.2 -------------------------------------------------------------------------------- /src/IfSharp/paket.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fsprojects/IfSharp/6bca367feb90d98fc83350764f56f965d2afcd91/src/IfSharp/paket.lock -------------------------------------------------------------------------------- /src/IfSharp/paket.references: -------------------------------------------------------------------------------- 1 | FSharp.Compiler.Service 2 | NetMQ 3 | Newtonsoft.Json 4 | Paket.Core 5 | FSharp.Core 6 | Plotly.NET 7 | Plotly.NET.ImageExport 8 | 9 | Trinet.Core.IO.Ntfs 10 | System.Memory 11 | #System.Threading 12 | #System.Runtime -------------------------------------------------------------------------------- /src/IfSharpNetCore/IfSharpNetCore.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | x64 7 | x64 8 | true 9 | 10 | 11 | 12 | PreserveNewest 13 | 14 | 15 | PreserveNewest 16 | 17 | 18 | 19 | PreserveNewest 20 | 21 | 22 | PreserveNewest 23 | 24 | 25 | PreserveNewest 26 | 27 | 28 | PreserveNewest 29 | 30 | 31 | PreserveNewest 32 | 33 | 34 | PreserveNewest 35 | 36 | 37 | PreserveNewest 38 | 39 | 40 | PreserveNewest 41 | 42 | 43 | PreserveNewest 44 | 45 | 46 | PreserveNewest 47 | 48 | 49 | PreserveNewest 50 | 51 | 52 | PreserveNewest 53 | 54 | 55 | PreserveNewest 56 | 57 | 58 | PreserveNewest 59 | 60 | 61 | PreserveNewest 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/IfSharpNetCore/Paket.Generated.Refs.fsx: -------------------------------------------------------------------------------- 1 | #load @".paket/load/netcoreapp2.2/main.group.fsx" -------------------------------------------------------------------------------- /src/IfSharpNetCore/Program.fs: -------------------------------------------------------------------------------- 1 | open System 2 | open IfSharp.Kernel 3 | open System.Globalization 4 | open System.IO 5 | open Trinet.Core.IO.Ntfs 6 | 7 | //This hidden info can be left behind depending how you unzip a release on Windows, which in turn can break notebook's use of Paket 8 | let ClearAlternativeStreamsWindows() = 9 | let path = System.Reflection.Assembly.GetEntryAssembly().Location 10 | if path <> null then 11 | for filePath in (FileInfo(path).Directory.GetFileSystemInfos()) do 12 | filePath.DeleteAlternateDataStream("Zone.Identifier") |> ignore 13 | 14 | [] 15 | let main args = 16 | printfn "IFSharp on .NET Core is experimental! It has known issues." 17 | 18 | //This is really useful if you need debug the start-up process 19 | //System.Diagnostics.Debugger.Launch() |> ignore 20 | 21 | if (Environment.OSVersion.Platform <> PlatformID.Unix && Environment.OSVersion.Platform <> PlatformID.MacOSX) then 22 | ClearAlternativeStreamsWindows() 23 | CultureInfo.DefaultThreadCurrentCulture <- CultureInfo.InvariantCulture 24 | CultureInfo.DefaultThreadCurrentUICulture <- CultureInfo.InvariantCulture 25 | App.Start args Config.NetCore 26 | 0 -------------------------------------------------------------------------------- /src/IfSharpNetCore/XPlot.GoogleCharts.Paket.fsx: -------------------------------------------------------------------------------- 1 | #load "Paket.fsx" 2 | 3 | Paket.Version ["XPlot.GoogleCharts", "2.0.0"] -------------------------------------------------------------------------------- /src/IfSharpNetCore/XPlot.GoogleCharts.fsx: -------------------------------------------------------------------------------- 1 | #r "IfSharp.Kernel.dll" 2 | 3 | #load @".paket/load/netcoreapp2.2/main.group.fsx" 4 | 5 | #r "System.Net" 6 | #r "System.Net.WebClient.dll" 7 | 8 | open IfSharp.Kernel 9 | open IfSharp.Kernel.App 10 | open IfSharp.Kernel.Globals 11 | 12 | do 13 | //System.Net.ServicePointManager.SecurityProtocol <- System.Net.SecurityProtocolType.Tls12 14 | use wc = new System.Net.WebClient() 15 | sprintf 16 | """ 17 | 23 | """ 24 | (wc.DownloadString("https://www.gstatic.com/charts/loader.js")) 25 | |> Util.Html 26 | |> Display 27 | 28 | type XPlot.GoogleCharts.GoogleChart with 29 | member __.GetContentHtml() = 30 | let html = __.GetInlineHtml() 31 | html 32 | .Replace ("google.charts.setOnLoadCallback(drawChart);", "google.charts.load('current',{ packages: ['corechart', 'annotationchart', 'calendar', 'gauge', 'geochart', 'map', 'sankey', 'table', 'timeline', 'treemap'], callback: drawChart });") 33 | 34 | type XPlot.GoogleCharts.Chart with 35 | static member Content (chart : XPlot.GoogleCharts.GoogleChart) = 36 | { ContentType = "text/html"; Data = chart.GetContentHtml() } 37 | 38 | AddDisplayPrinter (fun (plot: XPlot.GoogleCharts.GoogleChart) -> { ContentType = "text/html"; Data = plot.GetContentHtml() }) 39 | -------------------------------------------------------------------------------- /src/IfSharpNetCore/XPlot.Plotly.Paket.fsx: -------------------------------------------------------------------------------- 1 | #load "Paket.fsx" 2 | 3 | Paket.Version ["XPlot.Plotly", "2.0.0"] -------------------------------------------------------------------------------- /src/IfSharpNetCore/XPlot.Plotly.fsx: -------------------------------------------------------------------------------- 1 | #r "IfSharp.Kernel.dll" 2 | 3 | //Make sure to keep consistent with project version 4 | #load @".paket/load/netcoreapp2.2/main.group.fsx" 5 | 6 | open XPlot.Plotly 7 | open IfSharp.Kernel 8 | open IfSharp.Kernel.Globals 9 | 10 | do 11 | Printers.addDisplayPrinter(fun (plot: PlotlyChart) -> 12 | { ContentType = "text/html"; Data = plot.GetInlineHtml() }) 13 | 14 | //System.Net.ServicePointManager.SecurityProtocol <- System.Net.SecurityProtocolType.Tls12 15 | //use wc = new System.Net.WebClient() 16 | 17 | sprintf 18 | """ 19 | 50 | """ 51 | //(wc.DownloadString("https://cdn.plot.ly/plotly-latest.min.js")) 52 | (System.IO.File.ReadAllText(__SOURCE_DIRECTORY__ + "/plotly-latest.min.js")) 53 | |> Util.Html 54 | |> Display 55 | 56 | type XPlot.Plotly.PlotlyChart with 57 | 58 | member __.GetPngHtml() = 59 | let html = __.GetInlineHtml() 60 | html 61 | .Replace("Plotly.newPlot(", "Plotly.plot(") 62 | .Replace( 63 | "data, layout);", 64 | "data, layout).then(ifsharpMakePng);") 65 | 66 | member __.GetSvgHtml() = 67 | let html = __.GetInlineHtml() 68 | html 69 | .Replace("Plotly.newPlot(", "Plotly.plot(") 70 | .Replace( 71 | "data, layout);", 72 | "data, layout).then(ifsharpMakeSvg);") 73 | 74 | type XPlot.Plotly.Chart with 75 | 76 | static member Png (chart: PlotlyChart) = 77 | { ContentType = "text/html" 78 | Data = chart.GetPngHtml() 79 | } 80 | 81 | static member Svg (chart: PlotlyChart) = 82 | { ContentType = "text/html" 83 | Data = chart.GetSvgHtml() 84 | } 85 | -------------------------------------------------------------------------------- /src/IfSharpNetCore/hide/paket.dependencies: -------------------------------------------------------------------------------- 1 | framework: netstandard2.0, netcoreapp2.2 2 | generate_load_scripts: true 3 | storage:none 4 | source https://api.nuget.org/v3/index.json 5 | #When changing the default FSharp.Core version make sure to change everywhere e.g. Clear() 6 | nuget FSharp.Core = 5.0.2 -------------------------------------------------------------------------------- /src/IfSharpNetCore/paket.references: -------------------------------------------------------------------------------- 1 | group NETCORE 2 | 3 | FSharp.Compiler.Service 4 | NetMQ 5 | Newtonsoft.Json 6 | Paket.Core 7 | FSharp.Core 8 | 9 | Trinet.Core.IO.Ntfs 10 | #System.Threading 11 | #System.Runtime --------------------------------------------------------------------------------